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