680 likes | 856 Views
Bluespec. Lectures 1 & 2. Contact Information. Satnam Singh Email: satnams@microsoft.com Web: http://research.microsoft.com/~satnams Lecture notes and other Bluespec information: http://cas.ee.ic.ac.uk/~ssingh. Objectives. What is Bluespec? What is the design flow?
E N D
Bluespec Lectures 1 & 2
Contact Information • Satnam Singh • Email: satnams@microsoft.com • Web: http://research.microsoft.com/~satnams • Lecture notes and other Bluespec information: http://cas.ee.ic.ac.uk/~ssingh
Objectives • What is Bluespec? • What is the design flow? • What is it interesting or important? • How is it different from VHDL/Verilog/SystemC/C-to-gate? • What is it good for?
Overview • Lectures 1 & 2: basics about Bluespec rules and their synthesis; examples. • Lectures 3 & 4: Scheduling algorithm for rules; FSM design with Bluespec; Higher-order design with Bluespec
FPGAs as Co-Processors XD2000i FPGA in-socket accelerator for Intel FSB XD2000F FPGA in-socket accelerator for AMD socket F XD1000 FPGA co-processor module for socket 940
Microsoft High Level Synthesis Projects Kiwi: concurrent C# programs for control-oriented applications [Univ. Cambridge] shape analysis: synthesis of dynamic data structures (C) [MPI and CMU] Accelerator/FPGA: synthesis of data parallel programs in C++ [MSR Redmond]
scientific computing data mining search image processing financial analytics opportunity challenge
ray of light Handel-C Esterel SPARK Lola Bluespec Occam System-C ROCC Streams-C CatapultC
Bluespec • Spin-off from MIT • Control language based on a collection of “atomic rules”. • Expression language based on Haskell type system. • Original syntax Haskell based. • Current syntax inspired by System Verilog.
Using Bluespec • bombastic.ee.ic.ac.uk • goliath.ee.ic.ac.uk • Binary: bsc • License: at 27004@ee-fs1.ee.ic.ac.uk (just in case) • Website: bluespec.com • Many thanks to Sam Bayliss for setup help.
Counter.bsv interfaceCounter_Interface; methodint count(); endinterface: Counter_Interface (* synthesize *) modulemkCounter (Counter_Interface); Reg#(int) c <- mkReg (0) ; rule increment (c < 10); c <= c + 1 ; $display("count = %d", c) ; endrule methodint count () = c ; endmodule:mkCounter
Simulatiom $ bsc -sim -u Counter.bsv $ bsc-sim -o mkCounter -e mkCountermkCounter.ba $ ./mkCounter –m 10 count = 0 count = 1 count = 2 count = 3 count = 4 count = 5 count = 6 count = 7 count = 8 count = 9
Verilog $ bsc -verilogCounter.bsv … Verilog file created: mkCounter.v $ vlib work $ vlogmkCounter.v
Interface Rules1_Interface; methodActionsetA (intaV); methodActionsetB (intbV); methodintgetX(); methodintgetY(); endinterface: Rules1_Interface (* synthesize *) module rules1 (Rules1_Interface); Reg#(int) a <- mkRegU ; Reg#(int) b <- mkRegU ; Wire#(int) x <- mkWire ; Wire#(int) y <- mkWire ; rule r1 ; x <= 2 * a ; endrule rule r2 ; y <= 3 * b ; endrule methodActionsetA (intaV); a <= aV ; endmethod: setA methodActionsetB (intbV); b <= bV ; endmethod: setB methodintgetX = x ; methodintgetY = y ; endmodule:rules1 Rules1_Interface setA getX setB getY convert this method into hardware a (din) a (qout) clk b (din) b (qout) clk
// // Generated by Bluespec Compiler, version 2008.06.E (build 14395, 2008-06-30) // // On Mon Dec 13 06:26:27 PST 2010 // // Method conflict info: // Method: setA // Conflict-free: setB, getX, getY // Sequenced before (restricted): setA // // Method: setB // Conflict-free: setA, getX, getY // Sequenced before (restricted): setB // // Method: getX // Conflict-free: setA, setB, getX, getY // // Method: getY // Conflict-free: setA, setB, getX, getY // // // Ports: // Name I/O size props // RDY_setA O 1 const // RDY_setB O 1 const // getX O 32 // RDY_getX O 1 const // getY O 32 // RDY_getY O 1 const // CLK I 1 clock // RST_N I 1 unused // setA_aV I 32 reg // setB_bV I 32 reg // EN_setA I 1 // EN_setB I 1 // // No combinational paths from inputs to outputs // //
module rules1(CLK, RST_N, setA_aV, EN_setA, RDY_setA, setB_bV, EN_setB, RDY_setB, getX, RDY_getX, getY, RDY_getY); input CLK; input RST_N; // action method setA input [31 : 0] setA_aV; inputEN_setA; outputRDY_setA;
// action method setB input [31 : 0] setB_bV; inputEN_setB; outputRDY_setB; // value method getX output [31 : 0] getX; outputRDY_getX; // value method getY output [31 : 0] getY; outputRDY_getY; // signals for module outputs wire [31 : 0] getX, getY; wireRDY_getX, RDY_getY, RDY_setA, RDY_setB; // register a reg [31 : 0] a; wire [31 : 0] a$D_IN; wirea$EN; // register b reg [31 : 0] b; wire [31 : 0] b$D_IN; wireb$EN;
// remaining internal signals wire [63 : 0] _3_MUL_b___d2; // action method setA assignRDY_setA = 1'd1 ; // action method setB assignRDY_setB = 1'd1 ; // value method getX assigngetX = { a[30:0], 1'd0 } ; assignRDY_getX = 1'd1 ; // value method getY assignRDY_getY = 1'd1 ; assigngetY = _3_MUL_b___d2[31:0] ; // register a assigna$D_IN = setA_aV ; assigna$EN = EN_setA ; // register b assignb$D_IN = setB_bV ; assignb$EN = EN_setB ; // remaining internal signals assign _3_MUL_b___d2 = 32'd3 * b ;
always@(posedge CLK) begin if (a$EN) a <= `BSV_ASSIGNMENT_DELAY a$D_IN; if (b$EN) b <= `BSV_ASSIGNMENT_DELAY b$D_IN; end // synopsystranslate_off `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS initial begin a = 32'hAAAAAAAA; b = 32'hAAAAAAAA; end `endif // BSV_NO_INITIAL_BLOCKS // synopsystranslate_on endmodule // rules1
(* synthesize *) module rules2 (Empty) ; Reg#(int) x <- mkReg (0) ; rule r1 ; x <= x + 1 ; endrule rule r2 ; x <= x + 2 ; endrule rule monitor ; $display ("x = %d", x) ; endrule endmodule
$ bsc -verilog Rules2.bsv Warning: "Rules2.bsv", line 2, column 8: (G0010) Rule "r2" was treated as more urgent than "r1". Conflicts: "r2" cannot fire before "r1": calls to x.write vs. x.read "r1" cannot fire before "r2": calls to x.write vs. x.read Warning: "Rules2.bsv", line 6, column 8: (G0021) According to the generated schedule, rule "r1" can never fire. Verilog file created: rules2.v
$ ./rules2 -m 6 x = 0 x = 2 x = 4 x = 6 x = 8
(* synthesize *) module rules3 (Empty) ; Reg#(int) x <- mkReg (0) ; Reg#(Bool) b <- mkReg (False) ; rule toggle ; b <= !b ; endrule rule r1 (b) ; x <= x + 1 ; endrule rule r2 (!b) ; x <= x + 2 ; endrule rule monitor ; $display ("x = %d", x) ; endrule endmodule
(* synthesize *) module rules3 (Empty) ; Reg#(int) x <- mkReg (0) ; Reg#(Bool) b <- mkReg (False) ; rule toggle ; b <= !b ; endrule rule r1 (b) ; x <= x + 1 ; endrule rule r2 (!b) ; x <= x + 2 ; endrule rule monitor ; $display ("x = %d", x) ; endrule endmodule
$ ./rules3 -m 8 x = 0 x = 2 x = 3 x = 5 x = 6 x = 8 x = 9
package DVI_I2C_Init ; importStmtFSM::*; interface I2C_Interface; (* always_ready, always_enabled *) methodActionValue#(bit) sda_out(); (* always_ready, always_enabled *) methodActionsda_in(bit v); (* always_ready, always_enabled *) methodActionValue#(bit) rw(); (* always_ready, always_enabled *) methodActionValue#(bit) scl(); (* always_ready, always_enabled *) methodActionValue#(Bit#(8)) versionID(); endinterface: I2C_Interface
(* synthesize *) module chrontel_i2c_init (I2C_Interface); Reg#(bit) sdax <- mkReg(1) ; Reg#(bit) sda_inx <- mkRegU ; Reg#(bit) sclx <- mkReg(1) ; Reg#(bit) rwx <- mkReg(0) ; // init IOBUF to drive SDA pin Reg#(Bool) initDone <- mkReg(False) ; Reg#(Bit#(8)) versionIDx <- mkReg (0) ; FSMServer#(Bit#(8), Bit#(0)) send_byte_fsm <- mkSendByte (sdax, sclx) ; FSMServer#(Bit#(0), Bit#(8)) recv_byte_fsm <- mkRecvByte (sda_inx, sclx, rwx) ; Bit#(7) deviceID = 'h76 ; Bit#(8) versionReg = 'h4A ; // Result should be 10010101 = 'h95
letdoInit = seq i2c_read (deviceID, versionReg, versionIDx, sdax, sda_inx, sclx, rwx, send_byte_fsm, recv_byte_fsm) ; i2c_write (deviceID, 'h49, 'hc0, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; i2c_write (deviceID, 'h21, 'h09, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; i2c_write (deviceID, 'h1d, 'h46, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; i2c_write (deviceID, 'h36, 'h60, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; i2c_write (deviceID, 'h34, 'h16, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; i2c_write (deviceID, 'h33, 'h08, sdax, sda_inx, sclx, rwx, send_byte_fsm) ; endseq ; letdoInitFSM <- mkFSM (doInit) ; ruleperformInit (!initDone) ; doInitFSM.start ; initDone <= True ; endrule
methodActionValue#(bit) sda_out ; returnsdax ; endmethod methodActionValue#(bit) rw ; returnrwx ; endmethod method Action sda_in (bit v) ; sda_inx <= v ; endmethod methodActionValue#(bit) scl ; returnsclx ; endmethod methodActionValue#(Bit#(8)) versionID ; returnversionIDx ; endmethod endmodule
function Stmt i2c_read (Bit#(7) deviceID, Bit#(8) regToRead, Reg#(Bit#(8)) resultReg, Reg#(bit) sda, Reg#(bit) sda_in, Reg#(bit) scl, Reg#(bit) rw, FSMServer#(Bit#(8), Bit#(0)) send_byte_fsm, FSMServer#(Bit#(0), Bit#(8)) recv_byte_fsm) ; Reg#(Bit#(0)) token = ? ; Stmt i2c_read_statement = seqinitial_condition (sda, scl) ; token <- callServer (send_byte_fsm, {deviceID, 0}) ; do_ack (sda, sda_in, scl, rw) ; token <- callServer (send_byte_fsm, regToRead) ; do_ack (sda, sda_in, scl, rw) ; initial_condition (sda, scl) ; token <- callServer (send_byte_fsm, {deviceID, 1}) ; do_ack (sda, sda_in, scl, rw) ; resultReg <- callServer (recv_byte_fsm, ?) ; do_noack (sda, sda_in, scl, rw) ; stop_condition (sda, scl) ; endseq ; return i2c_read_statement ; endfunction
function Stmtdo_ack (Reg#(bit) sda, Reg#(bit) sda_in, Reg#(bit) scl, Reg#(bit) rw) = seq action rw <= 1 ; // Set SDA pin for input scl <= 0 ; //Pulse SCL sda <= 1 ; endaction scl <= 1 ; // Wait for SDA input to drop to zero await (sda_in == 0) ; scl <= 0 ; rw <= 0 ; // Set SDA pin for output endseq; function Stmtdo_noack (Reg#(bit) sda, Reg#(bit) sda_in, Reg#(bit) scl, Reg#(bit) rw) = seq action rw <= 1 ; // Set SDA pin for input scl <= 0 ; //Pulse SCL sda <= 1 ; endaction scl <= 1 ; scl <= 0 ; rw <= 0 ; // Set SDA pin for output endseq;
interfaceDVI_Colour_Bars_Interface; (* always_ready, always_enabled *) methodActionValue#(Bit#(10)) vga_r(); (* always_ready, always_enabled *) methodActionValue#(Bit#(10)) vga_g(); (* always_ready, always_enabled *) methodActionValue#(Bit#(10)) vga_b(); (* always_ready, always_enabled *) methodActionValue#(bit) vga_hs(); (* always_ready, always_enabled *) methodActionValue#(bit) vga_vs(); (* always_ready, always_enabled *) methodActionValue#(bit) vga_blank(); (* always_ready, always_enabled *) methodActionValue#(bit) vga_sync(); endinterface: DVI_Colour_Bars_Interface
(* synthesize *) module mkDVI_Colour_bars (DVI_Colour_Bars_Interface) ; Reg#(bit) vga_hsx <- mkReg(0) ; Reg#(bit) vga_vsx <- mkReg(0) ; Reg#(int) col <- mkReg (0) ; Reg#(int) row <- mkReg (0) ; Reg#(Bit#(10)) vga_rx <- mkReg (0) ; Reg#(Bit#(10)) vga_gx <- mkReg (0) ; Reg#(Bit#(10)) vga_bx <- mkReg (0) ; Reg#(Bool) resetDone <- mkReg (False) ; Reg#(Bool) valid_h <- mkReg (False) ; Reg#(Bool) valid_v <- mkReg (False) ; inth_pixels_width = 640 ; inth_pixels_front_porch = 16 ; inth_pixels_sync = 96 ; inth_pixels_back_porch = 48 ; inth_pixels_total = h_pixels_width + h_pixels_front_porch + h_pixels_sync + h_pixels_back_porch ; intv_pixels_height = 480 ; intv_pixels_front_porch = 10 ; intv_pixels_sync = 2 ; intv_pixels_back_porch = 33 ; intv_pixels_total = v_pixels_height + v_pixels_front_porch + v_pixels_sync + v_pixels_back_porch ;
// Perform a reset by setting row and col to zero rule performReset (!resetDone) ; col <= 0 ; row <= 0 ; resetDone <= True ; endrule // Compute valid_h and valid_v rule compute_valid ; valid_h <= col < h_pixels_width ; valid_v <= row < v_pixels_height ; endrule // Advance row and col rule advance_row_and_col ; if (col == h_pixels_total - 1) begin if (row == v_pixels_total - 1) row <= 0 ; else row <= row + 1 ; col <= 0 ; end else col <= col + 1 ; endrule
// Generate HSYNC rule generate_hsync ; if (col < h_pixels_width + h_pixels_front_porch || col > h_pixels_width + h_pixels_front_porch + h_pixels_sync) vga_hsx <= 1 ; else vga_hsx <= 0 ; endrule // Generate VSYNC rule generate_vsync ; if (row < v_pixels_height + v_pixels_front_porch || row > v_pixels_height + v_pixels_front_porch + v_pixels_sync) vga_vsx <= 1 ; else vga_vsx <= 0 ; endrule
// Red bar rule red_bar (valid_v && valid_h && col < 100) ; vga_rx <= 'h3FF ; vga_gx <= 0 ; vga_bx <= 0 ; endrule // Green bar rule green_bar (valid_v && valid_h && col >= 100 && col < 200) ; vga_rx <= 0 ; vga_gx <= 'h3FF ; vga_bx <= 0 ; endrule // Blue bar rule blue_bar (valid_v && valid_h && col >= 200 && col < 300) ; vga_rx <= 0 ; vga_gx <= 0 ; vga_bx <= 'h3FF ; endrule // Yellow bar rule x1_bar (valid_v && valid_h && col >= 300 && col < 400) ; vga_rx <= 'h3FF ; vga_gx <= 'h3FF ; vga_bx <= 0 ; endrule
JTAG & RS232 RAMP BEE3 System 8 GB DDR2 8 GB DDR2 GB Ethernet FPGA XCVLX110T FPGA XCVLX110T Host PC images commands 8 GB DDR2 8 GB DDR2 images 8 GB DDR2 8 GB DDR2 FPGA XCVLX110T FPGA XCVLX110T 8 GB DDR2 8 GB DDR2 images
Class of synchronous FIFOs interfaceSyncFIFOIfc #(typea_type) ; methodActionenq (a_typesendData ) ; methodActiondeq () ; methoda_type first () ; methodBoolnotFull () ; methodBoolnotEmpty () ; endinterface modulemkSyncFIFOFromCC #(Integer depth, Clock dClkIn) (SyncFIFOIfc #(a_type)) SyncFIFOIfc#(Bit#(8)) fifo_in <- mkSyncFIFOFromCC (2000, clientClock) ;
SyncFIFOCountIfc interfaceSyncFIFOCountIfc#(type element_type, numeric type fifoDepth) ; methodActionenq ( element_typesendData ) ; methodActiondeq () ; methodelement_type first () ; methodBoolsNotFull ; methodBoolsNotEmpty ; methodBooldNotFull ; methodBooldNotEmpty ; methodUInt#(TLog#(TAdd#(fifoDepth,1))) sCount; methodUInt#(TLog#(TAdd#(fifoDepth,1))) dCount; method Action sClear; method Action dClear; endinterface
mkSyncFIFOCount SyncFIFOCountIfc#(Bit#(8), 2048) fifo_out <- mkSyncFIFOCount (clientClock, clientReset, currentClock) ;