Presentation is loading. Please wait.

Presentation is loading. Please wait.

Modeling Processors Arvind

Similar presentations


Presentation on theme: "Modeling Processors Arvind"— Presentation transcript:

1 Modeling Processors Arvind
Computer Science & Artificial Intelligence Lab Massachusetts Institute of Technology February 18, 2009

2 The Plan Non-pipelined processor Two-stage synchronous pipeline
Two-stage asynchronous pipeline In the rest of the talk, I want to say a little bit more about how to describe hardware as an TRS Next I will explain how to synthesize these operation-centric descriptions. I have a few more design that I can show you in the result section. Finally, I will say a fews things about related work and future work Some understanding of simple processor pipelines is needed to follow this lecture February 18, 2009

3 Instruction set typedef enum {R0;R1;R2;…;R31} RName; typedef union tagged { struct {RName dst; RName src1; RName src2;} Add; struct {RName cond; RName addr;} Bz; struct {RName dst; RName addr;} Load; struct {RName value; RName addr;} Store } Instr deriving(Bits, Eq); typedef Bit#(32) Iaddress; typedef Bit#(32) Daddress; typedef Bit#(32) Value; An instruction set can be implemented using many different microarchitectures February 18, 2009

4 Tagged Unions: Bit Representation
typedef union tagged { struct {RName dst; RName src1; RName src2;} Add; struct {RName cond; RName addr;} Bz; struct {RName dst; RName addr;} Load; struct {RName dst; Immediate imm;} AddImm; } Instr deriving(Bits, Eq); dst src src2 cond addr dst addr dst imm Automatically derived representation; can be customized by the user written pack and unpack functions February 18, 2009

5 Non-pipelined Processor
pc rf CPU fetch & execute iMem dMem module mkCPU#(Mem iMem, Mem dMem)(); Reg#(Iaddress) pc <- mkReg(0); RegFile#(RName, Bit#(32)) rf <- mkRegFileFull(); Instr instr = iMem.read(pc); Iaddress predIa = pc + 1; rule fetch_Execute ... endmodule February 18, 2009

6 Non-pipelined processor rule
Pattern matching rule fetch_Execute (True); case (instr) matches tagged Add {dst:.rd,src1:.ra,src2:.rb}: begin rf.upd(rd, rf[ra]+rf[rb]); pc <= predIa end tagged Bz {cond:.rc,addr:.ra}: begin pc <= (rf[rc]==0) ? rf[ra] : predIa; tagged Load {dest:.rd,addr:.ra}: begin rf.upd(rd, dMem.read(rf[ra])); pc <= predIa; tagged Store {value:.rv,addr:.ra}: begin dMem.write(rf[ra],rf[rv]); pc <= predIa; endcase endrule my syntax rf[r]  rf.sub(r) Assume “magic memory”, i.e. responds to a read request in the same cycle and a write updates the memory at the end of the cycle February 18, 2009

7 The Plan Non-pipelined processor Two-stage synchronous pipeline 
Two-stage asynchronous pipeline In the rest of the talk, I want to say a little bit more about how to describe hardware as an TRS Next I will explain how to synthesize these operation-centric descriptions. I have a few more design that I can show you in the result section. Finally, I will say a fews things about related work and future work February 18, 2009

8 Two-stage Synchronous Pipeline
fetch & decode execute buReg pc rf dMem time t0 t1 t2 t3 t4 t5 t6 t FDstage FD1 FD2 FD3 FD4 FD5 EXstage EX1 EX2 EX3 EX4 EX5 Actions to be performed in parallel every cycle: Fetch Action: Decodes the instruction at the current pc and fetches operands from the register file and stores the result in buReg Execute Action: Performs the action specified in buReg and updates the processor state (pc, rf, dMem) February 18, 2009

9 Instructions & Templates
buReg contains instruction templates, i.e., decoded instructions typedef union tagged { struct {RName dst; RName src1; RName src2} Add; struct {RName cond; RName addr} Bz; struct {RName dst; RName addr} Load; struct {RName value; RName addr} Store; } Instr deriving(Bits, Eq); typedef union tagged { struct {RName dst; Value op1; Value op2} EAdd; struct {Value cond; Iaddress tAddr} EBz; struct {RName dst; Daddress addr} ELoad; struct {Value data; Daddress addr} EStore; } InstTemplate deriving(Eq, Bits); February 18, 2009

10 Fetch & Decode Action Fills the buReg with a decoded instruction
buReg <= newIt(instr); function InstrTemplate newIt(Instr instr); case (instr) matches tagged Add {dst:.rd,src1:.ra,src2:.rb}: return EAdd{dst:rd,op1:rf[ra],op2:rf[rb]}; tagged Bz {cond:.rc,addr:.addr}: return EBz{cond:rf[rc],addr:rf[addr]}; tagged Load {dst:.rd,addr:.addr}: return ELoad{dst:rd,addr:rf[addr]}; tagged Store{value:.v,addr:.addr}: return EStore{value:rf[v],addr:rf[addr]}; endcase endfunction no extra gates! February 18, 2009

11 Execute Action: Reads buReg and modifies state (rf,dMem,pc)
case (buReg) matches tagged EAdd{dst:.rd,src1:.va,src2:.vb}: begin rf.upd(rd, va+vb); pc <= predIa; end tagged ELoad{dst:.rd,addr:.av}: begin rf.upd(rd, dMem.read(av)); tagged EStore{value:.vv,addr:.av}: begin dMem.write(av, vv); tagged EBz {cond:.cv,addr:.av}: if (cv != 0) then pc <= predIa; else begin pc <= av; Invalidate buReg end endcase What does this mean? February 18, 2009

12 Issues with buReg buReg may not always contain an instruction. Why?
fetch & decode execute buReg pc rf dMem buReg may not always contain an instruction. Why? start cycle Execute stage may kill the fetched instructions because of branch misprediction Maybe type to the rescue … Can’t update buReg in two concurrent actions fetchAction; executeAction Fold them together February 18, 2009

13 Synchronous Pipeline first attempt
fetch & decode execute pc rf CPU buReg Synchronous Pipeline first attempt rule SyncTwoStage (True); let instr = iMem.read(pc); let predIa = pc+1; Action fetchAction = action buReg <= Valid newIt(instr); pc <= predIa; endaction; case (buReg) matches … calls fetchAction or puts Invalid in buReg … endcase endcase endrule February 18, 2009

14 Execute case (buReg) matches tagged Valid .it: case (it) matches
fetch & decode execute pc rf CPU buReg Execute case (buReg) matches tagged Valid .it: case (it) matches tagged EAdd{dst:.rd,src1:.va,src2:.vb}: begin rf.upd(rd, va+vb); fetchAction; end tagged ELoad{dst:.rd,addr:.av}: begin rf.upd(rd, dMem.read(av)); fetchAction; end tagged EStore{value:.vv,addr:.av}: begin dMem.write(av, vv); fetchAction; end tagged EBz {cond:.cv,addr:.av}: if (cv != 0) then fetchAction; else begin pc <= av; buReg <= Invalid; end endcase tagged Invalid: fetchAction; Not quite correct! February 18, 2009

15 Pipeline Hazards time t0 t1 t2 t3 t4 t5 t6 t7 . . . .
fetch & decode execute buReg pc rf dMem time t0 t1 t2 t3 t4 t5 t6 t FDstage FD1 FD2 FD3 FD4 FD5 EXstage EX1 EX2 EX3 EX4 EX5 I1 Add(R1,R2,R3) I2 Add(R4,R1,R2) I2 must be stalled until I1 updates the register file time t0 t1 t2 t3 t4 t5 t6 t FDstage FD1 FD2 FD2 FD3 FD4 FD5 EXstage EX1 EX2 EX3 EX4 EX5 February 18, 2009

16 Synchronous Pipeline corrected
fetch & decode execute pc rf CPU buReg Synchronous Pipeline corrected rule SyncTwoStage (True); let instr = iMem.read(pc); let predIa = pc+1; Action fetchAction = action if stallFunc(instr, buReg) then buReg <=Invalid else begin buReg <= Valid newIt(instr); pc <= predIa; end endaction; case (buReg) matches … no change … endcase endcase endrule How do we detect stalls? February 18, 2009

17 The Stall Function function Bool stallFunc (Instr instr,
Maybe#(InstTemplate) mit); case (mit) matches tagged Invalid: return False; tagged Valid .it: case (instr) matches tagged Add {dst:.rd,src1:.ra,src2:.rb}: return (findf(ra,it) || findf(rb,it)); tagged Bz {cond:.rc,addr:.addr}: return (findf(rc,it) || findf(addr,it)); tagged Load {dst:.rd,addr:.addr}: return (findf(addr,it)); tagged Store {value:.v,addr:.addr}: return (findf(v,it) || findf(addr,it)); endcase endfunction This first rule describe what happens in the fetch of this pipeline. This rules says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this rule can fire forever, but because bf is bounded, when a rule enqueue into bf, there is an implied predicate that say bf must not be full. February 18, 2009 8 8 8 6

18 The findf function function Bool findf (RName r, InstrTemplate it);
case (it) matches tagged EAdd{dst:.rd,op1:.v1,op2:.v2}: return (r == rd); tagged EBz {cond:.c,addr:.a}: return (False); tagged ELoad{dst:.rd,addr:.a}: tagged EStore{value:.v,addr:.a}: endcase endfunction February 18, 2009

19 Synchronous Pipelines
Notoriously difficult to get right Imagine the cases to be analyzed if it was a five stage pipeline Difficult to refine for better clock timing Asynchronous pipelines February 18, 2009

20 The Plan Non-pipelined processor Two-stage synchronous pipeline
Two-stage asynchronous pipeline  In the rest of the talk, I want to say a little bit more about how to describe hardware as an TRS Next I will explain how to synthesize these operation-centric descriptions. I have a few more design that I can show you in the result section. Finally, I will say a fews things about related work and future work February 18, 2009

21 Processor Pipelines and FIFOs
pc rf fetch decode execute memory write- back iMem dMem CPU It is better to think in terms of FIFOs as opposed to pipeline registers. February 18, 2009

22 SFIFO (glue between stages)
interface SFIFO#(type t, type tr); method Action enq(t); // enqueue an item method Action deq(); // remove oldest entry method t first(); // inspect oldest item method Action clear(); // make FIFO empty method Bool find(tr); // search FIFO endinterface n enab enq rdy not full n = # of bits needed to represent the values of type “t“ m = # of bits needed values of type “tr" enab rdy deq SFIFO module not empty n first not empty rdy enab more on searchable FIFOs later clear bool m find February 18, 2009

23 Two-Stage Pipeline module mkCPU#(Mem iMem, Mem dMem)(Empty);
fetch & decode execute pc rf CPU bu module mkCPU#(Mem iMem, Mem dMem)(Empty); Reg#(Iaddress) pc <- mkReg(0); RegFile#(RName, Bit#(32)) rf <- mkRegFileFull(); SFIFO#(InstTemplate, RName) bu <- mkSFifo(findf); Instr instr = iMem.read(pc); Iaddress predIa = pc + 1; InstTemplate it = bu.first(); rule fetch_decode ... endmodule This first method describe what happens in the fetch of this pipeline. This methods says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this method can fire forever, but because bf is bounded, when a method enqueue into bf, there is an implied predicate that say bf must not be full. February 18, 2009 8 8 8 6

24 Rules for Add CPU implicit check: pc rf fetch & decode execute bu
rule decodeAdd(instr matches Add{dst:.rd,src1:.ra,src2:.rb}) bu.enq (EAdd{dst:rd,op1:rf[ra],op2:rf[rb]}); pc <= predIa; endrule implicit check: This first method describe what happens in the fetch of this pipeline. This methods says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this method can fire forever, but because bf is bounded, when a method enqueue into bf, there is an implied predicate that say bf must not be full. bu notfull rule executeAdd(it matches EAdd{dst:.rd,op1:.va,op2:.vb}) rf.upd(rd, va + vb); bu.deq(); endrule bu notempty February 18, 2009 8 8 8 6

25 Fetch & Decode Rule: Reexamined
execute pc rf CPU bu rule decodeAdd (instr matches Add{dst:.rd,src1:.ra,src2:.rb}) bu.enq (EAdd{dst:rd, op1:rf[ra], op2:rf[rb]}); pc <= predIa; endrule This first method describe what happens in the fetch of this pipeline. This methods says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this method can fire forever, but because bf is bounded, when a method enqueue into bf, there is an implied predicate that say bf must not be full. Wrong! Because instructions in bu may be modifying ra or rb stall ! February 18, 2009 8 8 8 6

26 Fetch & Decode Rule: corrected
execute pc rf CPU bu rule decodeAdd (instr matches Add{dst:.rd,src1:.ra,src2:.rb} bu.enq (EAdd{dst:rd, op1:rf[ra], op2:rf[rb]}); pc <= predIa; endrule &&& !bu.find(ra) &&& !bu.find(rb)) This first method describe what happens in the fetch of this pipeline. This methods says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this method can fire forever, but because bf is bounded, when a method enqueue into bf, there is an implied predicate that say bf must not be full. February 18, 2009 8 8 8 6

27 Rules for Branch CPU rule-atomicity ensures that pc update, and
fetch & decode execute pc rf CPU bu rule-atomicity ensures that pc update, and discard of pre- fetched instrs in bu, are done consistently rule decodeBz(instr matches Bz{cond:.rc,addr:.addr}) &&& !bu.find(rc) &&& !bu.find(addr)); bu.enq (EBz{cond:rf[rc],addr:rf[addr]}); pc <= predIa; endrule This first method describe what happens in the fetch of this pipeline. This methods says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this method can fire forever, but because bf is bounded, when a method enqueue into bf, there is an implied predicate that say bf must not be full. rule bzTaken(it matches EBz{cond:.vc,addr:.va}) &&& (vc==0)); pc <= va; bu.clear(); endrule rule bzNotTaken (it matches EBz{cond:.vc,addr:.va}) &&& (vc != 0)); bu.deq; endrule February 18, 2009 8 8 8 6

28 Fetch & Decode Rule rule fetch_and_decode (!stallFunc(instr, bu));
bu.enq(newIt(instr)); pc <= predIa; endrule function InstrTemplate newIt(Instr instr); case (instr) matches tagged Add {dst:.rd,src1:.ra,src2:.rb}: return EAdd{dst:rd,op1:rf[ra],op2:rf[rb]}; tagged Bz {cond:.rc,addr:.addr}: return EBz{cond:rf[rc],addr:rf[addr]}; tagged Load {dst:.rd,addr:.addr}: return ELoad{dst:rd,addr:rf[addr]}; tagged Store{value:.v,addr:.addr}: return EStore{value:rf[v],addr:rf[addr]}; endcase endfunction Same as before February 18, 2009

29 The Stall Signal Bool stall = stallFunc(instr, bu);
function Bool stallFunc (Instr instr, SFIFO#(InstTemplate, RName) bu); case (instr) matches tagged Add {dst:.rd,src1:.ra,src2:.rb}: return (bu.find(ra) || bu.find(rb)); tagged Bz {cond:.rc,addr:.addr}: return (bu.find(rc) || bu.find(addr)); tagged Load {dst:.rd,addr:.addr}: return (bu.find(addr)); tagged Store {value:.v,addr:.addr}: return (bu.find(v)) || bu.find(addr)); endcase endfunction This first rule describe what happens in the fetch of this pipeline. This rules says that given any processor term, we can always rewrite it to a new term wehre, and we enqueue the current instruction into bf. And at the same time the pc field is incremende by one It may look like this rule can fire forever, but because bf is bounded, when a rule enqueue into bf, there is an implied predicate that say bf must not be full. Need to extend the fifo interface with the “find” method where “find” searches the fifo to see if a register is going to be updated February 18, 2009 8 8 8 6

30 The findf function When we make a searchable FIFO we need to supply a function that determines if a register is going to be updated by an instruction template mkSFifo can be parameterized by such a search function SFIFO#(InstrTemplate, RName) bu <- mkSFifo(findf); function Bool findf (RName r, InstrTemplate it); case (it) matches tagged EAdd{dst:.rd,op1:.v1,op2:.v2}: return (r == rd); tagged EBz {cond:.c,addr:.a}: return (False); tagged ELoad{dst:.rd,addr:.a}: tagged EStore{value:.v,addr:.a}: endcase endfunction Same as before February 18, 2009

31 Execute Rule rule execute (True); case (it) matches tagged EAdd{dst:.rd,src1:.va,src2:.vb}: begin rf.upd(rd, va+vb); bu.deq(); end tagged EBz {cond:.cv,addr:.av}: if (cv == 0) then begin pc <= av; bu.clear(); end else bu.deq(); tagged ELoad{dst:.rd,addr:.av}: begin rf.upd(rd, dMem.read(av)); bu.deq(); end tagged EStore{value:.vv,addr:.av}: begin dMem.write(av, vv); bu.deq(); end endcase endrule February 18, 2009

32 Next time -- Bypassing February 18, 2009


Download ppt "Modeling Processors Arvind"

Similar presentations


Ads by Google