punk@1: /// The MIT License
punk@1: 
punk@1: // Copyright (c) 2009 Massachusetts Institute of Technology
punk@1: 
punk@1: // Permission is hereby granted, free of charge, to any person obtaining a copy
punk@1: // of this software and associated documentation files (the "Software"), to deal
punk@1: // in the Software without restriction, including without limitation the rights
punk@1: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
punk@1: // copies of the Software, and to permit persons to whom the Software is
punk@1: // furnished to do so, subject to the following conditions:
punk@1: 
punk@1: // The above copyright notice and this permission notice shall be included in
punk@1: // all copies or substantial portions of the Software.
punk@1: 
punk@1: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
punk@1: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
punk@1: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
punk@1: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
punk@1: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
punk@1: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
punk@1: // THE SOFTWARE.
punk@1: 
punk@1: import Connectable::*;
punk@1: import GetPut::*;
punk@1: import ClientServer::*;
punk@1: import RegFile::*;
punk@1: import BRegFile::*;
punk@1: import FIFO::*;
punk@1: import FIFOF::*;
punk@1: import SFIFO::*;
punk@1: import RWire::*;
punk@1: 
punk@1: import BFIFO::*;
punk@1: import MemTypes::*;
punk@1: import ProcTypes::*;
punk@1: import BranchPred::*;
punk@1: import PathTypes::*;
punk@1: 
punk@1: import Trace::*;
punk@1: 
punk@1: interface ProcStats;
punk@1:   interface Get#(Stat) num_cycles;
punk@1:   interface Get#(Stat) num_inst;
punk@1: endinterface
punk@1: 
punk@1: interface CPUToHost;
punk@1:   method Bit#(32) cpuToHost(int req);
punk@1: endinterface
punk@1: 
punk@1: interface Proc;
punk@1: 
punk@1:   // Interface from processor to caches
punk@1:   interface Client#(DataReq,DataResp) dmem_client;
punk@1:   interface Client#(InstReq,InstResp) imem_client;
punk@1: 
punk@1:   // Interface for enabling/disabling statistics on the rest of the core
punk@1:   interface Get#(Bool) statsEn_get;
punk@1: 
punk@1:   // Interface for collecting statistics.
punk@1:   interface ProcStats stats;
punk@1: 
punk@1:   // Interface to host
punk@1:   interface CPUToHost tohost;
punk@1: 
punk@1: endinterface
punk@1: 
punk@1: 
punk@1: typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);
punk@1: 
punk@1: //-----------------------------------------------------------
punk@1: // Register file module
punk@1: //-----------------------------------------------------------
punk@1: 
punk@1: interface BRFile;
punk@1:    method Action   wr( Rindx rindx, Bit#(32) data );
punk@1:    method Bit#(32) rd1( Rindx rindx );
punk@1:    method Bit#(32) rd2( Rindx rindx );
punk@1: endinterface
punk@1: 
punk@1: module mkBRFile( BRFile );
punk@1:    
punk@1:    RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();
punk@1:    
punk@1:    method Action wr( Rindx rindx, Bit#(32) data );
punk@1:       rfile.upd( rindx, data );
punk@1:    endmethod
punk@1:    
punk@1:    method Bit#(32) rd1( Rindx rindx );
punk@1:       return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
punk@1:    endmethod
punk@1:    
punk@1:    method Bit#(32) rd2( Rindx rindx );
punk@1:       return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
punk@1:    endmethod
punk@1: 
punk@1: endmodule
punk@1: 
punk@1: //-----------------------------------------------------------
punk@1: // Helper functions
punk@1: //-----------------------------------------------------------
punk@1: 
punk@1: function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );
punk@1:    return zeroExtend( pack( signedLT(val1,val2) ) );
punk@1: endfunction
punk@1: 
punk@1: function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );
punk@1:    return zeroExtend( pack( val1 < val2 ) );
punk@1: endfunction
punk@1: 
punk@1: function Bit#(32) rshft( Bit#(32) val );
punk@1:    return zeroExtend(val[4:0]);
punk@1: endfunction
punk@1: 
punk@1: 
punk@1: //-----------------------------------------------------------
punk@1: // Find funct for wbQ
punk@1: //-----------------------------------------------------------
punk@1: function Bool findwbf(Rindx fVal, WBResult cmpVal);
punk@1:   case (cmpVal) matches   
punk@1:      tagged WB_ALU  {data:.res, dest:.rd} :
punk@1: 	return (fVal == rd);
punk@1:      tagged WB_Load .rd  :
punk@1: 	return (fVal == rd);
punk@1:      tagged WB_Store .st :
punk@1: 	return False;
punk@1:      tagged WB_Host .x   :
punk@1: 	return False;
punk@1:   endcase
punk@1: endfunction
punk@1: 
punk@1:      
punk@1: //-----------------------------------------------------------
punk@1: // Stall funct for wbQ
punk@1: //-----------------------------------------------------------
punk@1: function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);
punk@1:    case (inst) matches
punk@1:       	 // -- Memory Ops ------------------------------------------------      
punk@1:       tagged LW .it :
punk@1: 	 return f.find(it.rbase);
punk@1:       tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :
punk@1: 	 return (f.find(addr) ||  f.find2(dreg));
punk@1: 
punk@1: 	 // -- Simple Ops ------------------------------------------------      
punk@1:       tagged ADDIU .it : return f.find(it.rsrc);
punk@1:       tagged SLTI  .it : return f.find(it.rsrc);
punk@1:       tagged SLTIU .it : return f.find(it.rsrc);
punk@1:       tagged ANDI  .it : return f.find(it.rsrc);
punk@1:       tagged ORI   .it : return f.find(it.rsrc);
punk@1:       tagged XORI  .it : return f.find(it.rsrc);
punk@1:       
punk@1:       tagged LUI   .it : return f.find(it.rdst);  //this rds/wrs itself
punk@1:       tagged SLL   .it : return f.find(it.rsrc);
punk@1:       tagged SRL   .it : return f.find(it.rsrc);
punk@1:       tagged SRA   .it : return f.find(it.rsrc);
punk@1:       tagged SLLV  .it : return (f.find(it.rsrc) || f.find(it.rshamt));
punk@1:       tagged SRLV  .it : return (f.find(it.rsrc) || f.find(it.rshamt));
punk@1:       tagged SRAV  .it : return (f.find(it.rsrc) || f.find(it.rshamt));
punk@1:       tagged ADDU  .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged SUBU  .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged AND   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged OR    .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged XOR   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged NOR   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged SLT   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged SLTU  .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:    
punk@1: 
punk@1:       // -- Branches --------------------------------------------------
punk@1:     
punk@1:       tagged BLEZ  .it : return (f.find(it.rsrc));
punk@1:       tagged BGTZ  .it : return (f.find(it.rsrc));
punk@1:       tagged BLTZ  .it : return (f.find(it.rsrc));
punk@1:       tagged BGEZ  .it : return (f.find(it.rsrc));
punk@1:       tagged BEQ   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       tagged BNE   .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
punk@1:       
punk@1:       // -- Jumps -----------------------------------------------------
punk@1:       
punk@1:       tagged J     .it : return False;
punk@1:       tagged JR    .it : return f.find(it.rsrc);
punk@1:       tagged JALR  .it : return f.find(it.rsrc);
punk@1:       tagged JAL   .it : return False;
punk@1:       
punk@1:       // -- Cop0 ------------------------------------------------------
punk@1:       
punk@1:       tagged MTC0  .it : return f.find(it.rsrc);      
punk@1:       tagged MFC0  .it : return False; 
punk@1: 
punk@1:       // -- Illegal ---------------------------------------------------
punk@1: 
punk@1:       default : return False;
punk@1: 
punk@1:     endcase
punk@1: endfunction
punk@1: //-----------------------------------------------------------
punk@1: // Reference processor
punk@1: //-----------------------------------------------------------
punk@1: 
punk@1: 
punk@1: (* doc = "synthesis attribute ram_style mkProc distributed;" *)
punk@1: (* synthesize *)
punk@1: module  mkProc( Proc );
punk@1: 
punk@1:    //-----------------------------------------------------------
punk@1:    // State
punk@1: 
punk@1:    // Standard processor state
punk@1:    
punk@1:    Reg#(Addr)  pc    <- mkReg(32'h00001000);
punk@1:    Reg#(Epoch) epoch <- mkReg(0);
punk@1:    Reg#(Stage) stage <- mkReg(PCgen);
punk@1:    BRFile      rf    <- mkBRFile;
punk@1: 
punk@1:    // Branch Prediction
punk@1:    BranchPred               bp <- mkBranchPred();
punk@1:    FIFO#(PCStat)        execpc <- mkLFIFO();
punk@1:    
punk@1:    // Pipelines
punk@1:    FIFO#(PCStat)           pcQ <-mkSizedFIFO(3);
punk@1:    SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);
punk@1: 
punk@1:    Reg#(Bit#(32)) cp0_tohost   <- mkReg(0);
punk@1:    Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);
punk@1:    Reg#(Bool)     cp0_statsEn  <- mkReg(False);
punk@1: 
punk@1:    // Memory request/response state
punk@1:    
punk@1:    FIFO#(InstReq)  instReqQ    <- mkBFIFO1();
punk@1:    FIFO#(InstResp) instRespQ   <- mkFIFO();
punk@1: 
punk@1:    FIFO#(DataReq)  dataReqQ    <- mkBFIFO1();
punk@1:    FIFO#(DataResp) dataRespQ   <- mkFIFO();
punk@1: 
punk@1:    // Statistics state
punk@1:    Reg#(Stat) num_cycles <- mkReg(0);
punk@1:    Reg#(Stat) num_inst <- mkReg(0);
punk@1: 
punk@1:    //-----------------------------------------------------------
punk@1:    // Rules
punk@1: 
punk@1:    (* descending_urgency = "exec, pcgen" *)
punk@1:    rule pcgen; //( stage == PCgen );
punk@1:       let pc_plus4 = pc + 4;
punk@1: 
punk@1:       traceTiny("mkProc", "pc",pc);
punk@1:       traceTiny("mkProc", "pcgen","P");
punk@1:       instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );
punk@1:       
punk@1:       let next_pc = bp.get(pc);
punk@1:       if (next_pc matches tagged Valid .npc) 
punk@1: 	begin
punk@1: 	   pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});
punk@1: 	   pc <= npc;
punk@1: 	end
punk@1:      else
punk@1: 	 begin
punk@1: 	   pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});
punk@1: 	   pc <= pc_plus4;
punk@1: 	 end
punk@1:       
punk@1:    endrule
punk@1: 
punk@1:    rule discard (instRespQ.first() matches tagged LoadResp .ld
punk@1: 					      &&& ld.tag != epoch);
punk@1:       traceTiny("mkProc", "stage", "D");
punk@1:       instRespQ.deq();
punk@1:    endrule
punk@1: 
punk@1:    (* conflict_free = "exec, writeback" *)		      
punk@1:    rule exec (instRespQ.first() matches tagged LoadResp.ld
punk@1: 	      &&& (ld.tag == epoch)
punk@1: 	      &&& unpack(ld.data) matches .inst
punk@1:               &&& !stall(inst, wbQ));
punk@1: 
punk@1:       // Some abbreviations
punk@1:       let sext = signExtend;
punk@1:       let zext = zeroExtend;
punk@1:       let sra  = signedShiftRight;
punk@1:       
punk@1:       // Get the instruction
punk@1:       
punk@1:       instRespQ.deq();
punk@1:       Instr inst 
punk@1:       = case ( instRespQ.first() ) matches
punk@1: 	   tagged LoadResp  .ld : return unpack(ld.data);
punk@1: 	   tagged StoreResp .st : return ?;
punk@1: 	endcase;
punk@1: 
punk@1:       // Get the PC info
punk@1:       let instrpc = pcQ.first().qpc;
punk@1:       let pc_plus4 = instrpc + 4;
punk@1:       
punk@1:       Bool branchTaken = False;
punk@1:       Addr newPC = pc_plus4;
punk@1: 
punk@1:       // Tracing
punk@1:       traceTiny("mkProc", "exec","X");
punk@1:       traceTiny("mkProc", "exInstTiny",inst);
punk@1:       traceFull("mkProc", "exInstFull",inst);
punk@1: 
punk@1:       case ( inst ) matches
punk@1: 
punk@1: 	 // -- Memory Ops ------------------------------------------------      
punk@1: 
punk@1: 	 tagged LW .it : 
punk@1: 	    begin
punk@1:                Addr addr = rf.rd1(it.rbase) + sext(it.offset);
punk@1:                dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );
punk@1:                wbQ.enq(tagged WB_Load it.rdst);
punk@1: 	    end
punk@1: 
punk@1: 	 tagged SW .it : 
punk@1: 	    begin
punk@1:                Addr addr = rf.rd1(it.rbase) + sext(it.offset);
punk@1:                dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );
punk@1:                wbQ.enq(tagged WB_Store);
punk@1: 	    end
punk@1: 
punk@1: 	 // -- Simple Ops ------------------------------------------------      
punk@1: 
punk@1: 	 tagged ADDIU .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);
punk@1: 	       wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});
punk@1: 	    end
punk@1: 	 tagged SLTI  .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});
punk@1: 	 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });
punk@1: 	 tagged ANDI  .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_imm = zext(it.imm);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );
punk@1: 	    end
punk@1: 	 tagged ORI   .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_imm = zext(it.imm);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );
punk@1: 	    end
punk@1: 	 tagged XORI  .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_imm = zext(it.imm);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});
punk@1: 	    end
punk@1: 	 tagged LUI   .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_imm = zext(it.imm);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });
punk@1: 	    end
punk@1: 	 
punk@1: 	 tagged SLL   .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_shamt = zext(it.shamt);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );
punk@1: 	    end
punk@1: 	 tagged SRL   .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_shamt = zext(it.shamt);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});
punk@1: 	    end
punk@1: 	 tagged SRA   .it : 
punk@1: 	    begin
punk@1: 	       Bit#(32) zext_it_shamt = zext(it.shamt);
punk@1: 	       wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});
punk@1: 	    end
punk@1: 	 tagged SLLV  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});
punk@1: 	 tagged SRLV  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );
punk@1: 	 tagged SRAV  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });
punk@1: 	 tagged ADDU  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );
punk@1: 	 tagged SUBU  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );
punk@1: 	 tagged AND   .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );
punk@1: 	 tagged OR    .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );
punk@1: 	 tagged XOR   .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );
punk@1: 	 tagged NOR   .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );
punk@1: 	 tagged SLT   .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
punk@1: 	 tagged SLTU  .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
punk@1: 
punk@1: 	 // -- Branches --------------------------------------------------
punk@1: 
punk@1: 	 tagged BLEZ  .it : 
punk@1:             if ( signedLE( rf.rd1(it.rsrc), 0 ) )
punk@1: 	       begin
punk@1: 		  newPC = pc_plus4 + (sext(it.offset) << 2);
punk@1: 		  branchTaken = True;
punk@1: 	       end
punk@1: 
punk@1: 	 tagged BGTZ  .it : 
punk@1:             if ( signedGT( rf.rd1(it.rsrc), 0 ) ) 
punk@1:                begin 
punk@1: 		  newPC = pc_plus4 + (sext(it.offset) << 2);
punk@1: 		  branchTaken = True;
punk@1: 	       end
punk@1: 
punk@1: 	 tagged BLTZ  .it : 
punk@1:             if ( signedLT( rf.rd1(it.rsrc), 0 ) )
punk@1:                begin 
punk@1: 		  newPC = pc_plus4 + (sext(it.offset) << 2);
punk@1: 		  branchTaken = True;
punk@1: 	       end
punk@1: 		  
punk@1: 	 tagged BGEZ  .it : 
punk@1:             if ( signedGE( rf.rd1(it.rsrc), 0 ) )
punk@1:                begin 
punk@1: 		  newPC = pc_plus4 + (sext(it.offset) << 2);		  
punk@1: 		  branchTaken = True;
punk@1: 	       end
punk@1: 
punk@1:       tagged BEQ   .it : 
punk@1:         if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )
punk@1:           begin 
punk@1: 	     newPC = pc_plus4 + (sext(it.offset) << 2);
punk@1: 	     branchTaken = True;
punk@1: 	  end
punk@1: 
punk@1:       tagged BNE   .it : 
punk@1:         if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )
punk@1:           begin 
punk@1: 	     newPC = pc_plus4 + (sext(it.offset) << 2);
punk@1: 	     branchTaken = True;
punk@1: 	  end
punk@1: 
punk@1:       // -- Jumps -----------------------------------------------------
punk@1:       
punk@1:       tagged J     .it : 
punk@1:         begin 
punk@1: 	   newPC = { pc_plus4[31:28], it.target, 2'b0 };
punk@1: 	   branchTaken = True;
punk@1: 	end
punk@1:       
punk@1:       tagged JR    .it : 
punk@1:         begin 
punk@1: 	   newPC = rf.rd1(it.rsrc);
punk@1: 	   branchTaken = True;
punk@1: 	end
punk@1: 
punk@1:       tagged JAL   .it : 
punk@1:        begin
punk@1:           wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });
punk@1:           newPC = { pc_plus4[31:28], it.target, 2'b0 };		  
punk@1: 	  branchTaken = True;
punk@1:        end
punk@1: 
punk@1:       tagged JALR  .it : 
punk@1:        begin
punk@1:           wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });
punk@1:           newPC = rf.rd1(it.rsrc);
punk@1: 	  branchTaken = True;
punk@1:        end
punk@1: 
punk@1:       // -- Cop0 ------------------------------------------------------
punk@1:       
punk@1:       tagged MTC0  .it : 
punk@1: 	 begin
punk@1:             case ( it.cop0dst )
punk@1: 	       5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));
punk@1: 	       5'd21 : cp0_tohost  <= truncate(rf.rd1(it.rsrc));
punk@1: 	       default :
punk@1: 	       $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );
punk@1: 	    endcase
punk@1: 	    wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.
punk@1: 	 end
punk@1: 
punk@1: //this is host stuff?
punk@1:       tagged MFC0  .it :
punk@1: 	 begin
punk@1:             case ( it.cop0src )
punk@1: 	    // not actually an ALU instruction but don't have the format otherwise
punk@1:                5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });
punk@1:                5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });
punk@1:                5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost   });
punk@1:               default : 
punk@1:                 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );
punk@1:             endcase
punk@1: 	end
punk@1: 
punk@1:       // -- Illegal ---------------------------------------------------
punk@1: 
punk@1:       default : 
punk@1:         $display( " RTL-ERROR : %m : Illegal instruction !" );
punk@1: 
punk@1:     endcase
punk@1: 
punk@1: //evaluate branch prediction
punk@1:      Addr ppc = pcQ.first().qnxtpc; //predicted branch
punk@1:      if (ppc != newPC) //prediction wrong
punk@1:        begin
punk@1: 	  epoch <= pcQ.first().qepoch + 1;
punk@1: 	  bp.upd(instrpc, newPC); //update branch predictor
punk@1: 	  pcQ.clear();
punk@1: 	  pc <= newPC;
punk@1:        end
punk@1:      else
punk@1: 	pcQ.deq();
punk@1: 
punk@1:     if ( cp0_statsEn )
punk@1:       num_inst <= num_inst+1;
punk@1: 
punk@1:   endrule
punk@1: 
punk@1:   rule writeback; // ( stage == Writeback );
punk@1:      traceTiny("mkProc", "writeback","W");
punk@1:      
punk@1: 
punk@1:     // get what to do off the writeback queue
punk@1:      wbQ.deq();
punk@1:      case (wbQ.first()) matches
punk@1: 	tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);
punk@1: 	tagged WB_Load .regWr : 
punk@1: 	   begin
punk@1: 	      dataRespQ.deq();
punk@1: 	      if (dataRespQ.first() matches tagged LoadResp .ld)
punk@1: 		rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue?  Duplicate?
punk@1: 	   end
punk@1: 	tagged WB_Store : dataRespQ.deq();
punk@1: 	tagged WB_Host .dat : noAction;
punk@1:      endcase
punk@1:            
punk@1:   endrule
punk@1: 
punk@1:   rule inc_num_cycles;
punk@1:     if ( cp0_statsEn )
punk@1:       num_cycles <= num_cycles+1;
punk@1:   endrule
punk@1: 
punk@1: 
punk@1: //-----------------------------------------------------------
punk@1: // My Adds
punk@1: //-----------------------------------------------------------
punk@1: 
punk@1:   //-----------------------------------------------------------
punk@1:   // Methods
punk@1: 
punk@1:   interface Client imem_client;
punk@1:     interface Get request  = toGet(instReqQ);
punk@1:     interface Put response = toPut(instRespQ);
punk@1:   endinterface
punk@1: 
punk@1:   interface Client dmem_client;
punk@1:     interface Get request  = toGet(dataReqQ);
punk@1:     interface Put response = toPut(dataRespQ);
punk@1:   endinterface
punk@1: 
punk@1:   interface Get statsEn_get = toGet(asReg(cp0_statsEn));
punk@1: 
punk@1:   interface ProcStats stats;
punk@1:     interface Get num_cycles = toGet(asReg(num_cycles));
punk@1:     interface Get num_inst = toGet(asReg(num_inst));
punk@1:   endinterface
punk@1: 
punk@1:   interface CPUToHost tohost;
punk@1:     method Bit#(32) cpuToHost(int req);
punk@1:       return (case (req)
punk@1:        0: cp0_tohost;
punk@1:        1: pc;
punk@1:        2: zeroExtend(pack(stage));
punk@1:       endcase);
punk@1:     endmethod
punk@1:   endinterface
punk@1: 
punk@1: endmodule
punk@1: