Computer Laboratory

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:


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

MPhil ACS Advanced Computer Design

The MPhil Advanced Computer Design course uses Bluespc and you might find the notes and lab sessions to be of interest.

Thacker's Tiny Computer in Bluespec

I've created a Bluespec version of Thacker's Tiny Comptuer.

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:


Many of these examples are available open source from:

Finally, the official Bluespec SystemVerilog documentation is available here (please do not redistribute over the web):


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;

(* 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)
            $display("%05t: do_division enq'd result early",$time);
            running <= False;
   rule do_ending (running && (ra<rb));
      running <= False;
      $display("%05t: do_division enq'd result",$time);
   method Action start(UInt#(16) a, UInt#(16) b) if (!running);
      ra <= a;
      rb <= b;
      d <= 0;
      running <= True;
   method ActionValue#(UInt#(16)) get_result;
      return result_fifo.first;

module mkTestBench(Empty);
   Reg#(UInt#(16)) a <- mkReg(13);
   DividerIfc div <- mkDivider;
   rule do_init (a>=5);
      a <= a-5;
      $display("%05t: started division",$time);
   rule read_result;
      let r <- div.get_result();
      $display("%05t: result = %d",$time,r);
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:
code generation for mkTestBench starts
Elaborated module file created:
All packages are up to date.
bsc -keep-fires -cross-info -sim -o mkTestBench  -e mkTestBench
Bluesim object created: mkTestBench.{h,o}
Bluesim object created: mkDivider.{h,o}
Bluesim object created: schedule.{h,o}
Simulation shared library created:
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