Hls Setup Guide
Hls Setup Guide
1 Introduction
High-level synthesis (HLS) is a hardware design method based on high-level programming
languages. It automatically handles low-level details, focuses on architectural design, and
greatly improves the productivity of hardware development. In this tutorial, you will set
up Vivado HLS [1] on the teaching server, and test your setup by optimizing and running a
provided example.
After enrolling in the class, you will be granted access to the Cornell ECE Linux server. You
can access it from your terminal with the following command:
ssh <NetID>@ecelinux.ece.cornell.edu
with <NetID> replaced with your Cornell account. If you are connected to the campus
network, you can directly log in using the password for your Cornell account. For off-campus
access, you will need to first connect to the Cornell VPN following these instructions.
You will be automatically redirected to a specific node in the cluster, named ecelinux-xx,
where xx ranges from 01 to 20. If the current node is slow or unstable, you can directly ssh
to another node using ssh <NetID>@ecelinux-xx.ece.cornell.edu.
In case you find it challenging to do everything through a plain SSH terminal, you can use
the free Visual Studio Code (VS Code) editor which integrates all functions needed. This
guide provides useful instructions on setting up VS Code with its remote SSH plugin. Once
1
you are logged into the ECE Linux server from VS Code, you should see a user interface: the
“EXPLORER” tab on the left allows you to navigate through the project, the “TERMINAL”
tab at the bottom works exactly as an SSH terminal, and the top right blank region is where
you will be coding.
You will be using Vivado HLS version 2019 for this tutorial. To use it on the ECE Linux
server, you need to source the setup script by running the following command:
source /classes/ece6775/setup-ece6775.sh
You must do it every time you open a new terminal, or you may consider adding it to your
.bashrc to automatically set up the environment on every new terminal you open. Please
note that the setup script runs a module load command, which modifies your environment
to make Vivado HLS available. This might override or conflict with other tools that rely on
different library or executable versions.
You can also create an alias within your .bashrc file so you can easily set up the tools in
the future (v2019 is just for demonstartion, you may use any name you like):
Now, you will just need to type the alias in the terminal to enable the environment.
You can check if the environment is correctly set up by running:
which vivado_hls
/opt/xilinx/Vivado/2019.2/bin/vivado_hls
You are given a zip file named mv-tutorial.zip under /classes/ece6775 on the ECE Linux
server. In your working directory on the server, do:
cp /classes/ece6775/mv-tutorial.zip .
unzip mv-tutorial.zip
cd mv-tutorial
and you will find four files in the project: mv.h, mv.cpp, testbench.cpp, and run.tcl.
2
2.3.1 Header File (mv.h)
The header file contains the declaration of the top-level function, the function that drives
the design at top level. In this case, the top-level function is MV.
1 // mv . h
2 // constant definition and function declaration
3
4 # define N 16
5
6 void MV ( int A [ N ][ N ] , int x [ N ] , int y [ N ]) ;
The source file implements the top-level function and includes the header file.
1 // mv . cpp
2 // original , non - optimized version of matrix - vector multiplication
3
4 # include " mv . h "
5
6 void MV ( int A [ N ][ N ] , int x [ N ] , int y [ N ]) {
7 int i , j ;
8 int acc ;
9 OUTER :
10 for ( i = 0; i < N ; i ++) {
11 acc = 0;
12 INNER :
13 for ( j = 0; j < N ; j ++) {
14 acc += A [ i ][ j ] * x [ j ];
15 }
16 y [ i ] = acc ;
17 }
18 }
The test bench file tests the functionality of your top-level function. It includes the header files
for the functions or directories used within the code and a main() function that bootstraps
the testing of your code. The main() function should return non-zero if it finds an error.
1 // matrix - vector multiply test bench
2
3 # include < stdio .h >
4 # include < cstdlib >
5 # include " mv . h "
6
7 int main () {
8
9 int A [ N ][ N ]; // matrix
10 int x [ N ]; // vector
11 int sw_y [ N ]; // software output , used for testing
3
12 int y [ N ]; // hardware output
13
14 int correct ; // number of correct outputs
15
16 // temporary variables
17 int i , j ;
18 int sw_acc ;
19
20 // initialize input
21 for ( i = 0; i < N ; i ++) {
22 for ( j = 0; j < N ; j ++) {
23 A [ i ][ j ] = rand () % 10;
24 }
25 x [ i ] = rand () % 10;
26 sw_y [ i ] = 0;
27 y [ i ] = 0;
28 }
29
30 // call MV function
31 MV (A , x , y ) ;
32
33 // software result
34 for ( i = 0; i < N ; i ++) {
35 sw_acc = 0;
36 for ( j = 0; j < N ; j ++) {
37 sw_acc += A [ i ][ j ] * x [ j ];
38 }
39 sw_y [ i ] = sw_acc ;
40 }
41
42 // compare and check results
43 correct = 0;
44 for ( i = 0; i < N ; i ++) {
45 if ( y [ i ] == sw_y [ i ])
46 correct ++;
47 else
48 printf ( " [ %4 d ] hw = %6 d , sw = %6 d \ n " , i , y [ i ] , sw_y [ i ]) ;
49 }
50
51 printf ( " \ n \ n \ t \ t % d /% d correct values !\ n \ n \ n " , correct , N ) ;
52
53 if ( correct == N )
54 return 0;
55 else
56 return 1;
57 }
Tcl stands for tool commanding language, which is widely used by CAD tools including
Vivado HLS. The following code is an example script for the matrix-vector multiplication
design in this tutorial:
1 # ===================================================================
4
2 # run.tcl
3 # ===================================================================
4 # @brief: A Tcl script for synthesizing the matrix-vector multiply design.
5 #
6 # @desc: This script launches a simulation & synthesis run
7 #
8 # ------------------------------------------------------
9
10 # open the HLS project
11 open_project -reset mv.prj
12
13 # set the top-level function of the design to be fir
14 set_top MV
15
16 # add design files
17 add_files mv.cpp
18
19 # always add testbench file for cosim
20 add_files -tb testbench.cpp
21
22 open_solution " solution1 "
23
24 # use Zynq device
25 set_part xc7z020clg484-1
26
27 # target clock period is 10 ns
28 create_clock -period 10 -name default
29
30 # do a c simulation
31 csim_design
32
33 # synthesize the design
34 csynth_design
35
36 # do a co-simulation
37 cosim_design
38
39 # exit vivado HLS
40 exit
Note that it includes all building and testing commands in lines 30 - 37; you may not need
all of them in a specific step in this tutorial.
Any Vivado HLS project can be compiled as a regular C++ application. On the ECE Linux
server, you can compile and link the project with GNU Compiler Collection (GCC), by
5
running the command below:
Once the C++ code is compiled and linked properly, a binary output file named matvec gcc
will occur. You may run the binary output file to launch the test bench and obtain results.
This is done by running:
./mv
It is important to note that this tutorial project only involves one source file, one test bench
file, and does not use any HLS-specific libraries. As the project gets more complicated in the
future, you may need to link more files, and include the HLS libraries accordingly.
A better way to deal with complicated projects, especially for those using HLS-specific li-
braries (you will learn about these libraries in upcoming labs), is to utilize an HLS feature
called csim. Csim also treats your design as an C++ application, but it figures out the
libraries on its own as long as you correctly add the source and test bench files in the Tcl
script, as shown in lines 4 - 6 in run.tcl from Section 2.3.4.
The Tcl command to launch csim is csim design, as shown in line 31 in run.tcl. You may
comment out the commands in lines 34 and 37 if you only want to run csim. In the terminal,
run:
vivado_hls -f run.tcl
and you will see the following output among many other info messages from HLS:
...
INFO: [SIM 211-2] *************** CSIM start ***************
INFO: [SIM 211-4] CSIM will launch GCC as the compiler.
Compiling ../../../../testbench.cpp in debug mode
Compiling ../../../../mv.cpp in debug mode
Generating csim.exe
6
INFO: [SIM 211-1] CSim done with 0 errors.
INFO: [SIM 211-3] *************** CSIM finish ***************
...
Csynth refers to the process where the C++ source code is turned into RTL, which is the
main job of HLS. The Tcl command to synthesize your design into RTL is csynth design,
as shown in line 34 in run.tcl from Section 2.3.4. You may comment out the commands in
lines 31 and 37 if you only want to run csynth. In the terminal, run:
vivado_hls -f run.tcl
and you will see the synthesis information printed to the terminal as the tool is running. The
synthesis information is also logged into a file named vivado hls.log.
Once csynth is finished, you can find a MV csynth.rpt file within the report folder of your
project, which should have the following path:
./mv.prj/solution1/syn/report/MV csynth.rpt
The synthesis report shows the estimates of the latency and resource utilization of your
deisgn. It is highly recommended to review the contents of this file to understand the quality
of your design and identify optimization opportunities.
Please save the report elsewhere; you use it as the baseline design when trying out optimiza-
tions later in Section 4.
After having the output RTL as the hardware design, you need to check if it has the correct
functionality, since improper optimizations may cause the hardware to malfunction. To verify
the output RTL, you will utilize the cosim feature of Vivado HLS, which replaces the call to
the top-level function in the test bench with RTL simulation.
To launch cosim, you need to make sure csynth has finished so that there is an RTL to be
vierfied. The Tcl command to run cosim is cosim design, as shown in line 37 in run.tcl from
Section 2.3.4. You may comment out the command in line 31 if you only want to run csynth
and cosim. In the terminal, run:
7
vivado_hls -f run.tcl
and you will see the simulation activity among the output messages:
...
// RTL Simulation : 0 / 1 [0.00%] @ "125000"
// RTL Simulation : 1 / 1 [100.00%] @ "10715000"
...
if the hardware works well, you will also see a success message:
Vivado HLS will measure the actual latency of each call to your top-level function, and
generate a cosim report. For our example, you can find MV cosim.rpt at:
./mv.prj/solution1/sim/report/MV cosim.rpt
It is highly recommended to check the cosim report and compare it with the synthesis report.
8
12 INNER :
13 for ( j = 0; j < N ; j ++) {
14 # pragma HLS unroll factor =2
15 # pragma HLS pipeline II =1
16 acc += A [ i ][ j ] * x [ j ];
17 }
18 y [ i ] = acc ;
19 }
20 }
Please run csynth on the updated project, and compare the report with the baseline. You
should be able to see a decrease in latency and an increase in resource utilization.
Note that it is also possible to add optimization directives in the Tcl script instead of adding
pragmas in the source code. You may also add set directive unroll -factor 2 MV/INNER
and set directive pipeline -II 1 MV/INNER before csynth design in run.tcl to achieve
the same effect as adding pragmas. This technique can be useful when you want to generate
different designs from the same source code.
5 Acknowledgement
This tutorial was created by Yixiao Du, Andrew Butt, George Maidhof, and Matthew Hoff-
man.
9
References
[1] (2023) Vitis hls. [Online]. Available: https://www.xilinx.com/products/design-tools/vit
is/vitis-hls.html
10