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