ECAD and Architecture Practical Classes
Bluespec SystemVerilog
I have mentioned Bluespec SystemVerilog a couple of times during ECAD lectures. For those feeling adventerous (!), you might like to have a go with Bluespec that I've installed on the PWF Linux here:
/ux/clteach/swm11/bluespec
Before using the tools a few environment variables need to be setup which is easily achived using the following script which needs to be sourced:
source /ux/clteach/swm11/bluespec/setup.bash
Examples and Tutorial Material
I teaching an ACS Masters module on Advanced Computer Design - see the course wiki for some of the material. I've also placed design examples on the PWF here:
/ux/clteach/swm11/bluespec/bluespec-examples
Many of these examples are available open source from: http://www.cl.cam.ac.uk/~swm11/examples/bluespec/
Finally, the official Bluespec SystemVerilog documentation is available here (please do not redistribute over the web):
/ux/clteach/swm11/bluespec/current/doc/BSV
Quick start
Below is a copy of me running the tools in a shell. Note that there are a few comments (look for the # prefix).
soup:~$ source /ux/clteach/swm11/bluespec/setup.bash
soup:~$ mkdir MyFirstBluespec
soup:~$ cd MyFirstBluespec/
soup:MyFirstBluespec$ cp /ux/clteach/swm11/bluespec/DividerExample/Divider.bsv .
soup:MyFirstBluespec$ cat Divider.bsv
import FIFO::*;
interface DividerIfc;
method Action start(UInt#(16) a, UInt#(16) b);
method ActionValue#(UInt#(16)) get_result;
endinterface
(* synthesize *)
module mkDivider(DividerIfc);
Reg#(UInt#(16)) ra <- mkReg(0);
Reg#(UInt#(16)) rb <- mkReg(0);
Reg#(UInt#(16)) d <- mkReg(0);
Reg#(Bool) running <- mkReg(False);
FIFO#(UInt#(16)) result_fifo <- mkLFIFO;
// horibly inefficient divider implementation!
rule do_division (running && (ra>=rb));
let new_ra = ra - rb;
let new_d = d+1;
ra <= new_ra;
d <= new_d;
$display("%05t: do_division... ra=%d rb=%d d=%d",$time,ra,rb,d);
if(new_ra < rb)
begin
$display("%05t: do_division enq'd result early",$time);
result_fifo.enq(new_d);
running <= False;
end
endrule
rule do_ending (running && (ra<rb));
running <= False;
result_fifo.enq(d);
$display("%05t: do_division enq'd result",$time);
endrule
method Action start(UInt#(16) a, UInt#(16) b) if (!running);
ra <= a;
rb <= b;
d <= 0;
running <= True;
endmethod
method ActionValue#(UInt#(16)) get_result;
result_fifo.deq;
return result_fifo.first;
endmethod
endmodule
module mkTestBench(Empty);
Reg#(UInt#(16)) a <- mkReg(13);
DividerIfc div <- mkDivider;
rule do_init (a>=5);
div.start(a,3);
a <= a-5;
$display("%05t: started division",$time);
endrule
rule read_result;
let r <- div.get_result();
$display("%05t: result = %d",$time,r);
endrule
endmodule
soup:MyFirstBluespec$ # now create a makefile to do simulate the testbench
soup:MyFirstBluespec$ makemakefile Divider.bsv mkTestBench
Creating Makefile with top-level package "Divider.bsv" and top-level module "mkTestBench"
soup:MyFirstBluespec$ make run
bsc -keep-fires -cross-info -sim -g mkTestBench -u Divider.bsv
checking package dependencies
compiling Divider.bsv
code generation for mkDivider starts
Elaborated module file created: mkDivider.ba
code generation for mkTestBench starts
Elaborated module file created: mkTestBench.ba
All packages are up to date.
bsc -keep-fires -cross-info -sim -o mkTestBench -e mkTestBench mkTestBench.ba
Bluesim object created: mkTestBench.{h,o}
Bluesim object created: mkDivider.{h,o}
Bluesim object created: schedule.{h,o}
Simulation shared library created: mkTestBench.so
Simulation executable created: mkTestBench
./mkTestBench -m 1500
10: started division
20: do_division... ra= 13 rb= 3 d= 0
30: do_division... ra= 10 rb= 3 d= 1
40: do_division... ra= 7 rb= 3 d= 2
50: do_division... ra= 4 rb= 3 d= 3
50: do_division enq'd result early
60: result = 4
60: started division
70: do_division... ra= 8 rb= 3 d= 0
80: do_division... ra= 5 rb= 3 d= 1
80: do_division enq'd result early
90: result = 2
soup:MyFirstBluespec$ # note that the following C++ files were created and then compiled to form the executable cycle accurate simulation:
soup:MyFirstBluespec$ ls *.cxx
mkDivider.cxx mkTestBench.cxx schedule.cxx
soup:MyFirstBluespec$ make clean
rm -f *.bi *.bo *.ba *.info *.sched *.c *.h *.o *.so mk*.v *~ mkTestBench v95/* >/dev/null
soup:MyFirstBluespec$ # now lets synthesis the Verilog by specifying ModelSim as the simulator (i.e. a Verilog simulator)
soup:MyFirstBluespec$ makemakefile Divider.bsv mkTestBench modelsim
Makefile exists, ok to overwrite? (y/N) y
Creating Makefile with top-level package "Divider.bsv" and top-level module "mkTestBench"
soup:MyFirstBluespec$ # the following verilog files were created:
soup:MyFirstBluespec$ ls -l *.v
-rw-r--r-- 1 swm11 swm11 6411 2010-11-08 11:36 mkDivider.v
-rw-r--r-- 1 swm11 swm11 2750 2010-11-08 11:36 mkTestBench.v
