Sei sulla pagina 1di 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 4
1.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.1 AHIR V2 Tool-Chain . . . . . . . . . . . . . . . . . . . 5
1.1.2 RIFFA 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.3 Additional tools . . . . . . . . . . . . . . . . . . . . . . 8
1.1.4 Xilinx ISE Design suite . . . . . . . . . . . . . . . . . . 8
1.1.5 Connection of the FPGA Card to the Host Computer . 8
1.2 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 An Example Algorithm and Its Verifiction in Software 11


2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 The Example Algorithm . . . . . . . . . . . . . . . . . . . . . 11
2.3 C Programming of the Example . . . . . . . . . . . . . . . . 12
2.3.1 Program to Specify the Algorithm . . . . . . . . . . . . 12
2.3.2 Program to Design the Test-infrastructure . . . . . . . 13
2.4 Method to Verify the Design in Software Level . . . . . . . . . 15
2.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3 Converting the Example to VHDL and Its Verification 17


3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Use of AHIR V2 Tool-chain: Taking the Design from C to
VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Validation of the New AHIR Generated VHDL . . . . . . . . . 20
3.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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

1
4.4 Use of Xilinx iMPACT: From Bit-file to Physical Hardware on
the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5 Verifying the Hardware on FPGA With RIFFA Testbench 26


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

6 References 31

2
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 algo-
rithm verification at the C level. After successful verification, the AHIR-V2
generated VHDL is mapped to an FPGA target using standard FPGA syn-
thesis 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 hard-
ware 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.

3
Chapter 1

Introduction

We start this pathway by describing algorithms in C. Using a C test infras-


tructure, 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. Addi-
tionaly, 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 Bom-

4
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. In-
side ’Release’ directory, two directories named ’bin’ and ’lin’ must be present.
THe ”bin” directory’s path is added to PATH environment variable, and the
”lib” directory’s 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.

5
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

6
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 ti-


tled riffa-2.0.2. To start installing riffa 2.0, one needs to go to the riffa-
2.0.2/source/driver/linux directory. Inside that directory, the following com-
mand 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 Com-


puter
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 be-


tween 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.

9
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 C-
algorithm 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 test-
infrastructure 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 simultane-
usly. 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 in-
troduced 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 addition-
algorithm 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 in-
put 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 Make-
file. 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 test-
bench 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 Dif-
ferent 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 in-
frastructure. 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 com-
mands 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 synthe-
sizing.(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 consor-
tium 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 de-
noted 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 communica-
tion 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/matt-
jacobsen/riffa/riffa_2_0/c-interface

Clearly, this testbench is somewhat similar to that we described in C. How-


ever, 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 send-
ing 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 <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "timer.h"
#include <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 de-
scribed 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 Hard-


ware 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 integra-
tion framework for FPGA accelerators. Field-Programmable Custom Com-
puting Machines (FCCM), 2012 20th IEEE Annual International Symposium
on, 29 April - 1 May 2012.

31

Potrebbero piacerti anche