Bluepsec Examples
Fib. Servers
Overview
The following code presents a collection of implementations of modules which compute Fibonacci numbers. The first version is iterative (i.e. it takes multiple cycles). Then there are two versions which create ROMs at compile time using Bluespec's powerful static elaboration system. The ROM versions produce a result in a single cycle but the ROM size obviously grows with the bit-width of the input variable. The ROM versions produce particularly nice Verilog, particularly when one considers that so much static elaboration was done to produce it. Some simple test cases are also provided.
The code
/*****************************************************************************
Examples of Fibonnaci Servers
=============================
Simon Moore, January 2010
*****************************************************************************/
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import Vector::*;
/*****************************************************************************
Iterative Fib Server
*****************************************************************************/
// specialisation of Server interface for Fib
typedef Server#(UInt#(width), UInt#(TMul#(width,4)))
FibServerT#(numeric type width);
module mkFibServer(FibServerT#(width))
provisos (Add#(a__, width, TMul#(width, 4)));
Reg#(UInt#(TMul#(width,4))) a <- mkRegU;
Reg#(UInt#(TMul#(width,4))) b <- mkRegU;
Reg#(UInt#(TMul#(width,4))) j <- mkRegU;
Reg#(Bool) active <- mkReg(False);
FIFO#(UInt#(TMul#(width,4))) result_fifo <- mkLFIFO;
rule loop (active && (j>1));
a <= a+b;
b <= a;
j <= j-1;
endrule
rule the_end (active && (j==1));
result_fifo.enq(a);
active <= False;
endrule
rule n_is_zero (active && (j==0));
result_fifo.enq(0);
active <= False;
endrule
interface Put request;
method Action put(n) if (!active);
j <= extend(n);
a <= 1;
b <= 0;
active <= True;
endmethod
endinterface
interface response = toGet(result_fifo);
endmodule
// simple test code for the above
module mkTestFibServer(Empty);
FibServerT#(8) fib <- mkFibServer;
Reg#(UInt#(8)) n <- mkReg(0);
FIFO#(UInt#(8)) inputs <- mkSizedFIFO(4);
rule loop (n <= 20);
n <= n+1;
fib.request.put(n);
inputs.enq(n);
endrule
rule display_results;
let r <- fib.response.get();
inputs.deq;
$display("%05t: result of fib(%2d)=%d",
$time, inputs.first, r);
endrule
endmodule
/*****************************************************************************
Recursive and iterative functions for Fib used in static elaboration
*****************************************************************************/
function Integer fib_func(Integer n);
if(n<2) return n;
else return fib_func(n-1)+fib_func(n-2);
endfunction
function Integer fib_func_iterative(Integer n);
if(n<2) return n;
else
begin
Integer a=1;
Integer b=1;
for(Integer j=2; j<n; j=j+1)
begin
a=a+b;
b=a-b;
end
return a;
end
endfunction
module mkTestFibFunc(Empty);
rule do_fib;
$display("Output fib results on one cycle");
for(Integer n=0; n<10; n=n+1)
begin
Integer f = fib_func(n);
$display("%05t: result of fib(%1d)=%d",
$time, n, fromInteger(f));
end
$finish();
endrule
endmodule
/*****************************************************************************
Fib in ROM
==========
Fib. numbers stored in ROMs generated during static elaboration
(i.e. at compile time). Arrays and vectors are demonstrated.
*****************************************************************************/
module mkFibServerROM(FibServerT#(width))
provisos (Add#(width,TMul#(width,3),TMul#(width,4)));
FIFO#(UInt#(TMul#(width,4))) result_fifo <- mkLFIFO;
UInt#(width) index=0;
UInt#(TMul#(width,4)) rom[valueOf(TExp#(width))];
for(Integer n=0; inLiteralRange(index,n); n=n+1)
rom[fromInteger(n)] = fromInteger(fib_func(n));
interface Put request;
method Action put(n);
result_fifo.enq(rom[n]);
endmethod
endinterface
interface response = toGet(result_fifo);
endmodule
module mkFibServerROMvectors(FibServerT#(width))
provisos (Add#(width,TMul#(width,3),TMul#(width,4)));
Vector#(TExp#(width), Wire#(UInt#(TMul#(width,4)))) rom <- replicateM(mkBypassWire);
FIFO#(UInt#(TMul#(width,4))) result_fifo <- mkLFIFO;
UInt#(width) index=0;
rule init_rom;
for(Integer n=0; inLiteralRange(index,n); n=n+1)
rom[fromInteger(n)] <= fromInteger(fib_func_iterative(n));
endrule
interface Put request;
method Action put(n);
result_fifo.enq(rom[n]);
endmethod
endinterface
interface response = toGet(result_fifo);
endmodule
// make a test ROM
`define romwidth 4
module mkTestFibServerROM(Empty);
FibServerT#(`romwidth) fib <- mkFibServerROM;
Reg#(UInt#(`romwidth)) n <- mkReg(1);
FIFO#(UInt#(`romwidth)) inputs <- mkSizedFIFO(`romwidth);
rule loop (n!=0);
n <= n+1;
fib.request.put(n);
inputs.enq(n);
endrule
rule display_results;
let r <- fib.response.get();
inputs.deq;
$display("%05t: result of fib(%2d)=%d",
$time, inputs.first, r);
endrule
endmodule
// make a synthesized version
(* synthesize *)
module mkFibServerROM4(FibServerT#(4));
FibServerT#(4) fibserver <- mkFibServerROM;
interface request = fibserver.request;
interface response = fibserver.response;
endmodule
Link to the FibServer.bsv source