Vous êtes sur la page 1sur 32

Seminar Report

on

A Pathway From C to Hardware

Presented by Prottay M. Adhikari (13307R020)


M. Tech (Electronic Systems)
under the guidance of Prof Madhav P. Desai
Department of Electrical Engineering, Indian Institute of Technology, Bombay

Contents
1 Introduction
1.1 Prerequisites . . . . . . . . . . .
1.1.1 AHIR V2 Tool-Chain . .
1.1.2 RIFFA 2.0 . . . . . . . .
1.1.3 Additional tools . . . . .
1.1.4 Xilinx ISE Design suite .
1.1.5 Connection of the FPGA
1.2 Conclusion . . . . . . . . . . . .
2 An
2.1
2.2
2.3

. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
Card to the
. . . . . . .

. . .
. . .
. . .
. . .
. . .
Host
. . .

. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
Computer
. . . . . .

Example Algorithm and Its Verifiction in Software


Introduction . . . . . . . . . . . . . . . . . . . . . . . . .
The Example Algorithm . . . . . . . . . . . . . . . . . .
C Programming of the Example . . . . . . . . . . . . .
2.3.1 Program to Specify the Algorithm . . . . . . . . .
2.3.2 Program to Design the Test-infrastructure . . . .
2.4 Method to Verify the Design in Software Level . . . . . .
2.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

3 Converting the Example to VHDL and Its Verification


3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Use of AHIR V2 Tool-chain: Taking the Design from C to
VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Validation of the New AHIR Generated VHDL . . . . . . . .
3.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.

4
4
5
7
8
8
8
10

.
.
.
.
.
.
.

11
11
11
12
12
13
15
16

17
. 17
. 17
. 20
. 21

4 From VHDL to Physical Hardware on FPGA


22
4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2 Wrapper Generation for AHIR Generated HDLs . . . . . . . . 22
4.3 Use of FPGA Synthesis Tools: From VHDL Description to
Bit-files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4.4
4.5

Use of Xilinx iMPACT: From Bit-file to Physical Hardware on


the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5 Verifying the Hardware on FPGA With RIFFA Testbench


5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 From the C-Testbench to the Test-infrastructure in RIFFA 2.0
5.3 Validation of the Hardware . . . . . . . . . . . . . . . . . . . .
5.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26
26
26
30
30

6 References

31

Abstract
We describe a complete pathway using which an algorithm described in C can
be implemented in FPGA hardware. The initial specification and verification
of the algorithm is done in C (using standard C-compilers and debuggers).
Once verified, the C description of the algorithm is converted to VHDL using
the AHIR-V2 tool-chain (developed at IIT Bombay). The generated VHDL
is then verified using the same test infrastructure which was used for algorithm verification at the C level. After successful verification, the AHIR-V2
generated VHDL is mapped to an FPGA target using standard FPGA synthesis tools. In this particular case, we use the ML605 card from Xilinx as
the target platform. The ML605 card uses a Virtex 6 FPGA from Xilinx,
and has a PCI-express interface through which it can be connected to a host
computer. In order to communicate between the card and the host computer,
we use the RIFFA 2.0 infrastructure (developed at UCSD). The final hardware implementation of the algorithm can then be accessed from the host
in real-time. We illustrate the entire pathway by taking an application from
the algorithm level to the final hardware level.

Chapter 1
Introduction
We start this pathway by describing algorithms in C. Using a C test infrastructure, those C algorithms are verified(a standard C compiler like gcc is
used). Initial debugging(if required) is also performed at this stage. The next
step is converting those C specifications into VHDL descriptions by AHIR
V2 tool-chain[1]. The same C test infrastructure which was used to verify the
algorithm is again used to validate the AHIR generated VHDL descriptions.
Once validated, those VHDL files are used to make bit-files using standard
FPGA synthesis tools(in this particular case, we used Xilinx XST). Those
bit-files are mapped to a target FPGA (in this case we used ML605 board
which uses a Virtex 6 FPGA) - by using Xilinx iMPACT. Thus, a hardware
is generated on the FPGA from the intial algorithm specified in C. That
hardware is validated using a RIFFA 2.0 test infrastructure. RIFFA 2.0 [2]
connects the core of an FPGA with a software running on host computer,
through PCI-e interface and yields a very high speed communication between
the host computer and the FPGA hardware. Thus the hardware mapped on
FPGA is verified directly from the terminal of the host computer. This entire
pathway was first integrated by Kartik Lakhotia and Sarath M. in 2013.
In this chapter we describe the tools we need before starting with this
path from C to hardware. We also discuss on how to connect the ML605
FPGA card to PCI-e slot of a computer.

1.1

Prerequisites

We need AHIR V2 tool-chain and RIFFA 2.0 installed in our system. Additionaly, Xilinx ISE 13.2 (which includes iMPACT and XST) must be installed
in the system. Some additional tools are also needed, and downloaded as a
package named addonsAHIR from the VLSI consortium website of IIT Bom4

bay (Will be discussed in details later). The ML605 card also needs to be
connected to the host computer thriugh PCI-e interface.

1.1.1

AHIR V2 Tool-Chain

AHIR V2 tool-chain will be used used to generate VHDL descriptions from


C programs. AHIR V2 installation process is illustrated for a system running
on Ubuntu 12.04 operating system.
Installation Prerequisites
Two packages- llvm-2.8, clang-2.8 must be installed before installing AHIR
V2. ( In order to use llvm 2.8, gcc 4.2 is also needed which was already
present in Ubuntu 12.04). All these packages can be downloaded from the
following link.
http://llvm.org/releases/download.html
These packages get downloaded as zip-files. Upon extraction they create two
directories named llvm-2.8 and clang-2.8. clang-2.8 directory is copied
to llvm-2.8/tools directory. The entire llvm-2.8 directory is kept inside a
directory named llvm. Now inside the llvm directory, following commands
are run.
mkdir build
cd build
A build directory is created outside the llvm-2.8 directory. From that
directory the following commands are run.
../llvm-2.8/configure
make
These commands, installs the llvm-2.8 and clang-2.8 packages upon successful
execution. Inside build directory, a directory named Release is created. Inside Release directory, two directories named bin and lin must be present.
THe bin directorys path is added to PATH environment variable, and the
lib directorys path is added to LD-LIBRARY-PATH variable. For that,
bashrc file is opened using following command.
vim ~/.bashrc
Following lines are added to this bashrc file.

PATH=$PATH:/full-path-of-the-bin-directory-as-stated-above
export PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path of bin directory
Thus Clang-2.8 and llvm-2.8 installation is completed. Boost is also required
before installing AHIR V2. To download and install Boost, the following
command is executed.
sudo apt-get install libboost-all-dev
It is also possible to install Boost through Synaptic Package Manager.
Installation Procedure
AHIR V2 is an open source tool available for download from github. The
following command is run to download it from git repository.
git clone https://github.com/madhavPdesai/ahir.git
By this, a directory titled ahir will be created in the workspace which will
contain all necessary files,libraries and scripts. The following commands are
then executed in the given order
cd ahir/v2
source build_bashrc
scons
To make a Release of AHIR V2 in the system, following commands are
to be executed.
cd ahir/v2
make -f ReleaseMakefile
After a release for AHIR V2 is made, the bashrc file needs to be modified.
This file is opened by following command.
vi ~/.bashrc
The following lines are added to this file. The AHIR RELEASE path will
change according to the user-name

export AHIR_RELEASE=/home/the- path-of-the-ahir-release- directory


#in this case the path was /home/pratt/ahir/release
export PATH=$AHIR_RELEASE/bin:$PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/iolib/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/CtestBench/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$AHIR_RELEASE/pipeHandler/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

1.1.2

RIFFA 2.0

RIFFA 2.0 infrastructure is required to test the hardware mapped on FPGA.


Here, RIFFA 2.0 installation process is illustrated for a system running on
Ubuntu 12.04 operating system.
Installation Prerequisites
The system must be using a Linux kernel version 2.6 or higher. If this criteria
is not meet, the operating system must be updated before installing RIFFA
2.0. Since, we are describing the installation preocedure for an Ubuntu
12.04 operating system(that uses kernel version 3.2) no further upgradation
is needed.
Installation Procedure
First, RIFFA 2.0 distribution needs to be downloaded from the following
link.
https://sites.google.com/a/eng.ucsd.edu/matt-jacobsen/riffa/
riffa_2_0/download/
It gets downloaded as a zipfile. Upon extraction, it creates a directory titled riffa-2.0.2. To start installing riffa 2.0, one needs to go to the riffa2.0.2/source/driver/linux directory. Inside that directory, the following command is run to install the kernel headers.
sudo make setup
This command actually installs the kernel headers against the current kernel
version of the operating system. The following commands are then executed.
make
sudo make install
7

These commands build and install the drivers and the libraries. The system
gets configured to load the driver at boot time. It is recommended to reboot
the system once after RIFFA 2.0 driver installation.

1.1.3

Additional tools

Some additional tools are also required to make our AHIR generated designs
compatible with RIFFA interfaces. These tools can be found in the following
link and can be downloaded for free(in tar format). In this package, one script
is also provided to generate bit-files from our HDLs using Xilinx XST. This
entire package is titled as addonsAHIR and can be found in the following
link.
https://www.ee.iitb.ac.in/vlsi/wb/pages/research/completed-projects.php
It is uploaded as a tar file. The tar file is downloaded and extracted. Upon
successful extraction, we will have the all the necessary files ready in our
system.

1.1.4

Xilinx ISE Design suite

Xilinx tools are to be installed in the system. In this case, we used Xilinx
ISE 13.2. Two software tools, XST and iMPACT (which are part of this ISE
Design Suite 13.2) will be needed for our work. The detailed procedure to
install these packages can be found in the official webpage of Xilinx in the
following link.
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_2/iil.pdf

1.1.5

Connection of the FPGA Card to the Host Computer

We used ML605 FPGA card from Xilinx - which has a Virtex-6 FPGA on it.
The detailed documentation on this card can be found in the following link.
http://www.xilinx.com/support/documentation/boards_and_kits/ug534.pdf
It is necessary to go through this detailed documentation before starting to
handle the card. If, the card is being used for the first time, then a series of
tests are to be run. These tests will verify the UART links, the LEDs , the
ethernet interface, the switches, the displays, memories and the timers. A
BIST program is provided by Xilinx, which is used to automatically test all
these things. The details of this test can be found in the document available
in the following link.
8

http://www.xilinx.com/support/documentation/boards_and_kits/ug533.pdf
ML-605 can be connected to host computer through a pcie interface or an
ethernet interface. In this case, we only used the PCI-e interface to connect
this card to the host computer. In figure 1.1, we show the ML605 FPGA
card connected to our system through PCI-e interface.

Figure 1.1: ML605 card connected through PCI-e interface


Although, PCI-e interface provides a high-speed communication link between the FPGA card and the host computer, it can not be not used to
prgram the FPGA. To program the FPGA, we need a JTAG connector.

Figure 1.2: Conncetion between FPGA board and computer through USB
JTAG connector
For ML605 board, Xilinx provides a microUSB JTAG connector- which
we used to program the FPGA. This connector connects the board with the
host computer through an USB 2.0 port as shown in figure 1.2. The long
white connector on the left is the USB JTAG connector.

1.2

Conclusion

In this chapter we have described the overall picture of the current work and
also discussed the software and hardware requirments before starting work.
In the next chapters we will take up an example algorithm and illustrate how
it is taken from C algorithm to FPGA hardware on ML605 board.

10

Chapter 2
An Example Algorithm and Its
Verifiction in Software
2.1

Introduction

In the previous chapter, we have described the tools required to take a Calgorithm to FPGA-based physical hardware(using our scheme). Once, we
have all those tools successfully installed in the system and the FPGA card
is properly connected to the system through PCI-e interface, we are ready to
take an algorithm to FPGA hardware and verify it.
In this chapter, we take up a small example algorithm. Then we explain
how to describe that algorithm in C. We also describe how to write a testinfrastructure in C for our example design. Then we will discuss how to
validate our design with that C test-infrastructure.

2.2

The Example Algorithm

We take an addition-example which reads data from two pipes simultaneusly. Then, the system adds the received data and send the result back to a
pipe. We also need to write a test-infrastructure (in C language) to test this
algorithm. Keeping in mind the fact, that the C-algorithm will be converted
to VHDL by AHIR V2, we need to write this C code in a certain way as
described in the next sections. Moreover, we will need to have provisions in
the test infrastructure for purely software level verifiations of the design. For
that, we used conditional group. Conditional group is the part of code introduced within the #ifdef SW and #endif SW part(In the codes mentioned
in the next sections). That part will be executed as a part of the program if
and only if SW is defined.
11

2.3

C Programming of the Example

In chapter 1, we had created AHIR release. Inside this release directory, we


create a directory named example. Inside this example directory, we create
another directory named src. This src directory will contain our C algorithm
and its testbench. As mentioned, we started by describing an additionalgorithm in C(Inside the src directory said above). We need to write both
the algorithm and its test-infrastructure in C.

2.3.1

Program to Specify the Algorithm

The example algorithm is described by the code written below. In this


case, the system receives data from two pipes named input port 0 and input port 1. It sends the added result to a pipe named output port 1. If
SW is defined, then only it will perform the calculations for software level
verifications.
Inside the recvd() function, data are sent to input port 0 and input port 1
pipes. A function add() is defined before, which adds the received numbers
and sends the result to the pipe output port 0. This add() function is called
inside recvd() function to compute the addition and send the result to pipe
output port 1. The recv function is kept inside a while loop which keeps on
executing. In this particular case, we are sending 20 pairs of 64 bit numbers
and computing the added result for each case.
#include <stdlib.h>
#include <stdint.h>
#include <Pipes.h>
#include <stdio.h>
#include "prog.h"
#define ORDER 20
unsigned int y;
double x1[ORDER],x2[ORDER];
double x3[ORDER];
void recvd()
{
while(1)
{
12

int idx,i;
for( idx=0 ; idx < ORDER ; idx++)
{
x1[idx] = read_float64("input_port_0");
x2[idx] = read_float64("input_port_1");
}
for( i = 0 ; i < ORDER ; i ++ )
{
x3[i]=x1[i] + x2[i];
}
for( idx=0 ; idx<ORDER ; idx++)
{
write_float64("output_port_0",x3[idx]);
}
}
}

2.3.2

Program to Design the Test-infrastructure

The initial verifiaction of the algorithm was carried out in software level. We
designed the following test-infrastructure in C and tested our algorithm with
it.

#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <pthreadUtils.h>
#include <Pipes.h>
#include <pipeHandler.h>
#include "prog.h"
#ifndef SW
#include "vhdlCStubs.h"
#endif
13

#define ORDER 20

#ifdef SW
DEFINE_THREAD(recvd)
#endif
int main(int argc, char* argv[])
{
#ifdef SW
init_pipe_handler();
//The input and output pipes we registered here,
//are of depth 20, and they deal with 64 bit numbers.
register_pipe("input_port_0",20,64,0);
register_pipe("input_port_1",20,64,0);
register_pipe("output_port_0",20,64,0);
PTHREAD_DECL(recvd);
PTHREAD_CREATE(recvd);
#endif
double result[ORDER] ;
uint32_t idx;
uint8_t jdx;
for(idx = 0; idx <ORDER ; idx++)
{
double val = 10*idx ; //we will send multiples of 10
double val2 = 2*idx ; //we will send multiples of 2
write_float64("input_port_0",val); // sent to input_port_0
write_float64("input_port_1",val2); //sent to input_port_1
fprintf(stderr," sent %f %f \n",val,val2);
14

for(idx = 0; idx < ORDER; idx++)


{
result[idx] = read_float64("output_port_0"); //receiving result
fprintf(stdout,"Result = %lf \n", result[idx]);
}
#ifdef SW
PTHREAD_CANCEL(recvd);
close_pipe_handler();
#endif
return(0);
}
In this code, we have written a function Sender 0. This function sends data
through two pipes and receives data back from one pipe. Inside the main
function, this function is called and it sends and receives data. When SW is
defined, the two C programs get executed in parallel and talk to each other.

2.4

Method to Verify the Design in Software


Level

Inside the example directory (as mentioned before) we need to write a Makefile. This Makefile is shown below. To execute the validation process of the
algorithm using the C testbench, we used this Makefile.

#stage 1- The path of some libraries and


#other important files are specified
#AHIR_RELEASE must be an environment variable.
PIPEHANDLER_INCLUDE=$(AHIR_RELEASE)/pipeHandler/include
FUNCTIONLIB=$(AHIR_RELEASE)/functionLibrary/
15

PTHREADUTILS_INCLUDE=$(AHIR_RELEASE)/pthreadUtils/include
SRC=./src
PROGDEFS=
#Stage 2 - this part actually carries out the software level verification
#using gcc compiler.
# -g option enables debugging.
# -c option enables compilation.
# -DSW option enables the use of #ifdef SW segments. These macros will be
#executed only during software level verification, i.e. when SW is defined.
SW: $(SRC)/prog.c $(SRC)/prog.h $(SRC)/testbench.c
gcc -g -c -DSW $(PROGDEFS) -I$(PIPEHANDLER_INCLUDE) -I$(FUNCTIONLIB)/include
-I$(SRC) $(SRC)/prog.c
gcc -g -c -DSW $(PROGDEFS) -I$(PIPEHANDLER_INCLUDE) -I$(PTHREADUTILS_INCLUDE)
-I$(SRC) $(SRC)/testbench.c
gcc -g -o testbench_sw prog.o testbench.o -L$(PIPEHANDLER_LIB) lPipeHandler -lpthread -lriffa
To execute software level verification using that makefile following command
was run from the example directory.
make SW
Upon successful execution, an executable named testbench sw will be created
(in the same working directory from where the make command was run). This
new testbench sw has to be run(using the following command) in order to
carry out the software level verification, and print the results.
./testbench_sw
This executable will run the C algorithm along with its testbench. We can
check the results and verify whether they are accurate.

2.5

Conclusion

In this chapter, we described how to write an example algorithm and its


test-infrastructure in C. We wrote a small example and discussed how to
verify it using C test-infrastructure. In the next chapters, we will convert
this C algorithm into VHDL design and generate hardware on FPGA from
that VHDL design.
16

Chapter 3
Converting the Example to
VHDL and Its Verification
3.1

Introduction

In the last chapter, we described how to write hardware descriptions in C and


verify them in software level. We took an example algorithm, and explained
how to write and test it in software, using a standard C compiler(in our
case gcc). In this chapter, we will show how a C-algorithm is converted to
synthesizable VHDL design using AHIR V2. We will also describe, how to
use the same C- test-bench to validate this AHIR generated VHDL.

3.2

Use of AHIR V2 Tool-chain: Taking the


Design from C to VHDL

Once the software level verification of the algorithm is successful, it is ready


to be converted into VHDL descriptions. AHIR V2 tool chain is used for this
purpose. It converts the C code into VHDL designs in a few steps.
Firstly, the C code is converted to llvm byte code. This llvm byte code
is converted to Aa code. Aa stands for AHIR assembly. A hardware can
be designed in Aa language itself. This Aa code is converted to vc(virtual
circuit) code. Finally, the vc code is converted to VHDL description. Various
optimizations are carried out in each step. To perform this conversion, we
again use the same Makefile. A few more lines are to be added to that
Makefile for hardware level verfication as shown below.

17

#step 1:we declared some paths


in the makefile for Software level verification.
# following paths are added to the list of existing
paths inside the makefile.
#AHIR_RELEASE must be an environment variable .
SOCKETLIB_INCLUDE=$(AHIR_RELEASE)/CtestBench/include
%FUNCTIONLIB=$(AHIR_RELEASE)/functionLibrary/
%PTHREADUTILS_INCLUDE=$(AHIR_RELEASE)/pthreadUtils/include
VHDL_LIB=$(AHIR_RELEASE)/vhdl
SOCKETLIB_LIB=$(AHIR_RELEASE)/CtestBench/lib
#the following lines are added at the end
of the makefile.
LLVM2AAOPTS=-extract_do_while=true --storageinit=true pipedepths=pipedepths.txt
SRC=./src
#TOPMODULES name will change according to the design. In our case
top-most module was named addition.
TOPMODULES=-T addition
#step 2: From C to VHDL ,and its verification
# there are 5 intermediate steps between C files and VHDL designs. Those
five steps will be executed in sequence when HW is defined, as mentioned in
the following line.
HW: c2llvmbc llvmbc2aa aa2vc vc2vhdl vhdlsim
#stage 1 - generation of llvm byte codes from C codes. clang-2.8 is used
in this stage.
c2llvmbc: $(SRC)/prog.c $(SRC)/prog.h
clang -O3 -I/usr/include/i386-linux-gnu -std=gnu89 $(PROGDEFS) I$(SOCKETLIB_INCLUDE) -I$(FUNCTIONLIB)/include -emit-llvm -c $(SRC)/prog.c
opt --indvars --loopsimplify prog.o -o prog.opt.o
llvm-dis prog.opt.o

18

#stage 2 - Generation of AHIR assembly(Aa) codes from llvm byte codes.


llvmbc2aa: prog.opt.o
llvm2aa $(LLVM2AAOPTS)

prog.opt.o | vcFormat >

prog.aa

#stage 3 - From Aa to Virtual Circuit or vc codes generation.


aa2vc: prog.linked.opt.aa
Aa2VC -O -C prog.linked.opt.aa | vcFormat > prog.vc
#stage 4 - vc to VHDL code generation
vc2vhdl: prog.vc
vc2vhdl -O -S 4 -I 2 -v -a -C -e ahir_system -w -s ghdl $(TOPMODULES) -f
prog.vc -L $(FUNCTIONLIB)/fpu.list
vhdlFormat < ahir_system_global_package.unformatted_vhdl >
ahir_system_global_package.vhdl
vhdlFormat < ahir_system.unformatted_vhdl > ahir_system.vhdl
vhdlFormat < ahir_system_test_bench.unformatted_vhdl >
ahir_system_test_bench.vhdl
#stage 5 - We have generated VHDL codes at the end of stage 4. In stage
5, those VHDL codes are tested with the same C testbench which was used
in software level verification. In this stage, a testbench and the GHDL
executable is generated which are used for hardware level verification.
vhdlsim: ahir_system.vhdl ahir_system_test_bench.vhdl $(SRC)
/testbench.c vhdlCStubs.h vhdlCStubs.c
gcc -c vhdlCStubs.c -I$(SRC) -I./ -I$(SOCKETLIB_INCLUDE)
gcc -c $(SRC)/testbench.c -I$(PTHREADUTILS_INCLUDE)
-I$(SRC) -I./ -I$(SOCKETLIB_INCLUDE)
gcc -o testbench_hw testbench.o vhdlCStubs.o
-L$(SOCKETLIB_LIB) -lSocketLib
-lpthread
ghdl --clean
ghdl --remove
ghdl -i --work=GhdlLink $(VHDL_LIB)/GhdlLink.vhdl
ghdl -i --work=ahir $(VHDL_LIB)/ahir.vhdl
ghdl -i --work=aHiR_ieee_proposed $(VHDL_LIB)/aHiR_ieee_proposed.vhdl
ghdl -i --work=work ahir_system_global_package.vhdl
ghdl -i --work=work ahir_system.vhdl
19

ghdl -i --work=work ahir_system_test_bench.vhdl


ghdl -m --work=work -Wl,-L$(SOCKETLIB_LIB)
-Wl,-lVhpi ahir_system_test_bench

In order to generate VHDL descriptions out of C codes and to verify those


AHIR generated VHDL files(by the use of the Makefile as discussed before),
only the following command is to be run from our example directory.
make HW
If this command runs successfully, then ahir VHDL files are generated inside
our working directory(in this case the example directory). One executable
named testbench hw is also created which will be used for the verification of
these newly generated VHDL files.

3.3

Validation of the New AHIR Generated


VHDL

Upon successful execution of the previous commands, we will have a testbench hw executable inside the working directory. To start the verification,
this executable is run by following command.
./testbench_hw
Now, a new terminal is to be opened and from that terminal the ahir system testbench
executable is run by running the following command.
./ahir_system_testbench
In this experiment, actually the AHIR generated VHDL is simulated in
GHDL and the C testbench gets compiled in the standard gcc compiler.
These two processes interact with each other through sockets. This step is
shown in the screenshot below.

20

Figure 3.1: Hardware Simulation of the Design, Two Processes in Two Different Windows Interact with Each-other

3.4

Conclusion

In this chapter, we described how to convert the C algorithm into VHDL


descriptions and how to validate them. In the next chapter we will describe
how to map those validated VHDL descriptions on the FPGA hardware and
test the hardware.

21

Chapter 4
From VHDL to Physical
Hardware on FPGA
4.1

Introduction

In the last chapter, we took the example C algorithm and converted it to


VHDL description. We also showed, how to verify those VHDL desgins. In
this chapter, we will take those VHDL descriptions and generate the bit-file
out of them. We will then map the bit-file on the FPGA to get the physical
hardware.

4.2

Wrapper Generation for AHIR Generated


HDLs

It is to be noted, that our final objective is to validate the physical hardware


on FPGA. We will use RIFFA 2.0 infrastructure for that. But, our AHIR
generated designs are not inherently compatible to be used with RIFFA infrastructure. So, we need to put a wrapper over it. A wrapper sits around
the AHIR cores and provides the communication interfaces to enable it to
be used with RIFFA infrastructures. For this part, we need the additional
tools we kept in the addonAHIR directory(chapter 1, seection 1.1.3). The
wrapper is actually a verilog code which instantiates the ahir logic blocks
in it and helps them connect with the RIFFA interfaces. The user does not
need to write this code, because its generation is automated. To generate
this wrapper file, we need to run the perl script downloaded from the VLSI
Consortium website(as a part of the package addonsAHIR). Following commands are executed.(Here, we assume the package is extracted in a directory

22

named addonsAHIR)
cd addonsAHIR/ahirWrapper_gen
xilperl wrapgen.pl
This will ask for number of pipes and their names before generating the
wrapper. It will also ask for whether it is to be used for communication
through PCI-e interface or ethrnet interface. All these informations are to
be given correctly. The pipe names are as those specified in the C algorithm.
This will generate a verilog code titled chnl tester.v , which is the wrapper.
This file will be used along with the AHIR VHDL files for bit-file generation.

4.3

Use of FPGA Synthesis Tools: From VHDL


Description to Bit-files

Firstly, we need to gather all the necessary HDLs together before synthesizing.(In this case, we will gather all the HDLs inside a directory named
user design. This user designdirectory is kept in the same place with the
synthesis tools of the addonsAHIR package) We need three files to make
the proper bit-file using synthesis tools. The first two files are, the ahir
system.vhdl and ahir system global package.vhdl respectively- which were
created inside the /release/example directory(in this particular case) during
the hardware verification as described in chapter 3. These two files are copied
to a new directory(in this particular case /home/ahir/ahir/fpgaInterface/ml605/user design
directory).
To make this system RIFFA compatible, we will also need the wrapper
for AHIR VHDL descriptions (its generation is discussed in the previous
section). This wrapper is also copied to the user design directory. With
all these files present in the user design directory, one can proceed towards
synthesis and bit-file generation.
We used standard FPGA synthesis tools (in this case, we used Xilinx
XST) to convert our VHDL designs to bit-files. In the existing system,
there is already a perl script by running which we executed this part of the
work(This perl script is also a part of the addonsAHIR package). To run this
perl script in the existing system, following commands were run from the
directory, where we extracted the addonsAHIR(download from VLSI consortium IIT Bombay) package. The detailed directory structure is provided in
the README files inside the addonsAHIR package. The following command
is run to execute this step.
xilperl compile.pl
23

Upon successful execution, a new file named routed.bit will be created inside
synthesis tools/scripts/results directory(inside the addonsAHIR package).

4.4

Use of Xilinx iMPACT: From Bit-file to


Physical Hardware on the FPGA

Since we have our bit-file ready, we need to switch on the ML605 card now
and start working on the card itself. iMPACT is the tool provided by Xilinx,
by which one can upload the configuration file (bit-file) on the FPGA to
generate physical hardware. It is invoked by running the command impact
from the terminal. In the GUI of iMPACT, a new project is to be created.
There is an initialize chain button on the top of the new-project window.
Upon pressing this button, the software is expected to detect the ML605 card
and the FPGA sitting on it if the card is switched on. A screenshot of it is
shown below.

Figure 4.1: The iMPACT software detects the card, Virtex 6 FPGA is denoted by the xc6vlx240t symbol
In the GUI, the software will ask the user to assign configuration files
to the RAM and the FPGA. We shall bypass this step for the RAM. Then,
we need to browse through the file system and chose the newly generated
routed.bit file as the cofiguration file. Then we need to right-click on the
FPGA symbol and program it. Once, the programming is done, the hardware
is generated on the FPGA. However, before starting to use it, we must reboot
our system once (keeping the switch in the ML605 board turned on). Upon
restart, the hardware on FPGA is ready for use and testing.

4.5

Conclusion

In this chapter, we have generated physical hardware from our AHIR VHDL
files generated from some initial C-specifications. This hardware on FPGA
24

needs to be validated. In the next chapter, we will describe how to validate


the hardware on the FPGA using RIFFA 2.0 test-infrastructure.

25

Chapter 5
Verifying the Hardware on
FPGA With RIFFA Testbench
5.1

Introduction

In the end of the last chapter, we had our hardware ready on the FPGA.
This hardware is generated from the initial algorithmic specification in C.
But this hardware is yet not validated. In this chapter, we will describe the
process of writing the RIFFA test-infrastructure and verifying the hardware
using it.

5.2

From the C-Testbench to the Test-infrastructure


in RIFFA 2.0

RIFFA infrastructure provides us with dedicated functions for communication with the FPGA hardware through PCI-e interface. The general structure
of RIFFA testbench is as follows.
#include <stdio.h>
#include <stdlib.h>
#include <riffa.h>
#define BUF_SIZE (1*1024*1024)
unsigned int buf[BUF_SIZE];
int main(int argc, char* argv[]) {
fpga_t * fpga;
26

int fid = 0; // FPGA id


int channel = 0; // FPGA channel
fpga = fpga_open(fid);
fpga_send(fpga, channel, (void *)buf, BUF_SIZE, 0, 1, 0);
fpga_recv(fpga, channel, (void *)buf, BUF_SIZE, 0);
fpga_close(fpga);
return 0;
}
In general, the fpga is opened, some data are sent to it(using fpga send
function), some data are received from it(using fpga recv function), and then
it is closed using fpga close function. The details of these functions, their
uses, and the their arguments are explained in the following link.
https://sites.google.com/a/eng.ucsd.edu/mattjacobsen/riffa/riffa_2_0/c-interface
Clearly, this testbench is somewhat similar to that we described in C. However, read float64 and write float64 functions are replaced by fpga send and
fpga recv functions. In this testbench, the fpga is to be opened before sending data, and closed after receiveing the results. We used two channels in
our test-infrastructure. So, our program was a little more complex than this
one. Our test-infrastructure to validate the addition algorithm is as shown
below.
//RIFFA testbench for addition example.
#include
#include
#include
#include
#include
#include

<iostream>
<stdio.h>
<stdlib.h>
<pthread.h>
"timer.h"
<riffa.h>

using namespace std;


fpga_t * fpga;
int beginSend = 0;
int beginRecv = 0;
27

int end = 0;
int numWords = 80000;
int fid=0;
void * sender_fxn(void *)
{
unsigned int * sendbuf;
unsigned int * sendbuf2;
sendbuf = (unsigned int *)malloc(numWords<<2);
for (int i = 0; i<numWords; i++){
sendbuf[i] = 10*i;
}
sendbuf2 = (unsigned int *)malloc(numWords<<2);
for (int i = 0; i<numWords; i++){
sendbuf2[i] = i;
}
int sent;
int sent2;
while(beginRecv){}
sent = fpga_send(fpga, 0,sendbuf, numWords, 0, 1, 2000);
sent2 = fpga_send(fpga, 1,sendbuf2, numWords, 0, 1, 2000);
beginSend = 1;
for (int i=0; i<10; i++){
cout << "sent word " << i << " is "<< sendbuf[i] << endl;
}
while(!end);
if (sendbuf != NULL)
sendbuf = NULL;
for (int i=0; i<10; i++){
cout << "sent word " << i << " is "<< sendbuf2[i] << endl;
}
while(!end);
if (sendbuf2 != NULL)
sendbuf2 = NULL;
}
void * receiver_fxn(void *){
fpga=fpga_open(fid);
unsigned int * recvbuf;
recvbuf = (unsigned int *)malloc((numWords)<<2);
28

for (int i = 0; i<numWords; i++){


recvbuf[i] = 0;
}
int rc;
while (!beginSend){;};
beginRecv = 1;
rc = fpga_recv(fpga, 0, recvbuf, numWords, 2000);
GET_TIME_VAL(1);
for (int i=0; i<10; i++){
cout << "received word " << i << " is " << recvbuf[i] << endl;
}
if (recvbuf != NULL)
recvbuf = NULL;
}
int main( int argc, const char** argv )
{
pthread_t sender;
pthread_t receiver;
if (argc<2){
fprintf(stderr, "supply fpga number. Format ./tb <index>\n");
return 1;
}
fpga = fpga_open(atoi(argv[1]));
if(fpga == NULL){
cerr << "ERROR: Could not open FPGA " << atoi(argv[1]) << "!" << endl;
return -1;
}
fpga_reset(fpga);
pthread_create(&sender, NULL, sender_fxn, NULL);
pthread_create(&receiver, NULL, receiver_fxn, NULL);
pthread_join(sender, NULL);
pthread_join(receiver, NULL);
fpga_close(fpga);
return 0;
}
We send data through two channels. That part of the test-infrastructure
is scripted inside the sender function. The receiver function receives the
29

computed data. In this particular test-infrastrcture we print first 10 input


and output data-sets for verification.

5.3

Validation of the Hardware

After, programming the FPGA with the bit-file, the system has to be restarted
once (keeping the ML 605 board turned on). Upon restart, the hardware will
be ready to get tested. Then, we need to write the RIFFA testbench as described in the previous section. Once, we have our RIFFA testbench ready, it
is compiled and run to produce an executable. For that, following commands
are to be run.( in this particular clase new edit.cpp is the name of the RIFFA
testbench, and tb will be the name of the generated executable)
g++ -c new_edit.cpp
g++ -o tb new_edit.o -lriffa -lpthread
However, a Makefile can also be written, that contains these two lines. So,
only the make command will be sufficient to build the executable. The
executable(named tb in this case) is run with the command below.
./tb <fpga id>
In our case fpga id is 0. Once, this command is executed, data(as scripted
in the RIFFA testbench) will be sent to the hardware sitting on the FPGA
through PCI-e interface, and the host will receive the computed results from
that hardware. Since, our RIFFA testbench was written with the same data
sets as our initial C test-infrastructure, we expect he results to match with
the results in software simulation and hardware simulation.

5.4

Conclusion

Upon successful validation, we have a working hardware which actually was


specified in C ! Besides designing the hardware in C, initial debugging is
also carried out using C testbenches and C compilers. Since it is easier to
code and debug in C language, designing and debugging of hardware in this
scheme is much easier compared to the traditional methods. Although we
showed the flow of this work with a simple example, this same technique can
be used to design much complex systems.

30

Chapter 6
References
[1] Sahasrabuddhe, S.D. Raja, H. ; Arya, K. ; Desai, M.P. AHIR:A Hardware Intermediate Representation , 20th International Conference on VLSI
Design, pages 245 - 250.6-10 January, 2007.
[2] Jacobsen, M., Freund, Y. and Kastner, R. RIFFA: A reusable integration framework for FPGA accelerators. Field-Programmable Custom Computing Machines (FCCM), 2012 20th IEEE Annual International Symposium
on, 29 April - 1 May 2012.

31

Vous aimerez peut-être aussi