Mercurial > pygar
view core/src/Processor.bsv @ 13:6d461680c6d9 pygar svn.14
[svn r14] more stuff
author | punk |
---|---|
date | Tue, 27 Apr 2010 09:03:28 -0400 |
parents | 91a1f76ddd62 |
children |
line wrap: on
line source
1 /// The MIT License3 // Copyright (c) 2009 Massachusetts Institute of Technology5 // Permission is hereby granted, free of charge, to any person obtaining a copy6 // of this software and associated documentation files (the "Software"), to deal7 // in the Software without restriction, including without limitation the rights8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell9 // copies of the Software, and to permit persons to whom the Software is10 // furnished to do so, subject to the following conditions:12 // The above copyright notice and this permission notice shall be included in13 // all copies or substantial portions of the Software.15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN21 // THE SOFTWARE.23 import Connectable::*;24 import GetPut::*;25 import ClientServer::*;26 import RegFile::*;27 import BRegFile::*;28 import FIFO::*;29 import FIFOF::*;30 import SFIFO::*;31 import RWire::*;33 import BFIFO::*;34 import MemTypes::*;35 import ProcTypes::*;36 import BranchPred::*;37 import PathTypes::*;39 import Trace::*;41 interface ProcStats;42 interface Get#(Stat) num_cycles;43 interface Get#(Stat) num_inst;44 endinterface46 interface CPUToHost;47 method Bit#(32) cpuToHost(int req);48 endinterface50 interface Proc;52 // Interface from processor to caches53 interface Client#(DataReq,DataResp) dmem_client;54 interface Client#(InstReq,InstResp) imem_client;56 // Interface for enabling/disabling statistics on the rest of the core57 interface Get#(Bool) statsEn_get;59 // Interface for collecting statistics.60 interface ProcStats stats;62 // Interface to host63 interface CPUToHost tohost;65 endinterface68 typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);70 //-----------------------------------------------------------71 // Register file module72 //-----------------------------------------------------------74 interface BRFile;75 method Action wr( Rindx rindx, Bit#(32) data );76 method Bit#(32) rd1( Rindx rindx );77 method Bit#(32) rd2( Rindx rindx );78 endinterface80 module mkBRFile( BRFile );82 RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();84 method Action wr( Rindx rindx, Bit#(32) data );85 rfile.upd( rindx, data );86 endmethod88 method Bit#(32) rd1( Rindx rindx );89 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);90 endmethod92 method Bit#(32) rd2( Rindx rindx );93 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);94 endmethod96 endmodule98 //-----------------------------------------------------------99 // Helper functions100 //-----------------------------------------------------------102 function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );103 return zeroExtend( pack( signedLT(val1,val2) ) );104 endfunction106 function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );107 return zeroExtend( pack( val1 < val2 ) );108 endfunction110 function Bit#(32) rshft( Bit#(32) val );111 return zeroExtend(val[4:0]);112 endfunction115 //-----------------------------------------------------------116 // Find funct for wbQ117 //-----------------------------------------------------------118 function Bool findwbf(Rindx fVal, WBResult cmpVal);119 case (cmpVal) matches120 tagged WB_ALU {data:.res, dest:.rd} :121 return (fVal == rd);122 tagged WB_Load .rd :123 return (fVal == rd);124 tagged WB_Store .st :125 return False;126 tagged WB_Host .x :127 return False;128 endcase129 endfunction132 //-----------------------------------------------------------133 // Stall funct for wbQ134 //-----------------------------------------------------------135 function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);136 case (inst) matches137 // -- Memory Ops ------------------------------------------------138 tagged LW .it :139 return f.find(it.rbase);140 tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :141 return (f.find(addr) || f.find2(dreg));143 // -- Simple Ops ------------------------------------------------144 tagged ADDIU .it : return f.find(it.rsrc);145 tagged SLTI .it : return f.find(it.rsrc);146 tagged SLTIU .it : return f.find(it.rsrc);147 tagged ANDI .it : return f.find(it.rsrc);148 tagged ORI .it : return f.find(it.rsrc);149 tagged XORI .it : return f.find(it.rsrc);151 tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself152 tagged SLL .it : return f.find(it.rsrc);153 tagged SRL .it : return f.find(it.rsrc);154 tagged SRA .it : return f.find(it.rsrc);155 tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));156 tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));157 tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt));158 tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));159 tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));160 tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));161 tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));162 tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));163 tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));164 tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));165 tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));168 // -- Branches --------------------------------------------------170 tagged BLEZ .it : return (f.find(it.rsrc));171 tagged BGTZ .it : return (f.find(it.rsrc));172 tagged BLTZ .it : return (f.find(it.rsrc));173 tagged BGEZ .it : return (f.find(it.rsrc));174 tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));175 tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));177 // -- Jumps -----------------------------------------------------179 tagged J .it : return False;180 tagged JR .it : return f.find(it.rsrc);181 tagged JALR .it : return f.find(it.rsrc);182 tagged JAL .it : return False;184 // -- Cop0 ------------------------------------------------------186 tagged MTC0 .it : return f.find(it.rsrc);187 tagged MFC0 .it : return False;189 // -- Illegal ---------------------------------------------------191 default : return False;193 endcase194 endfunction195 //-----------------------------------------------------------196 // Reference processor197 //-----------------------------------------------------------200 (* doc = "synthesis attribute ram_style mkProc distributed;" *)201 (* synthesize *)202 module mkProc( Proc );204 //-----------------------------------------------------------205 // State207 // Standard processor state209 Reg#(Addr) pc <- mkReg(32'h00001000);210 Reg#(Epoch) epoch <- mkReg(0);211 Reg#(Stage) stage <- mkReg(PCgen);212 BRFile rf <- mkBRFile;214 // Branch Prediction215 BranchPred bp <- mkBranchPred();216 FIFO#(PCStat) execpc <- mkLFIFO();218 // Pipelines219 FIFO#(PCStat) pcQ <-mkSizedFIFO(3);220 SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);222 Reg#(Bit#(32)) cp0_tohost <- mkReg(0);223 Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);224 Reg#(Bool) cp0_statsEn <- mkReg(False);226 // Memory request/response state228 FIFO#(InstReq) instReqQ <- mkBFIFO1();229 FIFO#(InstResp) instRespQ <- mkFIFO();231 FIFO#(DataReq) dataReqQ <- mkBFIFO1();232 FIFO#(DataResp) dataRespQ <- mkFIFO();234 // Statistics state235 Reg#(Stat) num_cycles <- mkReg(0);236 Reg#(Stat) num_inst <- mkReg(0);238 //-----------------------------------------------------------239 // Rules241 (* descending_urgency = "exec, pcgen" *)242 rule pcgen; //( stage == PCgen );243 let pc_plus4 = pc + 4;245 traceTiny("mkProc", "pc",pc);246 traceTiny("mkProc", "pcgen","P");247 instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );249 let next_pc = bp.get(pc);250 if (next_pc matches tagged Valid .npc)251 begin252 pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});253 pc <= npc;254 end255 else256 begin257 pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});258 pc <= pc_plus4;259 end261 endrule263 rule discard (instRespQ.first() matches tagged LoadResp .ld264 &&& ld.tag != epoch);265 traceTiny("mkProc", "stage", "D");266 instRespQ.deq();267 endrule269 (* conflict_free = "exec, writeback" *)270 rule exec (instRespQ.first() matches tagged LoadResp.ld271 &&& (ld.tag == epoch)272 &&& unpack(ld.data) matches .inst273 &&& !stall(inst, wbQ));275 // Some abbreviations276 let sext = signExtend;277 let zext = zeroExtend;278 let sra = signedShiftRight;280 // Get the instruction282 instRespQ.deq();283 Instr inst284 = case ( instRespQ.first() ) matches285 tagged LoadResp .ld : return unpack(ld.data);286 tagged StoreResp .st : return ?;287 endcase;289 // Get the PC info290 let instrpc = pcQ.first().qpc;291 let pc_plus4 = instrpc + 4;293 Bool branchTaken = False;294 Addr newPC = pc_plus4;296 // Tracing297 traceTiny("mkProc", "exec","X");298 traceTiny("mkProc", "exInstTiny",inst);299 traceFull("mkProc", "exInstFull",inst);301 case ( inst ) matches303 // -- Memory Ops ------------------------------------------------305 tagged LW .it :306 begin307 Addr addr = rf.rd1(it.rbase) + sext(it.offset);308 dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );309 wbQ.enq(tagged WB_Load it.rdst);310 end312 tagged SW .it :313 begin314 Addr addr = rf.rd1(it.rbase) + sext(it.offset);315 dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );316 wbQ.enq(tagged WB_Store);317 end319 // -- Simple Ops ------------------------------------------------321 tagged ADDIU .it :322 begin323 Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);324 wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});325 end326 tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});327 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });328 tagged ANDI .it :329 begin330 Bit#(32) zext_it_imm = zext(it.imm);331 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );332 end333 tagged ORI .it :334 begin335 Bit#(32) zext_it_imm = zext(it.imm);336 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );337 end338 tagged XORI .it :339 begin340 Bit#(32) zext_it_imm = zext(it.imm);341 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});342 end343 tagged LUI .it :344 begin345 Bit#(32) zext_it_imm = zext(it.imm);346 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });347 end349 tagged SLL .it :350 begin351 Bit#(32) zext_it_shamt = zext(it.shamt);352 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );353 end354 tagged SRL .it :355 begin356 Bit#(32) zext_it_shamt = zext(it.shamt);357 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});358 end359 tagged SRA .it :360 begin361 Bit#(32) zext_it_shamt = zext(it.shamt);362 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});363 end364 tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});365 tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );366 tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });367 tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );368 tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );369 tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );370 tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );371 tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );372 tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );373 tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });374 tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });376 // -- Branches --------------------------------------------------378 tagged BLEZ .it :379 if ( signedLE( rf.rd1(it.rsrc), 0 ) )380 begin381 newPC = pc_plus4 + (sext(it.offset) << 2);382 branchTaken = True;383 end385 tagged BGTZ .it :386 if ( signedGT( rf.rd1(it.rsrc), 0 ) )387 begin388 newPC = pc_plus4 + (sext(it.offset) << 2);389 branchTaken = True;390 end392 tagged BLTZ .it :393 if ( signedLT( rf.rd1(it.rsrc), 0 ) )394 begin395 newPC = pc_plus4 + (sext(it.offset) << 2);396 branchTaken = True;397 end399 tagged BGEZ .it :400 if ( signedGE( rf.rd1(it.rsrc), 0 ) )401 begin402 newPC = pc_plus4 + (sext(it.offset) << 2);403 branchTaken = True;404 end406 tagged BEQ .it :407 if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )408 begin409 newPC = pc_plus4 + (sext(it.offset) << 2);410 branchTaken = True;411 end413 tagged BNE .it :414 if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )415 begin416 newPC = pc_plus4 + (sext(it.offset) << 2);417 branchTaken = True;418 end420 // -- Jumps -----------------------------------------------------422 tagged J .it :423 begin424 newPC = { pc_plus4[31:28], it.target, 2'b0 };425 branchTaken = True;426 end428 tagged JR .it :429 begin430 newPC = rf.rd1(it.rsrc);431 branchTaken = True;432 end434 tagged JAL .it :435 begin436 wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });437 newPC = { pc_plus4[31:28], it.target, 2'b0 };438 branchTaken = True;439 end441 tagged JALR .it :442 begin443 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });444 newPC = rf.rd1(it.rsrc);445 branchTaken = True;446 end448 // -- Cop0 ------------------------------------------------------450 tagged MTC0 .it :451 begin452 case ( it.cop0dst )453 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));454 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc));455 default :456 $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );457 endcase458 wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.459 end461 //this is host stuff?462 tagged MFC0 .it :463 begin464 case ( it.cop0src )465 // not actually an ALU instruction but don't have the format otherwise466 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });467 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });468 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost });469 default :470 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );471 endcase472 end474 // -- Illegal ---------------------------------------------------476 default :477 $display( " RTL-ERROR : %m : Illegal instruction !" );479 endcase481 //evaluate branch prediction482 Addr ppc = pcQ.first().qnxtpc; //predicted branch483 if (ppc != newPC) //prediction wrong484 begin485 epoch <= pcQ.first().qepoch + 1;486 bp.upd(instrpc, newPC); //update branch predictor487 pcQ.clear();488 pc <= newPC;489 end490 else491 pcQ.deq();493 if ( cp0_statsEn )494 num_inst <= num_inst+1;496 endrule498 rule writeback; // ( stage == Writeback );499 traceTiny("mkProc", "writeback","W");502 // get what to do off the writeback queue503 wbQ.deq();504 case (wbQ.first()) matches505 tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);506 tagged WB_Load .regWr :507 begin508 dataRespQ.deq();509 if (dataRespQ.first() matches tagged LoadResp .ld)510 rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate?511 end512 tagged WB_Store : dataRespQ.deq();513 tagged WB_Host .dat : noAction;514 endcase516 endrule518 rule inc_num_cycles;519 if ( cp0_statsEn )520 num_cycles <= num_cycles+1;521 endrule524 //-----------------------------------------------------------525 // My Adds526 //-----------------------------------------------------------528 //-----------------------------------------------------------529 // Methods531 interface Client imem_client;532 interface Get request = toGet(instReqQ);533 interface Put response = toPut(instRespQ);534 endinterface536 interface Client dmem_client;537 interface Get request = toGet(dataReqQ);538 interface Put response = toPut(dataRespQ);539 endinterface541 interface Get statsEn_get = toGet(asReg(cp0_statsEn));543 interface ProcStats stats;544 interface Get num_cycles = toGet(asReg(num_cycles));545 interface Get num_inst = toGet(asReg(num_inst));546 endinterface548 interface CPUToHost tohost;549 method Bit#(32) cpuToHost(int req);550 return (case (req)551 0: cp0_tohost;552 1: pc;553 2: zeroExtend(pack(stage));554 endcase);555 endmethod556 endinterface558 endmodule