Computer Laboratory

Course pages 2015–16

Advanced Computer Design

Exercise 1 - Cambridge Bluespec Web Tutor

  • Begin by learning the Bluespec hardware description language by completing the Cambridge Bluespec Tutor.
  • Then work through the Bluespec walk through.
  • Finally, simulate on your local Linux box the GCD Server code that you wrote as an exercise in the web tutor. You might like to use the following test bench (or the updated version at the bottom of the page).
package GcdTest;

import Gcdserver::*;
import GetPut::*;
import ClientServer::*;
import FIFO::*;

module mkGcdTest(Empty);

  Reg#(UInt#(8))           a <- mkReg(1);
  Reg#(UInt#(8))           b <- mkReg(1);
  GcdIfc                 gcd <- mkGcdServer;
  FIFO#(Bit#(64)) start_time <- mkSizedFIFO(8);

  rule testInputs(a<16);
    $display("%04t: Test input: (%2d,%2d)", $time, a, b);
    gcd.calculate.request.put(GcdT{a:a, b:b});
    Bit#(64) t <- $time;
    start_time.enq(t);
    if(b<15)
      b <= b+1;
    else
      begin
	b <= 1;
	a <= a+1;
      end
  endrule

  rule testOutputs;
    Bit#(64) t <- $time;
    t = t - start_time.first;
    start_time.deq;
    $display("%04t:\t\t\t\tTest output: Result %2d \tcycles=%2d", $time, gcd.calculate.response.get(), t/10);
  endrule

endmodule

endpackage : GcdTest

Assessment

Demonstrate that you understand your GCD code and were able to simulate it on a Linux machine.

Optional Extra

To find out more about the power of Bluespec, take a look at the ServerFarm example and try instantiating two copies of your GCD server vis:

GCDServerT#(`width) divServ <- mkServerFarm(2,mkGCDServer);

What performance improvements do you see?

Note: mkServerFarm uses higher-order types, i.e. you can pass a function as a variable. Try doing that in Verilog or VHDL!

Alternative test bench

Here is an alternative test bench which forwards the test input to the testOutput rule so that the inputs and outputs can be displayed more neatly together.

package GcdTest;

import Gcdserver::*;
import GetPut::*;
import ClientServer::*;
import FIFO::*;

typedef struct {
   UInt#(8)  a;
   UInt#(8)  b;
   Bit#(64)  start_time;
   } TestInputT deriving (Bits,Eq);

module mkGcdTest(Empty);

  Reg#(UInt#(8))           a <- mkReg(1);
  Reg#(UInt#(8))           b <- mkReg(1);
  GcdIfc                 gcd <- mkGcdServer;
  FIFO#(TestInputT)   testIn <- mkSizedFIFO(8);

  rule testInputs(a<16);
    gcd.calculate.request.put(GcdT{a:a, b:b});
    Bit#(64) t <- $time;
    testIn.enq(TestInputT{a:a, b:b, start_time:t});
    if(b<15)
      b <= b+1;
    else
      begin
	b <= 1;
	a <= a+1;
      end
  endrule

  rule testOutputs;
    Bit#(64) t <- $time;
    t = t - testIn.first.start_time;
    $display("%04t: Test input = (%2d,%2d)   Output result = %2d   cycles taken = %2d",
       $time,
       testIn.first.a, testIn.first.b,
       gcd.calculate.response.get(), t/10);
    testIn.deq;
  endrule

endmodule

endpackage : GcdTest