Slide 1MotivationTesting the IP Lookup DesignTesting IP LookupBut we usually want more counters, display, ...Writing a Testbench (Case 1)A more complicated Case: Initializing memoryInitialize a memory with a 2-D patternAn imperative viewFrom Action Lists to FSMsThe Stmt SublanguageTranslation Example: Seq to FSMParallel TasksStart ref and dut at the same timeWhat exactly is the translation?Base Case: Primitive Action: aSequential List - seqImplementation - parImplementation - ifImplementation - whileThe StmtFSM libraryFSM atomicityFSM AtomicityFSM summaryStmt FSMRichard S. UhlerComputer Science & Artificial Intelligence LabMassachusetts Institute of Technology(based on a lecture prepared by Arvind)March 7, 2011L10-1http://csg.csail.mit.edu/6.375MotivationSome common design patterns are tedious to express in BSVTestbenchsSequential machines (FSMs)especially sequential looping structuresThese are tedious to express in Verilog as well (but not in C)March 7, 2011L10-2http://csg.csail.mit.edu/6.375Testing the IP Lookup DesignInput: IP AddressOutput: Route ValueNeed to test many different input/output sequencesdone?done?RAMfifoentergetResultoutQcbufyesnogetTokenMarch 7, 2011L10-3http://csg.csail.mit.edu/6.375Testing IP LookupCall many streams of requests responses from the device under test (DUT)Case 1dut.enter(17.23.12.225)dut.getResult()dut.enter(17.23.12.25)dut.getResult()Case 2dut.enter(128.30.90.124)dut.enter(128.30.90.126)dut.getResult()dut.getResult()Check correct with 1 request at a timeCheck correct with 2 concurrent requestsMarch 7, 2011L10-4http://csg.csail.mit.edu/6.375But we usually want morecounters, display, ...function Action makeReq(x); action reqCnt <= reqCnt + 1; dut.enter(x); $display(“[Req #: ”,fshow(reqCnt),“] = ”,fshow(x)); endactionendfunctionfunction Action getResp(); action resCnt <= resCnt + 1; let x <- dut.getResult(); $display(“[Rsp #:”,fshow(resCnt),“] = ”,fshow(x)); endactionendfunction March 7, 2011L10-5http://csg.csail.mit.edu/6.375Writing a Testbench (Case 1)rule step0(pos==0); makeReq(17.23.12.225); pos <= 1;endrulerule step1(pos==1); getResp(); pos <= 2;endrulerule step2(pos==2); makeReq(17.23.12.25); pos <= 3;endrulerule step3(pos==3); getResp(); pos <= 4;endrulerule finish(pos==4); $finish;endruleA lot of text!Wait until response is readyHow should we do it for a sequence of 100 actions?March 7, 2011L10-6http://csg.csail.mit.edu/6.375A more complicated Case: Initializing memoryf(i)nIiaddr0int i; Addr addr=addr0;bool done = False;for(i=0; i<nI; i++){ mem.write(addr++,f(i));}done = True;CNeed an FSM in HW as memory can only do one write per cycleReg#(int) i <-mkReg(0);Reg#(Addr) addr <-mkReg(addr0);Reg#(Bool) done <-mkReg(False);rule initialize (i < nI); mem.write (addr, f(i)); addr <= addr + 1; i <= i + 1; if (i+1 == nI) done<=True;endruleBSVMarch 7, 2011L10-7http://csg.csail.mit.edu/6.375Initialize a memory with a 2-D patternReg#(int) i <-mkReg(0);Reg#(int) j <-mkReg(0);Reg#(Addr) addr <-mkReg(addr0);Reg#(Bool) done <-mkReg(False);rule loop ((i < nI) && (j < nJ)); mem.write (addr, f(i,j)); addr <= addr + 1; if (j < nJ-1) j <= j + 1; else begin j <= 0; if (i < nI-1) i <= i + 1; else done <= True; endendrulef(i,j)nJnIijaddr0Bluespec code gets messier as compared to C even with small changes in C, e.g.,initialization based on old memory valuesinitialization has to be done more than onceShall we do triply-nested loops?March 7, 2011L10-8http://csg.csail.mit.edu/6.375An imperative viewvoid doTest(){ makeReq(17.23.12.225); getResp(); makeReq(17.23.12.25); getResp(); exit(0);}seq makeReq(17.23.12.225); getResp(); makeReq(17.23.12.25); getResp(); $finish();endseq; It is easy to write a sequence in C Writing this in rules is tedious:Can we just write the actions and have the compiler make the rules?March 7, 2011L10-9http://csg.csail.mit.edu/6.375From Action Lists to FSMsFSM interfaceCreating an FSMinterface FSM; method Action start(); method Bool done();endinterfacemodule mkFSM#(Stmt s)(FSM);Stmt sdonestartMarch 7, 2011L10-10http://csg.csail.mit.edu/6.375The Stmt SublanguageStmt = <Bluespec Action>| seq s1..sN endseq | par s1..sN endpar| if-then / if-then-else| for-, while-, repeat(n)-(w/ break and continues)BSV ActionSequence of StmtList of Parallel StmtsConditional StmtsLoop StmtsMarch 7, 2011L10-11http://csg.csail.mit.edu/6.375Translation Example: Seq to FSMStmt s = seq makeReq(17.23.12.225); getResp(); makeReq(17.23.12.25); getResp(); $finish();endseq;FSM f <- mkFSM(s);module mkFSM_s(FSM) Reg#(Bit#(3)) pos <- mkReg(0); rule step1(pos==1); makeReq(17.23.12.225); pos <= 2; endrule rule step2(pos==2); getResp(); pos <= 3; endrule rule step3(pos==3); makeReq(17.23.12.25); pos <= 4; endrule rule step4(pos==4); getResp(); pos <= 5; endrule rule step5(pos==5); $finish; pos <= 0; endrule method Action start() if(pos==0); pos <= 1; endmethod method Bool done() return (pos == 0); endmethodendmoduleMarch 7, 2011L10-12http://csg.csail.mit.edu/6.375Parallel Tasksseq refReq(x); refRes(rReg); dutReq(x); dutRes(dReg); checkMatch(rReg,dReg);endseqWe want to check dut and ref have same result Do each, then check resultsBut it doesn’t matter that ref finishes before dut starts…March 7, 2011L10-13http://csg.csail.mit.edu/6.375Start ref and dut at the same timeSeq. for each implementationStart togetherBoth run at own rate Wait until both are doneseq par seq refReq(x); refRes(refv);endseq seq dutReq(x);dutRes(dutv); endseq endpar checkMatch(refv,dutv);endseqMarch 7, 2011L10-14http://csg.csail.mit.edu/6.375What exactly is the translation?The Stmt sublanguage is clearer for the designer; but, what FSM do we get?Let’s examine each Stmt Construction case and see how it can be implementedMarch 7, 2011L10-15http://csg.csail.mit.edu/6.375Base Case: Primitive Action: aReg#(Bool) doneR <- mkReg(True);rule dowork(!doneR); a; doneR <= True;endrulemethod Action start() if (doneR); doneR <= False;endmethodmethod Bool done(); return doneR; endmethodMarch 7, 2011L10-16http://csg.csail.mit.edu/6.375Sequential List - seq seq s1...sN endseq: sequential compositionReg#(int) s <- mkReg(0);FSM s1 <- mkFSM (s1); … ; FSM sN <- mkFSM (sN); Bool flag = rule one (s==1); s1.start(); s <= 2; endrulerule two (s==2&& s1.done()); s2.start(); s <= 3; endrule…rule n (s==n && sN-1.done()); sN.start(); s <= 0;
View Full Document