diff --git a/builds/Resources/Include_Common.mk b/builds/Resources/Include_Common.mk index 329695bb..ded06c56 100644 --- a/builds/Resources/Include_Common.mk +++ b/builds/Resources/Include_Common.mk @@ -113,6 +113,15 @@ run_example: $(TESTS_DIR)/elf_to_hex/elf_to_hex $(EXAMPLE) Mem.hex ./exe_HW_sim $(VERBOSITY) +exit +# ================================================================ +# Generate konata output + +.PHONY: generate_konata +generate_konata: + grep "KONATA" output.txt > koutput.txt + cut -c7- koutput.txt > klog.txt + ./../Resources/parse_pre_kanata.py klog.txt > k.log + # ================================================================ # Test: run the executable on the standard RISCV ISA test specified in TEST diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 6c0ea47c..215d72f9 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -660,6 +660,7 @@ module mkCore#(CoreId coreId)(Core); interface robIfc = rob; interface rtIfc = regRenamingTable; interface csrfIfc = csrf; + interface rsIfc = renameStage; method stbEmpty = stb.isEmpty; method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 971ff221..47060a80 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -584,6 +584,8 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(Data) mimpid_csr = readOnlyReg(0); // mhartid Reg#(Data) mhartid_csr = readOnlyReg(hartid); + // machine thread ID + Reg#(Data) mtid_csr <- mkCsrReg(0); // Supervisor level CSRs // sstatus: restricted view of mstatus @@ -673,7 +675,13 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(Bit#(44)) ppn_reg <- mkCsrReg(0); Reg#(Data) satp_csr = concatReg3(vm_mode_reg, full_asid_reg, ppn_reg); + // supervisor thread ID + Reg#(Data) stid_csr <- mkCsrReg(0); + // User level CSRs + + // user thread ID + Reg#(Data) utid_csr <- mkCsrReg(0); // According to spike, any write to fflags/frm/fcsr will set fs_reg as // dirty, regardless of whether the write truly changes value or not. // Besides, any non-zero FP exception flags will also make fs_reg dirty. @@ -815,18 +823,21 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(CapReg) ddc_reg <- mkCsrReg(defaultValue); // User level SCRs with accessSysRegs + Reg#(CapReg) utidc_reg <- mkCsrReg(nullCap); // Reg#(CapReg) utcc_reg <- mkCsrReg(defaultValue); // Reg#(CapReg) utdc_reg <- mkCsrReg(nullCap); // Reg#(CapReg) uScratchC_reg <- mkCsrReg(nullCap); // Reg#(CapReg) uepcc_reg <- mkCsrReg(defaultValue); // System level SCRs with accessSysRegs + Reg#(CapReg) stidc_reg <- mkCsrReg(nullCap); Reg#(CapReg) stcc_reg <- mkCsrReg(defaultValue); Reg#(CapReg) stdc_reg <- mkCsrReg(nullCap); Reg#(CapReg) sScratchC_reg <- mkCsrReg(nullCap); Ehr#(2, CapReg) sepcc_reg <- mkConfigEhr(defaultValue); // Machine level SCRs with accessSysRegs + Reg#(CapReg) mtidc_reg <- mkCsrReg(nullCap); Reg#(CapReg) mtcc_reg <- mkCsrReg(defaultValue); Reg#(CapReg) mtdc_reg <- mkCsrReg(nullCap); Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap); @@ -869,6 +880,7 @@ module mkCsrFile #(Data hartid)(CsrFile); csrAddrINSTRET: instret_csr; csrAddrTERMINATE: terminate_csr; csrAddrSTATS: stats_csr; + csrAddrUTID: utid_csr; // Supervisor CSRs csrAddrSSTATUS: sstatus_csr; csrAddrSIE: sie_csr; @@ -881,6 +893,7 @@ module mkCsrFile #(Data hartid)(CsrFile); csrAddrSIP: sip_csr; csrAddrSATP: satp_csr; csrAddrSCCSR: sccsr_csr; + csrAddrSTID: stid_csr; // Machine CSRs csrAddrMSTATUS: mstatus_csr; csrAddrMISA: misa_csr; @@ -901,6 +914,7 @@ module mkCsrFile #(Data hartid)(CsrFile); csrAddrMIMPID: mimpid_csr; csrAddrMHARTID: mhartid_csr; csrAddrMCCSR: mccsr_csr; + csrAddrMTID: mtid_csr; `ifdef PERFORMANCE_MONITORING //csrAddrMCOUNTERINHIBIT: perf_counters.inhibit; csrAddrMCOUNTERINHIBIT: mcountinhibit_reg; @@ -940,16 +954,19 @@ module mkCsrFile #(Data hartid)(CsrFile); // User SCRs scrAddrDDC: ddc_reg; // User CSRs with accessSysRegs + scrAddrUTIDC: utidc_reg; // scrAddrUTCC: utcc_reg; // scrAddrUTDC: utdc_reg; // scrAddrUScratchC: uScratchC_reg; // scrAddrUEPCC: uepcc_reg; // System CSRs with accessSysRegs + scrAddrSTIDC: stidc_reg; scrAddrSTCC: stcc_reg; scrAddrSTDC: stdc_reg; scrAddrSScratchC: sScratchC_reg; scrAddrSEPCC: sepcc_reg[1]; // Machine CSRs with accessSysRegs + scrAddrMTIDC: mtidc_reg; scrAddrMTCC: mtcc_reg; scrAddrMTDC: mtdc_reg; scrAddrMScratchC: mScratchC_reg; diff --git a/src_Core/ISA/SCRs.bsvi b/src_Core/ISA/SCRs.bsvi index b91be940..b7e44eb1 100644 --- a/src_Core/ISA/SCRs.bsvi +++ b/src_Core/ISA/SCRs.bsvi @@ -1,16 +1,20 @@ `SCR(PCC, 5'd00) `SCR(DDC, 5'd01) +`SCR(UTIDC, 5'd03) + //`SCR(UTCC, 5'd0) //`SCR(UTDC, 5'd05) //`SCR(UScratchC, 5'd06) //`SCR(UEPCC, 5'd07) +`SCR(STIDC, 5'd11) `SCR(STCC, 5'd12) `SCR(STDC, 5'd13) `SCR(SScratchC, 5'd14) `SCR(SEPCC, 5'd15) +`SCR(MTIDC, 5'd27) `SCR(MTCC, 5'd28) `SCR(MTDC, 5'd29) `SCR(MScratchC, 5'd30) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 81d4b992..9e571b75 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -66,6 +66,7 @@ import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; import RegFile::*; // Just for the interface +import RenameStage::*; `ifdef PERFORMANCE_MONITORING import StatCounters::*; `endif @@ -111,6 +112,7 @@ interface CommitInput; interface ReorderBufferSynth robIfc; interface RegRenamingTable rtIfc; interface CsrFile csrfIfc; + interface RenameStage rsIfc; // no stores method Bool stbEmpty; method Bool stqEmpty; @@ -297,7 +299,7 @@ deriving (Eq, FShow, Bits); `endif module mkCommitStage#(CommitInput inIfc)(CommitStage); - Bool verbose = False; + Bool verbose = True; Integer verbosity = 0; // Bluespec: for lightweight verbosity trace @@ -899,6 +901,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); !isValid(rob.deqPort[0].deq_data.ldKilled) && rob.deqPort[0].deq_data.rob_inst_state == Executed && isSystem(rob.deqPort[0].deq_data.iType) && + !rob.deqPort[0].deq_data.isPureDataRead && (! send_mip_csr_change_to_tv) ); rob.deqPort[0].deq; @@ -1100,7 +1103,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && rob.deqPort[0].deq_data.rob_inst_state == Executed && - !isSystem(rob.deqPort[0].deq_data.iType) && + !(isSystem(rob.deqPort[0].deq_data.iType) && !rob.deqPort[0].deq_data.isPureDataRead) && (! send_mip_csr_change_to_tv) ); // stop superscalar commit after we @@ -1169,7 +1172,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); let inst_tag = rob.deqPort[i].getDeqInstTag; // check can be committed or not - if(x.rob_inst_state != Executed || isValid(x.ldKilled) || isValid(x.trap) || isSystem(x.iType)) begin + if(x.rob_inst_state != Executed || isValid(x.ldKilled) || isValid(x.trap) || (isSystem(x.iType) && !x.isPureDataRead)) begin // inst not ready for commit, or system inst, or trap, or killed, stop here stop = True; end @@ -1307,7 +1310,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); if (opcode == opcMiscMem && funct3 == fnFENCE) fenceCnt = fenceCnt + 1; `ifdef KONATA case(x.iType) - Alu, J, Jr, Br, Auipc, Auipcc, CCall, CJAL, CJALR, Cap: begin + Alu, J, Jr, Br, Auipc, Auipcc, CCall, CJAL, CJALR, Cap, Csr, Scr: begin $display("KONATAE\t%0d\t%0d\t0\tAlu4", cur_cycle, x.u_id); $display("KONATAS\t%0d\t%0d\t0\tC", cur_cycle, x.u_id); $fflush; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index d935830a..a7f0f909 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -73,6 +73,7 @@ import ConfigReg::*; import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; +import Ehr::*; `ifdef PERFORMANCE_MONITORING import StatCounters::*; import DReg::*; @@ -115,6 +116,7 @@ endinterface interface RenameStage; // performance count method Data getPerf(ExeStagePerfType t); + method Action checkCSRWrite(CSR csr); `ifdef PERFORMANCE_MONITORING method EventsTransExe events; @@ -131,7 +133,7 @@ interface RenameStage; endinterface module mkRenameStage#(RenameInput inIfc)(RenameStage); - Bool verbose = False; + Bool verbose = True; Integer verbosity = 0; // func units @@ -148,6 +150,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); ReservationStationMem reservationStationMem = inIfc.rsMemIfc; SplitLSQ lsq = inIfc.lsqIfc; + Ehr#(2, PhyRIndx) wcount_stid <- mkEhr(0); + // performance counter Count#(Data) supRenameCnt <- mkCount(0); `ifdef PERF_COUNT @@ -394,7 +398,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); lsqAtCommitNotified: False, nonMMIOStDone: False, epochIncremented: True, // we have incremented epoch - spec_bits: specTagManager.currentSpecBits + spec_bits: specTagManager.currentSpecBits, + isPureDataRead: False // not relevant `ifdef RVFI_DII , dii_pid: x.dii_pid `endif @@ -481,7 +486,12 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); endfunction // check for system inst that needs to replay - Bool firstReplay = doReplay(fetchStage.pipelines[0].first.dInst.iType); + //Bool pureDataInst = isPureDataCSR(fetchStage.pipelines[0].first.dInst); + //Bool csrRead = isCSRRead(fetchStage.pipelines[0].first.regs, fetchStage.pipelines[0].first.dInst); + //Bool csrWrite = isCSRWrite(fetchStage.pipelines[0].first.regs, fetchStage.pipelines[0].first.dInst); + Bool pureDataRead = isPureDataRead(fetchStage.pipelines[0].first.regs, fetchStage.pipelines[0].first.dInst); + Bool firstReplay = (doReplay(fetchStage.pipelines[0].first.dInst.iType) && !pureDataRead); + // System inst is renamed only when ROB is empty rule doRenaming_SystemInst( @@ -531,6 +541,13 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); sbCons.setBusy[0].set(phy_regs.dst); sbAggr.setBusy[0].set(phy_regs.dst); + // on a CSR Write we increase the counter + if(isCSRWrite(arch_regs, dInst) &&& dInst.csr matches tagged Valid .c) begin + if (c == csrAddrSTID || c == csrAddrUTID) begin + wcount_stid[0] <= wcount_stid[0] + 1; + end + end + // print rename info if (verbose) begin printRename(0, regs_ready_cons, regs_ready_aggr, arch_regs, phy_regs); @@ -619,7 +636,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); lsqAtCommitNotified: False, nonMMIOStDone: False, epochIncremented: True, // system inst has incremented epoch - spec_bits: spec_bits + spec_bits: spec_bits, + isPureDataRead: False `ifdef RVFI_DII , dii_pid: x.dii_pid `endif @@ -813,7 +831,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); lsqAtCommitNotified: False, nonMMIOStDone: False, epochIncremented: False, - spec_bits: spec_bits + spec_bits: spec_bits, + isPureDataRead: False // mem inst are no pure data reads `ifdef RVFI_DII , dii_pid: x.dii_pid `endif @@ -864,7 +883,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); !inIfc.pendingMMIOPRq // stall when MMIO pRq is pending && epochManager.checkEpoch[0].check(fetchStage.pipelines[0].first.main_epoch) // correct path && !isValid(firstTrap) // not trap - && !firstReplay // not system inst + && !(firstReplay && !pureDataRead) // not system inst `ifdef SECURITY // stall for ROB empty if we don't allow speculation at all && (!specNone || rob.isEmpty) @@ -947,8 +966,15 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); if(isValid(getTrap(x))) begin stop = True; end + if(dInst.csr matches tagged Valid .c) begin + stop = (case (c) + csrAddrSTID, csrAddrUTID: (wcount_stid[0] > 0); + // think about updating! + default: True; + endcase); + end // for system inst, process in next cycle (in a different rule) - if(doReplay(dInst.iType)) begin + if(doReplay(dInst.iType) && !isPureDataRead(arch_regs, dInst)) begin stop = True; end `ifdef SECURITY @@ -1209,7 +1235,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); lsqAtCommitNotified: False, nonMMIOStDone: False, epochIncremented: False, - spec_bits: spec_bits + spec_bits: spec_bits, + isPureDataRead: isPureDataRead(arch_regs, dInst) `ifdef RVFI_DII , dii_pid: x.dii_pid `endif @@ -1295,6 +1322,13 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); endcase); endmethod + method Action checkCSRWrite(CSR csr); + case (csr) + csrAddrSTID: wcount_stid[1] <= wcount_stid[1] - 1; + default: noAction; + endcase + endmethod + `ifdef PERFORMANCE_MONITORING method events = events_reg; `endif diff --git a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi index fd793ea9..7b5cb07b 100644 --- a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi @@ -2,6 +2,7 @@ `CSR(FFLAGS, 12'h001) `CSR(FRM, 12'h002) `CSR(FCSR, 12'h003) +`CSR(UTID, 12'h080) `CSR(CYCLE, 12'hc00) `CSR(TIME, 12'hc01) `CSR(INSTRET, 12'hc02) @@ -21,6 +22,7 @@ `CSR(STVAL, 12'h143) // it's still called sbadaddr in spike `CSR(SIP, 12'h144) `CSR(SATP, 12'h180) // it's still called sptbr in spike +`CSR(STID, 12'h580) `CSR(SCCSR, 12'h9c0) // machine standard CSRs `CSR(MSTATUS, 12'h300) @@ -35,6 +37,7 @@ `CSR(MCAUSE, 12'h342) `CSR(MTVAL, 12'h343) // it's still called mbadaddr in spike `CSR(MIP, 12'h344) +`CSR(MTID, 12'h380) `CSR(MCYCLE, 12'hb00) `CSR(MINSTRET, 12'hb02) diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index c4089361..f11eb397 100644 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -526,7 +526,10 @@ function Maybe#(Trap) checkForException( || (csr == pack(csrAddrFCSR)) || (csr == pack(csrAddrCYCLE) && !writes_csr) || (csr == pack(csrAddrTIME) && !writes_csr) - || (csr == pack(csrAddrINSTRET) && !writes_csr); + || (csr == pack(csrAddrINSTRET) && !writes_csr) + || (csr == pack(csrAddrUTID) && !writes_csr) + || (csr == pack(csrAddrSTID) && !writes_csr) + || (csr == pack(csrAddrMTID) && !writes_csr); Bool unimplemented = (csr == pack(csrAddrNone)); // Added by Bluespec if (write_deny || !csr_has_priv || unimplemented) begin exception = Valid (Exception (excIllegalInst)); @@ -540,8 +543,12 @@ function Maybe#(Trap) checkForException( Bool writes_scr = regs.src1 == Valid (tagged Gpr 0) ? False : True; Bool read_only = (scr == scrAddrPCC); Bool write_deny = (writes_scr && read_only); - Bool asr_allow = getHardPerms(pcc).accessSysRegs || - scr == scrAddrDDC || scr == scrAddrPCC; + Bool asr_allow = getHardPerms(pcc).accessSysRegs + || scr == scrAddrDDC + || scr == scrAddrPCC + || (scr == scrAddrUTIDC && !writes_scr) + || (scr == scrAddrSTIDC && !writes_scr) + || (scr == scrAddrMTIDC && !writes_scr); if(!scr_has_priv || unimplemented || write_deny) begin exception = Valid (Exception (excIllegalInst)); end else if (!asr_allow) begin diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index ba191ad3..87547251 100644 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -874,6 +874,50 @@ function Bool isSystem(IType iType) = ( // instruction commits) function Bool doReplay(IType iType) = isSystem(iType); +function Bool isPureDataRead(ArchRegs regs, DecodedInst dInst) = (isPureDataCSR(dInst) && isCSRRead(regs, dInst) && !(isCSRWrite(regs, dInst))); + +function Bool isPureDataCSR(DecodedInst dInst); + if(dInst.csr matches tagged Valid .c) begin + case (c) + csrAddrSTID, csrAddrUTID: return True; + default: return False; + endcase + end + else return False; +endfunction + +function Bool isCSRRead(ArchRegs regs, DecodedInst dInst); + Bool ret = False; + if(dInst.execFunc matches tagged Alu .alu_func) begin + ret = (case (alu_func) + Csrw, Csrc, Csrs: True; + default: False; + endcase); + end + if(regs.dst matches tagged Valid .d) begin + if(d matches tagged Gpr .gpr) ret = ret && (gpr != 0); + else ret = False; + end + else ret = False; + return ret; +endfunction + +function Bool isCSRWrite(ArchRegs regs, DecodedInst dInst); + Bool ret = False; + if(dInst.execFunc matches tagged Alu .alu_func) begin + ret = (case (alu_func) + Csrw, Csrc, Csrs: True; + default: False; + endcase); + end + if(regs.src1 matches tagged Valid .s) begin + if(s matches tagged Gpr .gpr) ret = ret && (gpr != 0); + else ret = False; + end + else ret = False; + return ret; +endfunction + function Bool isFpuInst(IType iType) = (iType == Fpu); function Bool isMemInst(IType iType) = ( diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index 67536ae9..1006c555 100644 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -116,6 +116,7 @@ typedef struct { // speculation SpecBits spec_bits; + Bool isPureDataRead; `ifdef RVFI_DII Dii_Parcel_Id dii_pid; `endif @@ -284,6 +285,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p Ehr#(2, Bool) nonMMIOStDone <- mkEhr(?); Reg#(Bool) epochIncremented <- mkRegU; Ehr#(3, SpecBits) spec_bits <- mkEhr(?); + Reg#(Bool) isPureDataRead <- mkRegU; `ifdef RVFI_DII Reg#(Dii_Parcel_Id) dii_pid <- mkRegU; `endif @@ -439,6 +441,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p rob_inst_state[state_enq_port] <= x.rob_inst_state; epochIncremented <= x.epochIncremented; spec_bits[sb_enq_port] <= x.spec_bits; + isPureDataRead <= x.isPureDataRead; `ifdef INORDER_CORE // in-order core enqs to LSQ later, so don't set LSQ tag; and other // flags should default to false @@ -495,7 +498,8 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p `ifdef RVFI traceBundle: traceBundle[traceBundle_deq_port], `endif - spec_bits: spec_bits[sb_deq_port] + spec_bits: spec_bits[sb_deq_port], + isPureDataRead: isPureDataRead `ifdef KONATA , u_id: uid `endif