punk@26: /// The MIT License punk@26: punk@26: // Copyright (c) 2009 Massachusetts Institute of Technology punk@26: punk@26: // Permission is hereby granted, free of charge, to any person obtaining a copy punk@26: // of this software and associated documentation files (the "Software"), to deal punk@26: // in the Software without restriction, including without limitation the rights punk@26: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell punk@26: // copies of the Software, and to permit persons to whom the Software is punk@26: // furnished to do so, subject to the following conditions: punk@26: punk@26: // The above copyright notice and this permission notice shall be included in punk@26: // all copies or substantial portions of the Software. punk@26: punk@26: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR punk@26: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, punk@26: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE punk@26: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER punk@26: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, punk@26: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN punk@26: // THE SOFTWARE. punk@26: punk@26: punk@26: import Connectable::*; punk@26: import GetPut::*; punk@26: import ClientServer::*; punk@26: import RegFile::*; punk@26: punk@26: import FIFO::*; punk@26: import FIFOF::*; punk@26: import SFIFO::*; punk@26: import RWire::*; punk@36: punk@26: import Trace::*; punk@26: import BFIFO::*; punk@36: import MemTypes::*; punk@26: import ProcTypes::*; punk@26: import BRegFile::*; punk@26: import BranchPred::*; punk@26: //import PathTypes::*; This is only there to force the debugging punk@26: punk@26: //AWB includes punk@26: `include "asim/provides/low_level_platform_interface.bsh" punk@26: `include "asim/provides/soft_connections.bsh" punk@26: `include "asim/provides/common_services.bsh" punk@26: punk@26: // Local includes punk@26: //`include "asim/provides/processor_library.bsh" (included above directly) punk@36: punk@26: `include "asim/provides/common_services.bsh" punk@26: `include "asim/dict/STATS_PROCESSOR.bsh" punk@26: `include "asim/provides/processor_library.bsh" punk@26: punk@26: // Local includes. Look for the correspondingly named .awb files punk@26: // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/ punk@26: // to find the actual Bluespec files which are used to generate punk@26: // these includes. These files are specific to this audio processing punk@26: // pipeline punk@26: punk@26: `include "asim/provides/audio_pipe_types.bsh" punk@26: punk@26: //interface CPUToHost; punk@26: // method Bit#(32) cpuToHost(int req); punk@26: //endinterface punk@26: punk@26: interface Proc; punk@26: punk@26: // Interface from processor to caches punk@26: interface Client#(DataReq,DataResp) dmem_client; punk@26: interface Client#(InstReq,InstResp) imem_client; punk@26: punk@26: // Interface for enabling/disabling statistics on the rest of the core punk@26: interface Get#(Bool) statsEn_get; punk@26: punk@26: // // Interface to host punk@26: // interface CPUToHost tohost; punk@26: punk@26: // Interface to Audio Pipeline punk@26: interface Get#(AudioProcessorUnit) sampleOutput; punk@36: interface Put#(AudioProcessorUnit) sampleInput; punk@26: punk@26: endinterface punk@26: punk@26: //The full interface for this is as below in the common file for audioProcessorTypes.bsv punk@26: //interface AudioOut; punk@26: // interface Get#(AudioProcessorUnit) audioSampleOutput; punk@26: //endinterface punk@26: punk@26: //interface AudioIn; punk@26: // interface Put#(AudioProcessorUnit) audioSampleInput; punk@26: //endinterface punk@26: punk@26: typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits); punk@26: punk@26: //----------------------------------------------------------- punk@26: // Register file module punk@26: //----------------------------------------------------------- punk@26: punk@26: interface BRFile; punk@26: method Action wr( Rindx rindx, Bit#(32) data ); punk@26: method Bit#(32) rd1( Rindx rindx ); punk@26: method Bit#(32) rd2( Rindx rindx ); punk@26: endinterface punk@26: punk@26: module mkBRFile( BRFile ); punk@26: punk@26: RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile(); punk@26: punk@26: method Action wr( Rindx rindx, Bit#(32) data ); punk@26: rfile.upd( rindx, data ); punk@26: endmethod punk@26: punk@26: method Bit#(32) rd1( Rindx rindx ); punk@26: return ( rindx == 0 ) ? 0 : rfile.sub(rindx); punk@26: endmethod punk@26: punk@26: method Bit#(32) rd2( Rindx rindx ); punk@26: return ( rindx == 0 ) ? 0 : rfile.sub(rindx); punk@26: endmethod punk@26: punk@26: endmodule punk@26: punk@26: //----------------------------------------------------------- punk@26: // Helper functions punk@26: //----------------------------------------------------------- punk@26: punk@26: function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 ); punk@26: return zeroExtend( pack( signedLT(val1,val2) ) ); punk@26: endfunction punk@26: punk@26: function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 ); punk@26: return zeroExtend( pack( val1 < val2 ) ); punk@26: endfunction punk@26: punk@26: function Bit#(32) rshft( Bit#(32) val ); punk@26: return zeroExtend(val[4:0]); punk@26: endfunction punk@26: punk@26: punk@26: //----------------------------------------------------------- punk@26: // Find funct for wbQ punk@26: //----------------------------------------------------------- punk@26: function Bool findwbf(Rindx fVal, WBResult cmpVal); punk@26: case (cmpVal) matches punk@26: tagged WB_ALU {data:.res, dest:.rd} : punk@26: return (fVal == rd); punk@26: tagged WB_Load .rd : punk@26: return (fVal == rd); punk@26: tagged WB_Store .st : punk@26: return False; punk@26: tagged WB_Host .x : punk@26: return False; punk@26: endcase punk@26: endfunction punk@26: punk@26: punk@26: //----------------------------------------------------------- punk@26: // Stall funct for wbQ punk@26: //----------------------------------------------------------- punk@26: function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f); punk@26: case (inst) matches punk@26: // -- Memory Ops ------------------------------------------------ punk@26: tagged LW .it : punk@26: return f.find(it.rbase); punk@26: tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} : punk@26: return (f.find(addr) || f.find2(dreg)); punk@26: punk@26: // -- Simple Ops ------------------------------------------------ punk@26: tagged ADDIU .it : return f.find(it.rsrc); punk@26: tagged SLTI .it : return f.find(it.rsrc); punk@26: tagged SLTIU .it : return f.find(it.rsrc); punk@26: tagged ANDI .it : return f.find(it.rsrc); punk@26: tagged ORI .it : return f.find(it.rsrc); punk@26: tagged XORI .it : return f.find(it.rsrc); punk@26: punk@26: tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself punk@26: tagged SLL .it : return f.find(it.rsrc); punk@26: tagged SRL .it : return f.find(it.rsrc); punk@26: tagged SRA .it : return f.find(it.rsrc); punk@26: tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt)); punk@26: tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt)); punk@26: tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt)); punk@26: tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: punk@26: punk@26: // -- Branches -------------------------------------------------- punk@26: punk@26: tagged BLEZ .it : return (f.find(it.rsrc)); punk@26: tagged BGTZ .it : return (f.find(it.rsrc)); punk@26: tagged BLTZ .it : return (f.find(it.rsrc)); punk@26: tagged BGEZ .it : return (f.find(it.rsrc)); punk@26: tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2)); punk@26: punk@26: // -- Jumps ----------------------------------------------------- punk@26: punk@26: tagged J .it : return False; punk@26: tagged JR .it : return f.find(it.rsrc); punk@26: tagged JALR .it : return f.find(it.rsrc); punk@26: tagged JAL .it : return False; punk@26: punk@26: // -- Cop0 ------------------------------------------------------ punk@26: punk@26: tagged MTC0 .it : return f.find(it.rsrc); punk@26: tagged MFC0 .it : return False; punk@26: punk@26: // -- Illegal --------------------------------------------------- punk@26: punk@26: default : return False; punk@26: punk@26: endcase punk@26: endfunction punk@26: //----------------------------------------------------------- punk@26: // Reference processor punk@26: //----------------------------------------------------------- punk@26: punk@26: punk@26: //(* doc = "synthesis attribute ram_style mkProc distributed;" *) punk@26: //(* synthesize *) punk@26: punk@26: module [CONNECTED_MODULE] mkProc( Proc ); punk@26: punk@26: //----------------------------------------------------------- punk@26: // State punk@26: punk@26: // Standard processor state punk@26: punk@26: Reg#(Addr) pc <- mkReg(32'h00001000); punk@26: Reg#(Epoch) epoch <- mkReg(0); punk@26: Reg#(Stage) stage <- mkReg(PCgen); punk@26: BRFile rf <- mkBRFile; punk@26: punk@26: // Branch Prediction punk@26: BranchPred bp <- mkBranchPred(); punk@26: FIFO#(PCStat) execpc <- mkLFIFO(); punk@26: punk@26: // Pipelines punk@26: FIFO#(PCStat) pcQ <-mkSizedFIFO(3); punk@26: SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf); punk@26: punk@36: // NEED TO ADD CAPABILITY FOR RESET (should be able to just say if I get valid in and these are flagged, clear them. punk@26: Reg#(Bit#(32)) cp0_tohost <- mkReg(0); punk@26: Reg#(Bit#(32)) cp0_fromhost <- mkReg(0); punk@26: Reg#(Bool) cp0_statsEn <- mkReg(False); punk@36: Reg#(Bool) cp0_audioEOF <- mkReg(False); // Register to let code that EOF is reached punk@36: Reg#(Bool) cp0_progComp <- mkReg(False); // Register to let processor know that the program is complete (as this terminates) punk@36: punk@26: // Memory request/response state punk@26: punk@26: FIFO#(InstReq) instReqQ <- mkBFIFO1(); punk@26: FIFO#(InstResp) instRespQ <- mkFIFO(); punk@26: punk@26: FIFO#(DataReq) dataReqQ <- mkBFIFO1(); punk@26: FIFO#(DataResp) dataRespQ <- mkFIFO(); punk@26: punk@26: // Audio I/O punk@26: FIFO#(AudioProcessorUnit) inAudioFifo <- mkFIFO; punk@26: FIFO#(AudioProcessorUnit) outAudioFifo <- mkFIFO; punk@26: punk@26: punk@26: // Statistics state (2010) punk@36: // Reg#(Stat) num_cycles <- mkReg(0); punk@36: // Reg#(Stat) num_inst <- mkReg(0); punk@26: punk@26: //Or: punk@26: // Statistics state punk@26: STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT); punk@26: STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT); punk@26: punk@26: //----------------------------------------------------------- punk@26: // Rules punk@26: punk@26: (* descending_urgency = "exec, pcgen" *) punk@26: rule pcgen; //( stage == PCgen ); punk@26: let pc_plus4 = pc + 4; punk@26: punk@26: traceTiny("mkProc", "pc",pc); punk@26: traceTiny("mkProc", "pcgen","P"); punk@26: instReqQ.enq( LoadReq{ addr:pc, tag:epoch} ); punk@26: punk@26: let next_pc = bp.get(pc); punk@26: if (next_pc matches tagged Valid .npc) punk@26: begin punk@26: pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch}); punk@26: pc <= npc; punk@26: end punk@26: else punk@26: begin punk@26: pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch}); punk@26: pc <= pc_plus4; punk@26: end punk@26: punk@26: endrule punk@26: punk@26: rule discard (instRespQ.first() matches tagged LoadResp .ld punk@26: &&& ld.tag != epoch); punk@26: traceTiny("mkProc", "stage", "D"); punk@26: instRespQ.deq(); punk@26: endrule punk@26: punk@26: (* conflict_free = "exec, writeback" *) punk@26: rule exec (instRespQ.first() matches tagged LoadResp.ld punk@26: &&& (ld.tag == epoch) punk@26: &&& unpack(ld.data) matches .inst punk@26: &&& !stall(inst, wbQ)); punk@26: punk@26: // Some abbreviations punk@26: let sext = signExtend; punk@26: let zext = zeroExtend; punk@26: let sra = signedShiftRight; punk@26: punk@26: // Get the instruction punk@26: punk@26: instRespQ.deq(); punk@26: Instr inst punk@26: = case ( instRespQ.first() ) matches punk@26: tagged LoadResp .ld : return unpack(ld.data); punk@26: tagged StoreResp .st : return ?; punk@26: endcase; punk@26: punk@26: // Get the PC info punk@26: let instrpc = pcQ.first().qpc; punk@26: let pc_plus4 = instrpc + 4; punk@26: punk@26: Bool branchTaken = False; punk@26: Addr newPC = pc_plus4; punk@26: punk@26: // Tracing punk@26: traceTiny("mkProc", "exec","X"); punk@26: traceTiny("mkProc", "exInstTiny",inst); punk@26: traceFull("mkProc", "exInstFull",inst); punk@26: punk@26: case ( inst ) matches punk@26: punk@26: // -- Memory Ops ------------------------------------------------ punk@26: punk@26: tagged LW .it : punk@26: begin punk@26: Addr addr = rf.rd1(it.rbase) + sext(it.offset); punk@26: dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } ); punk@26: wbQ.enq(tagged WB_Load it.rdst); punk@26: end punk@26: punk@26: tagged SW .it : punk@26: begin punk@26: Addr addr = rf.rd1(it.rbase) + sext(it.offset); punk@26: dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } ); punk@26: wbQ.enq(tagged WB_Store); punk@26: end punk@26: punk@26: // -- Simple Ops ------------------------------------------------ punk@26: punk@26: tagged ADDIU .it : punk@26: begin punk@26: Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm); punk@26: wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst}); punk@26: end punk@26: tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )}); punk@26: tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) }); punk@26: tagged ANDI .it : punk@26: begin punk@26: Bit#(32) zext_it_imm = zext(it.imm); punk@26: wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} ); punk@26: end punk@26: tagged ORI .it : punk@26: begin punk@26: Bit#(32) zext_it_imm = zext(it.imm); punk@26: wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} ); punk@26: end punk@26: tagged XORI .it : punk@26: begin punk@26: Bit#(32) zext_it_imm = zext(it.imm); punk@26: wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )}); punk@26: end punk@26: tagged LUI .it : punk@26: begin punk@26: Bit#(32) zext_it_imm = zext(it.imm); punk@26: wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) }); punk@26: end punk@26: punk@26: tagged SLL .it : punk@26: begin punk@26: Bit#(32) zext_it_shamt = zext(it.shamt); punk@26: wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} ); punk@26: end punk@26: tagged SRL .it : punk@26: begin punk@26: Bit#(32) zext_it_shamt = zext(it.shamt); punk@26: wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )}); punk@26: end punk@26: tagged SRA .it : punk@26: begin punk@26: Bit#(32) zext_it_shamt = zext(it.shamt); punk@26: wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )}); punk@26: end punk@26: tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )}); punk@26: tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} ); punk@26: tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) }); punk@26: tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} ); punk@26: tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} ); punk@26: tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} ); punk@26: tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} ); punk@26: tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} ); punk@26: tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} ); punk@26: tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) }); punk@26: tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) }); punk@26: punk@26: // -- Branches -------------------------------------------------- punk@26: punk@26: tagged BLEZ .it : punk@26: if ( signedLE( rf.rd1(it.rsrc), 0 ) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged BGTZ .it : punk@26: if ( signedGT( rf.rd1(it.rsrc), 0 ) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged BLTZ .it : punk@26: if ( signedLT( rf.rd1(it.rsrc), 0 ) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged BGEZ .it : punk@26: if ( signedGE( rf.rd1(it.rsrc), 0 ) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged BEQ .it : punk@26: if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged BNE .it : punk@26: if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) ) punk@26: begin punk@26: newPC = pc_plus4 + (sext(it.offset) << 2); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: // -- Jumps ----------------------------------------------------- punk@26: punk@26: tagged J .it : punk@26: begin punk@26: newPC = { pc_plus4[31:28], it.target, 2'b0 }; punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged JR .it : punk@26: begin punk@26: newPC = rf.rd1(it.rsrc); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged JAL .it : punk@26: begin punk@26: wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 }); punk@26: newPC = { pc_plus4[31:28], it.target, 2'b0 }; punk@26: branchTaken = True; punk@26: end punk@26: punk@26: tagged JALR .it : punk@26: begin punk@26: wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 }); punk@26: newPC = rf.rd1(it.rsrc); punk@26: branchTaken = True; punk@26: end punk@26: punk@26: // -- Cop0 ------------------------------------------------------ punk@26: punk@36: tagged MTC0 .it : //Recieve things from host computer punk@26: begin punk@36: $display( " PROCESSOR MTC0 call\n"); punk@26: case ( it.cop0dst ) punk@26: 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc))); punk@26: 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc)); punk@36: 5'd26 : cp0_progComp <= unpack(truncate(rf.rd1(it.rsrc))); //states audio program completed and termination okay punk@36: 5'd27 : outAudioFifo.enq(tagged Sample unpack(truncate(rf.rd1(it.rsrc)))); //Bit size is 16 not 32 punk@26: default : punk@26: $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" ); punk@26: endcase punk@26: wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be. punk@26: end punk@26: punk@26: //this is host stuff? punk@36: tagged MFC0 .it : //Things out punk@26: begin punk@36: $display( " PROCESSOR MFC0 call\n"); punk@26: case ( it.cop0src ) punk@26: // not actually an ALU instruction but don't have the format otherwise punk@26: 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) }); punk@26: 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost }); punk@26: 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost }); punk@36: 5'd25 : begin punk@36: $display( "**** EOF Requested\n "); punk@36: wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_audioEOF)) }); // Reading clears bit punk@36: cp0_audioEOF <= False; punk@36: end punk@36: 5'd28 : begin punk@36: $display( "***** Reqesting Sample \n"); punk@36: let sample = inAudioFifo.first(); // is this going to cause perf. delay? punk@36: if (sample matches tagged Sample .audio) // if it is EOF another rule sets the cp0_audioEOF punk@36: wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(audio)) }); // do I need pack? punk@36: else $display ( "Audio File EOF Reached. Invalid sample request."); punk@36: inAudioFifo.deq(); punk@36: end punk@26: default : punk@26: $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" ); punk@26: endcase punk@26: end punk@26: punk@26: // -- Illegal --------------------------------------------------- punk@26: punk@26: default : punk@26: $display( " RTL-ERROR : %m : Illegal instruction !" ); punk@26: punk@26: endcase punk@26: punk@26: //evaluate branch prediction punk@26: Addr ppc = pcQ.first().qnxtpc; //predicted branch punk@26: if (ppc != newPC) //prediction wrong punk@26: begin punk@26: epoch <= pcQ.first().qepoch + 1; punk@26: bp.upd(instrpc, newPC); //update branch predictor punk@26: pcQ.clear(); punk@26: pc <= newPC; punk@26: end punk@26: else punk@26: pcQ.deq(); punk@26: punk@26: if ( cp0_statsEn ) punk@26: num_inst.incr(); punk@26: punk@26: endrule punk@26: punk@26: rule writeback; // ( stage == Writeback ); punk@26: traceTiny("mkProc", "writeback","W"); punk@26: punk@26: punk@26: // get what to do off the writeback queue punk@26: wbQ.deq(); punk@26: case (wbQ.first()) matches punk@26: tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res); punk@26: tagged WB_Load .regWr : punk@26: begin punk@26: dataRespQ.deq(); punk@26: if (dataRespQ.first() matches tagged LoadResp .ld) punk@26: rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate? punk@26: end punk@26: tagged WB_Store : dataRespQ.deq(); punk@26: tagged WB_Host .dat : noAction; punk@26: endcase punk@26: punk@26: endrule punk@26: punk@26: rule inc_num_cycles; punk@26: if ( cp0_statsEn ) punk@26: num_cycles.incr(); punk@26: endrule punk@26: punk@36: punk@36: // for now, we don't do anything. punk@36: // rule connectAudioReqResp; punk@36: // $display("rlm: PROCESSOR copies a datum\n"); punk@36: // outAudioFifo.enq(inAudioFifo.first()); punk@36: // inAudioFifo.deq; punk@36: // endrule punk@36: punk@36: rule flagAudioEnd (inAudioFifo.first() matches tagged EndOfFile); punk@36: $display (" Proc Says End Audio Flag Set "); punk@36: cp0_audioEOF <= True; punk@36: inAudioFifo.deq; punk@26: endrule punk@26: punk@36: rule sendAudioEnd (cp0_progComp); punk@36: $display (" PROCESSOR Says Program Complete "); punk@36: outAudioFifo.enq(tagged EndOfFile); punk@36: cp0_progComp <= False; //only send one. And functions to reset punk@26: endrule punk@26: punk@26: punk@26: //----------------------------------------------------------- punk@26: // Methods punk@26: punk@26: interface Client imem_client; punk@26: interface Get request = fifoToGet(instReqQ); punk@26: interface Put response = fifoToPut(instRespQ); punk@26: endinterface punk@26: punk@26: interface Client dmem_client; punk@26: interface Get request = fifoToGet(dataReqQ); punk@26: interface Put response = fifoToPut(dataRespQ); punk@26: endinterface punk@26: punk@26: interface Get statsEn_get = toGet(asReg(cp0_statsEn)); punk@26: punk@36: /* punk@36: interface CPUToHost tohost; punk@36: method Bit#(32) cpuToHost(int req); punk@36: return (case (req) punk@36: 0: cp0_tohost; punk@36: 1: pc; punk@36: 2: zeroExtend(pack(stage)); punk@36: endcase); punk@36: endmethod punk@36: endinterface punk@36: */ punk@36: punk@26: interface Get sampleOutput = fifoToGet(outAudioFifo); punk@36: interface Put sampleInput = fifoToPut(inAudioFifo); punk@26: punk@26: endmodule punk@26: