Mercurial > pygar
view modules/bluespec/Pygar/lab4/#Processor.bsv# @ 76:8bd0e4d37ad2 pygar svn.77 tip
[svn r77] I don't know why my last change didn't go through grumble grumble....
author | rlm |
---|---|
date | Wed, 12 May 2010 08:58:23 -0400 |
parents | 2c8166d205d5 |
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::*;28 import FIFO::*;29 import FIFOF::*;30 import SFIFO::*;31 import RWire::*;33 import BFIFO::*;34 import MemTypes::*;35 import ProcTypes::*;36 import BRegFile::*;37 import BranchPred::*;38 //import PathTypes::*; This is only there to force the debugging40 import Trace::*;42 //AWB includes43 `include "asim/provides/low_level_platform_interface.bsh"44 `include "asim/provides/soft_connections.bsh"45 `include "asim/provides/common_services.bsh"47 // Local includes48 `include "asim/provides/processor_library.bsh"49 `include "asim/rrr/remote_server_stub_PROCESSORSYSTEMRRR.bsh"50 `include "asim/provides/common_services.bsh"51 `include "asim/dict/STATS_PROCESSOR.bsh"53 interface ProcStats;54 interface Get#(Stat) num_cycles;55 interface Get#(Stat) num_inst;56 endinterface58 interface CPUToHost;59 method Bit#(32) cpuToHost(int req);60 endinterface62 interface Proc;64 // Interface from processor to caches65 interface Client#(DataReq,DataResp) dmem_client;66 interface Client#(InstReq,InstResp) imem_client;68 // Interface for enabling/disabling statistics on the rest of the core69 interface Get#(Bool) statsEn_get;71 // Interface for collecting statistics.72 interface ProcStats stats;74 // Interface to host75 interface CPUToHost tohost;77 endinterface80 typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);82 //-----------------------------------------------------------83 // Register file module84 //-----------------------------------------------------------86 interface BRFile;87 method Action wr( Rindx rindx, Bit#(32) data );88 method Bit#(32) rd1( Rindx rindx );89 method Bit#(32) rd2( Rindx rindx );90 endinterface92 module mkBRFile( BRFile );94 RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();96 method Action wr( Rindx rindx, Bit#(32) data );97 rfile.upd( rindx, data );98 endmethod100 method Bit#(32) rd1( Rindx rindx );101 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);102 endmethod104 method Bit#(32) rd2( Rindx rindx );105 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);106 endmethod108 endmodule110 //-----------------------------------------------------------111 // Helper functions112 //-----------------------------------------------------------114 function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );115 return zeroExtend( pack( signedLT(val1,val2) ) );116 endfunction118 function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );119 return zeroExtend( pack( val1 < val2 ) );120 endfunction122 function Bit#(32) rshft( Bit#(32) val );123 return zeroExtend(val[4:0]);124 endfunction127 //-----------------------------------------------------------128 // Find funct for wbQ129 //-----------------------------------------------------------130 function Bool findwbf(Rindx fVal, WBResult cmpVal);131 case (cmpVal) matches132 tagged WB_ALU {data:.res, dest:.rd} :133 return (fVal == rd);134 tagged WB_Load .rd :135 return (fVal == rd);136 tagged WB_Store .st :137 return False;138 tagged WB_Host .x :139 return False;140 endcase141 endfunction144 //-----------------------------------------------------------145 // Stall funct for wbQ146 //-----------------------------------------------------------147 function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);148 case (inst) matches149 // -- Memory Ops ------------------------------------------------150 tagged LW .it :151 return f.find(it.rbase);152 tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :153 return (f.find(addr) || f.find2(dreg));155 // -- Simple Ops ------------------------------------------------156 tagged ADDIU .it : return f.find(it.rsrc);157 tagged SLTI .it : return f.find(it.rsrc);158 tagged SLTIU .it : return f.find(it.rsrc);159 tagged ANDI .it : return f.find(it.rsrc);160 tagged ORI .it : return f.find(it.rsrc);161 tagged XORI .it : return f.find(it.rsrc);163 tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself164 tagged SLL .it : return f.find(it.rsrc);165 tagged SRL .it : return f.find(it.rsrc);166 tagged SRA .it : return f.find(it.rsrc);167 tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));168 tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));169 tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt));170 tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));171 tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));172 tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));173 tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));174 tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));175 tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));176 tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));177 tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));180 // -- Branches --------------------------------------------------182 tagged BLEZ .it : return (f.find(it.rsrc));183 tagged BGTZ .it : return (f.find(it.rsrc));184 tagged BLTZ .it : return (f.find(it.rsrc));185 tagged BGEZ .it : return (f.find(it.rsrc));186 tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));187 tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));189 // -- Jumps -----------------------------------------------------191 tagged J .it : return False;192 tagged JR .it : return f.find(it.rsrc);193 tagged JALR .it : return f.find(it.rsrc);194 tagged JAL .it : return False;196 // -- Cop0 ------------------------------------------------------198 tagged MTC0 .it : return f.find(it.rsrc);199 tagged MFC0 .it : return False;201 // -- Illegal ---------------------------------------------------203 default : return False;205 endcase206 endfunction207 //-----------------------------------------------------------208 // Reference processor209 //-----------------------------------------------------------212 //(* doc = "synthesis attribute ram_style mkProc distributed;" *)213 //(* synthesize *)215 module [CONNECTED_MODULE] mkProc( Proc );217 //-----------------------------------------------------------218 // Debug port220 ServerStub_PROCESSORSYSTEMRRR server_stub <- mkServerStub_PROCESSORSYSTEMRRR();223 //-----------------------------------------------------------224 // State226 // Standard processor state228 Reg#(Addr) pc <- mkReg(32'h00001000);229 Reg#(Epoch) epoch <- mkReg(0);230 Reg#(Stage) stage <- mkReg(PCgen);231 BRFile rf <- mkBRFile;233 // Branch Prediction234 BranchPred bp <- mkBranchPred();235 FIFO#(PCStat) execpc <- mkLFIFO();237 // Pipelines238 FIFO#(PCStat) pcQ <-mkSizedFIFO(3);239 SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);241 Reg#(Bit#(32)) cp0_tohost <- mkReg(0);242 Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);243 Reg#(Bool) cp0_statsEn <- mkReg(False);245 // Memory request/response state247 FIFO#(InstReq) instReqQ <- mkBFIFO1();248 FIFO#(InstResp) instRespQ <- mkFIFO();250 FIFO#(DataReq) dataReqQ <- mkBFIFO1();251 FIFO#(DataResp) dataRespQ <- mkFIFO();253 // Statistics state254 Reg#(Stat) num_cycles <- mkReg(0);255 Reg#(Stat) num_inst <- mkReg(0);257 //Or:258 // Statistics state259 //STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT);260 //STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT);262 //-----------------------------------------------------------263 // Rules265 (* descending_urgency = "exec, pcgen" *)266 rule pcgen; //( stage == PCgen );267 let pc_plus4 = pc + 4;269 traceTiny("mkProc", "pc",pc);270 traceTiny("mkProc", "pcgen","P");271 instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );273 let next_pc = bp.get(pc);274 if (next_pc matches tagged Valid .npc)275 begin276 pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});277 pc <= npc;278 end279 else280 begin281 pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});282 pc <= pc_plus4;283 end285 endrule287 rule discard (instRespQ.first() matches tagged LoadResp .ld288 &&& ld.tag != epoch);289 traceTiny("mkProc", "stage", "D");290 instRespQ.deq();291 endrule293 (* conflict_free = "exec, writeback" *)294 rule exec (instRespQ.first() matches tagged LoadResp.ld295 &&& (ld.tag == epoch)296 &&& unpack(ld.data) matches .inst297 &&& !stall(inst, wbQ));299 // Some abbreviations300 let sext = signExtend;301 let zext = zeroExtend;302 let sra = signedShiftRight;304 // Get the instruction306 instRespQ.deq();307 Instr inst308 = case ( instRespQ.first() ) matches309 tagged LoadResp .ld : return unpack(ld.data);310 tagged StoreResp .st : return ?;311 endcase;313 // Get the PC info314 let instrpc = pcQ.first().qpc;315 let pc_plus4 = instrpc + 4;317 Bool branchTaken = False;318 Addr newPC = pc_plus4;320 // Tracing321 traceTiny("mkProc", "exec","X");322 traceTiny("mkProc", "exInstTiny",inst);323 traceFull("mkProc", "exInstFull",inst);325 case ( inst ) matches327 // -- Memory Ops ------------------------------------------------329 tagged LW .it :330 begin331 Addr addr = rf.rd1(it.rbase) + sext(it.offset);332 dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );333 wbQ.enq(tagged WB_Load it.rdst);334 end336 tagged SW .it :337 begin338 Addr addr = rf.rd1(it.rbase) + sext(it.offset);339 dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );340 wbQ.enq(tagged WB_Store);341 end343 // -- Simple Ops ------------------------------------------------345 tagged ADDIU .it :346 begin347 Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);348 wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});349 end350 tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});351 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });352 tagged ANDI .it :353 begin354 Bit#(32) zext_it_imm = zext(it.imm);355 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );356 end357 tagged ORI .it :358 begin359 Bit#(32) zext_it_imm = zext(it.imm);360 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );361 end362 tagged XORI .it :363 begin364 Bit#(32) zext_it_imm = zext(it.imm);365 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});366 end367 tagged LUI .it :368 begin369 Bit#(32) zext_it_imm = zext(it.imm);370 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });371 end373 tagged SLL .it :374 begin375 Bit#(32) zext_it_shamt = zext(it.shamt);376 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );377 end378 tagged SRL .it :379 begin380 Bit#(32) zext_it_shamt = zext(it.shamt);381 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});382 end383 tagged SRA .it :384 begin385 Bit#(32) zext_it_shamt = zext(it.shamt);386 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});387 end388 tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});389 tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );390 tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });391 tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );392 tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );393 tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );394 tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );395 tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );396 tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );397 tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });398 tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });400 // -- Branches --------------------------------------------------402 tagged BLEZ .it :403 if ( signedLE( rf.rd1(it.rsrc), 0 ) )404 begin405 newPC = pc_plus4 + (sext(it.offset) << 2);406 branchTaken = True;407 end409 tagged BGTZ .it :410 if ( signedGT( rf.rd1(it.rsrc), 0 ) )411 begin412 newPC = pc_plus4 + (sext(it.offset) << 2);413 branchTaken = True;414 end416 tagged BLTZ .it :417 if ( signedLT( rf.rd1(it.rsrc), 0 ) )418 begin419 newPC = pc_plus4 + (sext(it.offset) << 2);420 branchTaken = True;421 end423 tagged BGEZ .it :424 if ( signedGE( rf.rd1(it.rsrc), 0 ) )425 begin426 newPC = pc_plus4 + (sext(it.offset) << 2);427 branchTaken = True;428 end430 tagged BEQ .it :431 if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )432 begin433 newPC = pc_plus4 + (sext(it.offset) << 2);434 branchTaken = True;435 end437 tagged BNE .it :438 if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )439 begin440 newPC = pc_plus4 + (sext(it.offset) << 2);441 branchTaken = True;442 end444 // -- Jumps -----------------------------------------------------446 tagged J .it :447 begin448 newPC = { pc_plus4[31:28], it.target, 2'b0 };449 branchTaken = True;450 end452 tagged JR .it :453 begin454 newPC = rf.rd1(it.rsrc);455 branchTaken = True;456 end458 tagged JAL .it :459 begin460 wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });461 newPC = { pc_plus4[31:28], it.target, 2'b0 };462 branchTaken = True;463 end465 tagged JALR .it :466 begin467 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });468 newPC = rf.rd1(it.rsrc);469 branchTaken = True;470 end472 // -- Cop0 ------------------------------------------------------474 tagged MTC0 .it :475 begin476 case ( it.cop0dst )477 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));478 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc));479 default :480 $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );481 endcase482 wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.483 end485 //this is host stuff?486 tagged MFC0 .it :487 begin488 case ( it.cop0src )489 // not actually an ALU instruction but don't have the format otherwise490 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });491 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });492 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost });493 default :494 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );495 endcase496 end498 // -- Illegal ---------------------------------------------------500 default :501 $display( " RTL-ERROR : %m : Illegal instruction !" );503 endcase505 //evaluate branch prediction506 Addr ppc = pcQ.first().qnxtpc; //predicted branch507 if (ppc != newPC) //prediction wrong508 begin509 epoch <= pcQ.first().qepoch + 1;510 bp.upd(instrpc, newPC); //update branch predictor511 pcQ.clear();512 pc <= newPC;513 end514 else515 pcQ.deq();517 if ( cp0_statsEn )518 num_inst <= num_inst+1;520 endrule522 rule writeback; // ( stage == Writeback );523 traceTiny("mkProc", "writeback","W");526 // get what to do off the writeback queue527 wbQ.deq();528 case (wbQ.first()) matches529 tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);530 tagged WB_Load .regWr :531 begin532 dataRespQ.deq();533 if (dataRespQ.first() matches tagged LoadResp .ld)534 rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate?535 end536 tagged WB_Store : dataRespQ.deq();537 tagged WB_Host .dat : noAction;538 endcase540 endrule542 rule inc_num_cycles;543 if ( cp0_statsEn )544 num_cycles <= num_cycles+1;545 endrule547 // THis rule breaks things548 // rule handleCPUToHost;549 // let req <- server_stub.acceptRequest_ReadCPUToHost();550 // case (req)551 // 0: server_stub.sendResponse_ReadCPUToHost(cp0_tohost);552 // 1: server_stub.sendResponse_ReadCPUToHost(pc);553 // 2: server_stub.sendResponse_ReadCPUToHost(zeroExtend(pack(stage)));554 // endcase555 // endrule556 //-----------------------------------------------------------557 // My Adds558 //-----------------------------------------------------------560 //-----------------------------------------------------------561 // Methods563 interface Client imem_client;564 interface Get request = toGet(instReqQ);565 interface Put response = toPut(instRespQ);566 endinterface568 interface Client dmem_client;569 interface Get request = toGet(dataReqQ);570 interface Put response = toPut(dataRespQ);571 endinterface573 interface Get statsEn_get = toGet(asReg(cp0_statsEn));575 interface ProcStats stats;576 interface Get num_cycles = toGet(asReg(num_cycles));577 interface Get num_inst = toGet(asReg(num_inst));578 endinterface580 interface CPUToHost tohost;581 method Bit#(32) cpuToHost(int req);582 return (case (req)583 0: cp0_tohost;584 1: pc;585 2: zeroExtend(pack(stage));586 endcase);587 endmethod588 endinterface590 endmodule