From 3543056f82954b6b5c204badf7994ddaed97b03e Mon Sep 17 00:00:00 2001 From: gameboo Date: Fri, 28 Jan 2022 12:13:26 +0000 Subject: [PATCH 1/7] Added a CORE_MINI configuration (with @jdw57) --- .../RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv index 871a586..d84e1ae 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv @@ -167,6 +167,30 @@ // ==== CORE SIZE ==== // +`ifdef CORE_MINI + + // superscalar + `define sizeSup 2 + + // ROB + `define ROB_SIZE 32 + + // speculation + `define NUM_EPOCHS 4 + `define NUM_SPEC_TAGS 4 + + // LSQ + `define LDQ_SIZE 8 + `define STQ_SIZE 4 + `define SB_SIZE 2 + + // reservation station sizes + `define RS_ALU_SIZE 8 + `define RS_MEM_SIZE 4 + `define RS_FPUMULDIV_SIZE 4 + +`endif + `ifdef CORE_TINY // superscalar From c1c4a46b1ec467a1d88800811121e296a6f9f693 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Thu, 9 Dec 2021 12:27:57 +0000 Subject: [PATCH 2/7] Simpelest strategy for making wrongSpec not conflict with loads of rules. This triggers some assertions in the ROB what should be dealt with properly if this is going to work. --- .../RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv index f17bb98..dbdf7c1 100644 --- a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv +++ b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv @@ -1,6 +1,6 @@ // Copyright (c) 2017 Massachusetts Institute of Technology -// +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -8,10 +8,10 @@ // modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -26,6 +26,13 @@ import HasSpecBits::*; import GetPut::*; import Vector::*; import ReorderBuffer::*; +import FIFO::*; + +typedef struct { + Bool kill_all; + SpecTag spec_tag; + InstTag inst_tag; +} IncorrectSpec deriving(Bits, Eq, FShow); interface GlobalSpecUpdate#(numeric type correctSpecPortNum, numeric type conflictWrongSpecPortNum); interface Vector#(correctSpecPortNum, Put#(SpecTag)) correctSpec; @@ -50,6 +57,9 @@ module mkGlobalSpecUpdate#( Vector#(correctSpecPortNum, RWire#(void)) spec_conflict <- replicateM(mkRWire); // let the caller of conflictWrongSpec to be conflict with wrong spec Vector#(conflictWrongSpecPortNum, RWire#(void)) wrongSpec_conflict <- replicateM(mkRWire); + // must be a single-element fifo to ensure all pushing rules cannot fire while we are waiting + // to kill. + FIFO#(IncorrectSpec) incorrectSpec_ff <- mkFIFO1; (* fire_when_enabled, no_implicit_conditions *) rule canon_correct_spec; @@ -63,6 +73,20 @@ module mkGlobalSpecUpdate#( rob.correctSpeculation(mask); endrule + rule do_incorrect_spec; + IncorrectSpec x <- toGet(incorrectSpec_ff).get; + ifc.incorrectSpeculation(x.kill_all, x.spec_tag); + rob.incorrectSpeculation(x.kill_all, x.spec_tag, x.inst_tag); + // conflict with correct spec + for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin + spec_conflict[i].wset(?); + end + // conflict with the caller of conflictWrongSpec + for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin + wrongSpec_conflict[i].wset(?); + end + endrule + Vector#(correctSpecPortNum, Put#(SpecTag)) correctVec = ?; for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin correctVec[i] = (interface Put; @@ -85,18 +109,8 @@ module mkGlobalSpecUpdate#( interface correctSpec = correctVec; - method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag); - ifc.incorrectSpeculation(kill_all, spec_tag); - rob.incorrectSpeculation(kill_all, spec_tag, inst_tag); - // conflict with correct spec - for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin - spec_conflict[i].wset(?); - end - // conflict with the caller of conflictWrongSpec - for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin - wrongSpec_conflict[i].wset(?); - end - endmethod + method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag) + = incorrectSpec_ff.enq(IncorrectSpec{kill_all: kill_all, spec_tag: spec_tag, inst_tag: inst_tag}); interface conflictWrongSpec = conflictWrongVec; endmodule From 4fbb7b56480a715ea591d9c308d4f2032171c790 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Tue, 11 Jan 2022 00:06:49 +0000 Subject: [PATCH 3/7] A version that seems to actually run. The buffer in GlobalSpecUpdate has to be a SpecFifo. --- src_Core/CPU/Core.bsv | 9 ++- .../procs/RV64G_OOO/AluExePipeline.bsv | 6 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 13 +-- .../RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv | 37 +++++---- .../RISCY_OOO/procs/lib/ReorderBuffer.bsv | 6 +- src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv | 5 ++ src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv | 80 ++++--------------- 7 files changed, 65 insertions(+), 91 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 7172cf9..5c29e37 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -223,6 +223,7 @@ interface CoreFixPoint; interface MemExePipeline memExeIfc; method Action killAll; // kill everything: used by commit stage interface Reg#(Bool) doStatsIfc; + method Bool pendingIncorrectSpec; endinterface `ifdef CONTRACTS_VERIFY @@ -412,7 +413,7 @@ module mkCore#(CoreId coreId)(Core); method setRegReadyAggr = writeAggr(aluWrAggrPort(i)); interface sendBypass = sendBypassIfc; method writeRegFile = writeCons(aluWrConsPort(i)); - method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag); + method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); if (verbose) begin $display("[ALU redirect - %d] ", i, fshow(new_pc), "; ", fshow(spec_tag), "; ", fshow(inst_tag)); @@ -423,7 +424,7 @@ module mkCore#(CoreId coreId)(Core); , inst_tag.dii_next_pid `endif ); - globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag); + globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag, spec_bits); endmethod method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put; method doStats = doStatsReg._read; @@ -510,9 +511,10 @@ module mkCore#(CoreId coreId)(Core); interface fpuMulDivExeIfc = fpuMulDivExe; interface memExeIfc = memExe; method Action killAll; - globalSpecUpdate.incorrectSpec(True, ?, ?); + globalSpecUpdate.incorrectSpec(True, ?, ?, 0); endmethod interface doStatsIfc = doStatsReg; + method pendingIncorrectSpec = globalSpecUpdate.pendingIncorrectSpec; endmodule CoreFixPoint coreFix <- moduleFix(mkCoreFixPoint); @@ -647,6 +649,7 @@ module mkCore#(CoreId coreId)(Core); method stbEmpty = stb.isEmpty; method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; + method pauseCommit = coreFix.pendingIncorrectSpec; method tlbNoPendingReq = iTlb.noPendingReq && dTlb.noPendingReq; method setFlushTlbs; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index b39fc2c..acb59be 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -194,7 +194,7 @@ interface AluExeInput; // write reg file & set conservative sb method Action writeRegFile(PhyRIndx dst, CapPipe data); // redirect - method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag); + method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); // spec update method Action correctSpec(SpecTag t); @@ -469,7 +469,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); if (x.controlFlow.mispredict) (* nosplit *) begin // wrong branch predictin, we must have spec tag doAssert(isValid(x.spec_tag), "mispredicted branch must have spec tag"); - inIfc.redirect(cast(x.controlFlow.nextPc), validValue(x.spec_tag), x.tag); + inIfc.redirect(cast(x.controlFlow.nextPc), validValue(x.spec_tag), x.tag, exeToFin.spec_bits); // must be a branch, train branch predictor doAssert(x.iType == Jr || x.iType == CJALR || x.iType == CCall || x.iType == Br, "only jr, br, cjalr, and ccall can mispredict"); inIfc.fetch_train_predictors(FetchTrainBP { @@ -481,6 +481,8 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); mispred: True, isCompressed: x.isCompressed }); + $display("alu mispredict pc¤: %x, nextPc: %x, %d", + x.controlFlow.pc, x.controlFlow.nextPc, cur_cycle); `ifdef PERF_COUNT // performance counter if(inIfc.doStats) begin diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 4e743fc..cdc1fd1 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -108,6 +108,8 @@ interface CommitInput; interface Vector#(SupSize, Put#(LdStQTag)) lsqSetAtCommit; // TLB has stopped processing now method Bool tlbNoPendingReq; + // Pause committing, probably for buffered wrongSpec + method Bool pauseCommit; // set flags method Action setFlushTlbs; method Action setUpdateVMInfo; @@ -526,6 +528,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // we commit trap in two cycles: first cycle deq ROB and flush; second // cycle handles trap, redirect and handles system consistency Reg#(Maybe#(CommitTrap)) commitTrap <- mkReg(Invalid); // saves new pc here + Bool pauseCommit = isValid(commitTrap) || inIfc.pauseCommit; FIFO#(RedirectInfo) redirectQ <- mkFIFO; @@ -660,7 +663,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `ifdef INCLUDE_GDB_CONTROL (rg_run_state == RUN_STATE_RUNNING) &&& `endif - !isValid(commitTrap) &&& + !pauseCommit &&& rob.deqPort[0].deq_data.trap matches tagged Valid .trap ); rob.deqPort[0].deq; @@ -825,7 +828,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `ifdef INCLUDE_GDB_CONTROL (rg_run_state == RUN_STATE_RUNNING) &&& `endif - !isValid(commitTrap) &&& + !pauseCommit &&& !isValid(rob.deqPort[0].deq_data.trap) &&& rob.deqPort[0].deq_data.ldKilled matches tagged Valid .killBy ); @@ -866,7 +869,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `ifdef INCLUDE_GDB_CONTROL (rg_run_state == RUN_STATE_RUNNING) && `endif - !isValid(commitTrap) && + !pauseCommit && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && rob.deqPort[0].deq_data.rob_inst_state == Executed && @@ -1042,7 +1045,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // Lr/Sc/Amo/MMIO cannot proceed to executed until we notify LSQ that it // has reached the commit stage rule notifyLSQCommit( - !isValid(commitTrap) && + !pauseCommit && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && rob.deqPort[0].deq_data.rob_inst_state != Executed && @@ -1063,7 +1066,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `ifdef INCLUDE_GDB_CONTROL (rg_run_state == RUN_STATE_RUNNING) && `endif - !isValid(commitTrap) && + !pauseCommit && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && rob.deqPort[0].deq_data.rob_inst_state == Executed && diff --git a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv index dbdf7c1..8234e3b 100644 --- a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv +++ b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv @@ -26,7 +26,7 @@ import HasSpecBits::*; import GetPut::*; import Vector::*; import ReorderBuffer::*; -import FIFO::*; +import SpecFifo::*; typedef struct { Bool kill_all; @@ -36,13 +36,14 @@ typedef struct { interface GlobalSpecUpdate#(numeric type correctSpecPortNum, numeric type conflictWrongSpecPortNum); interface Vector#(correctSpecPortNum, Put#(SpecTag)) correctSpec; - method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag); + method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); // Some rules (e.g. doFinishFpuMulDiv) in Core.bsv may not conflict with wrong spec // and is ordered before rules that calls incorrectSpec // this creates cycles in scheduling // To break the cycle, such rules can call the following interface // to manually create a conflict with rules that do incorrectSpec interface Vector#(conflictWrongSpecPortNum, Put#(void)) conflictWrongSpec; + method Bool pendingIncorrectSpec; endinterface module mkGlobalSpecUpdate#( @@ -54,12 +55,12 @@ module mkGlobalSpecUpdate#( // record correct spec tags Vector#(correctSpecPortNum, RWire#(SpecTag)) correctSpecTag <- replicateM(mkRWire); // make wrong spec conflict with correct spec - Vector#(correctSpecPortNum, RWire#(void)) spec_conflict <- replicateM(mkRWire); + Vector#(correctSpecPortNum, PulseWire) spec_conflict <- replicateM(mkPulseWire); // let the caller of conflictWrongSpec to be conflict with wrong spec - Vector#(conflictWrongSpecPortNum, RWire#(void)) wrongSpec_conflict <- replicateM(mkRWire); + Vector#(conflictWrongSpecPortNum, PulseWire) wrongSpec_conflict <- replicateM(mkPulseWire); // must be a single-element fifo to ensure all pushing rules cannot fire while we are waiting // to kill. - FIFO#(IncorrectSpec) incorrectSpec_ff <- mkFIFO1; + SpecFifo#(2,IncorrectSpec,1,1) incorrectSpec_ff <- mkSpecFifoCF(True); (* fire_when_enabled, no_implicit_conditions *) rule canon_correct_spec; @@ -69,31 +70,32 @@ module mkGlobalSpecUpdate#( mask[tag] = 0; end end + incorrectSpec_ff.specUpdate.correctSpeculation(mask); ifc.correctSpeculation(mask); rob.correctSpeculation(mask); endrule rule do_incorrect_spec; - IncorrectSpec x <- toGet(incorrectSpec_ff).get; + IncorrectSpec x = incorrectSpec_ff.first.data; + incorrectSpec_ff.deq; + incorrectSpec_ff.specUpdate.incorrectSpeculation(x.kill_all, x.spec_tag); ifc.incorrectSpeculation(x.kill_all, x.spec_tag); rob.incorrectSpeculation(x.kill_all, x.spec_tag, x.inst_tag); // conflict with correct spec for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin - spec_conflict[i].wset(?); + spec_conflict[i].send; end // conflict with the caller of conflictWrongSpec for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin - wrongSpec_conflict[i].wset(?); + wrongSpec_conflict[i].send; end endrule Vector#(correctSpecPortNum, Put#(SpecTag)) correctVec = ?; for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin correctVec[i] = (interface Put; - method Action put(SpecTag t); + method Action put(SpecTag t) if (!spec_conflict[i]); correctSpecTag[i].wset(t); - // conflict with wrong spec - spec_conflict[i].wset(?); endmethod endinterface); end @@ -101,16 +103,21 @@ module mkGlobalSpecUpdate#( Vector#(conflictWrongSpecPortNum, Put#(void)) conflictWrongVec = ?; for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin conflictWrongVec[i] = (interface Put; - method Action put(void x); - wrongSpec_conflict[i].wset(?); + method Action put(void x) if (!wrongSpec_conflict[i]); + noAction; endmethod endinterface); end interface correctSpec = correctVec; - method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag) - = incorrectSpec_ff.enq(IncorrectSpec{kill_all: kill_all, spec_tag: spec_tag, inst_tag: inst_tag}); + method Action incorrectSpec(Bool kill_all, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits) + = incorrectSpec_ff.enq(ToSpecFifo{ + data: IncorrectSpec{kill_all: kill_all, spec_tag: spec_tag, inst_tag: inst_tag}, + spec_bits: spec_bits + }); interface conflictWrongSpec = conflictWrongVec; + + method Bool pendingIncorrectSpec = incorrectSpec_ff.notEmpty; endmodule diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index 1ca4aa7..194f570 100644 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -674,7 +674,7 @@ module mkSupReorderBuffer#( Add#(1, a__, aluExeNum), Add#(1, b__, fpuMulDivExeNum) ); - Bool verbose = False; + Bool verbose = True; // doCommit rule: deq < wrongSpec (overwrite deq in doCommit) < doRenaming rule: enq Integer valid_deq_port = 0; @@ -756,6 +756,7 @@ module mkSupReorderBuffer#( // move deqP & reset valid deqP[i] <= getNextPtr(deqP[i]); valid[i][deqP[i]][valid_deq_port] <= False; + $display("deq[%d][%d]", i, deqP[i]); end end // update firstDeqWay: find the first deq port that is not enabled @@ -935,6 +936,9 @@ module mkSupReorderBuffer#( end endfunction for(Integer i = 0; i < valueof(SingleScalarSize); i = i+1) begin + if (in_kill_range(fromInteger(i)) != (row[w][i].dependsOn_wrongSpec(specTag) && valid[w][i][valid_wrongSpec_port])) + $display("enqP: %d, enqPNext: %d, w: %d, i: %d, wrongSpec: %d, valid: %d, cur_cycle: %d", + enqP[w], enqPNext[w], w, i, row[w][i].dependsOn_wrongSpec(specTag), valid[w][i][valid_wrongSpec_port], cur_cycle); doAssert( in_kill_range(fromInteger(i)) == (row[w][i].dependsOn_wrongSpec(specTag) && valid[w][i][valid_wrongSpec_port]), diff --git a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv index 818a340..8eb8c0e 100644 --- a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv @@ -43,6 +43,7 @@ interface SpecFifo#( method Action enq(ToSpecFifo#(t) x); method Action deq; method ToSpecFifo#(t) first; + method Bool notEmpty; interface SpeculationUpdate specUpdate; endinterface @@ -166,6 +167,8 @@ module mkSpecFifo#( }; endmethod + method Bool notEmpty = valid[deqP][sched.validDeqPort]; + interface SpeculationUpdate specUpdate; method Action correctSpeculation(SpecBits mask); // clear spec bits for all entries @@ -310,6 +313,8 @@ module mkSpecFifoCF#( }; endmethod + method Bool notEmpty = valid[1][deqP]; + interface SpeculationUpdate specUpdate; method correctSpeculation = correctSpecF.enq; method incorrectSpeculation(kill_all, specTag) = diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index 24fa28c..6513a8c 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -949,17 +949,7 @@ module mkSplitLSQ(SplitLSQ); // make wrongSpec conflict with all others (but not correctSpec method and // findIssue) - RWire#(void) wrongSpec_hit_conflict <- mkRWire; - RWire#(void) wrongSpec_enqIss_conflict <- mkRWire; - RWire#(void) wrongSpec_enq_conflict <- mkRWire; - RWire#(void) wrongSpec_cacheEvict_conflict <- mkRWire; - RWire#(void) wrongSpec_update_conflict <- mkRWire; - RWire#(void) wrongSpec_issue_conflict <- mkRWire; - RWire#(void) wrongSpec_respLd_conflict <- mkRWire; - RWire#(void) wrongSpec_deqLd_conflict <- mkRWire; - RWire#(void) wrongSpec_deqSt_conflict <- mkRWire; - RWire#(void) wrongSpec_verify_conflict <- mkRWire; - RWire#(void) wrongSpec_wakeBySB_conflict <- mkRWire; + PulseWire wrongSpec_conflict <- mkPulseWire; // make wrongSpec more urgent than firstSt (resolve bsc error) Wire#(Bool) wrongSpec_urgent_firstSt <- mkDWire(True); Map#(Bit#(10),Bit#(6),Int#(3),2) ldKillMap <- mkMapLossy(minBound); @@ -1145,7 +1135,7 @@ module mkSplitLSQ(SplitLSQ); end endrule - rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info); + rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info &&& !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqIss] ", fshow(info)); end @@ -1187,8 +1177,6 @@ module mkSplitLSQ(SplitLSQ); spec_bits: ld_specBits_enqIss[info.tag] }); ld_inIssueQ_enqIss[info.tag] <= True; - // make conflict with incorrect spec - wrongSpec_enqIss_conflict.wset(?); endrule // Verify SQ entry one by one @@ -1211,7 +1199,8 @@ module mkSplitLSQ(SplitLSQ); // NOTE that when SQ is full and all verified, verifyP will point to a // valid and verified entry rule verifySt(st_valid_verify[st_verifyP_verify] && - !st_verified_verify[st_verifyP_verify]); + !st_verified_verify[st_verifyP_verify] && + !wrongSpec_conflict); StQTag verP = st_verifyP_verify; // check if the entry can be verified. We should not fire this rule if @@ -1261,9 +1250,6 @@ module mkSplitLSQ(SplitLSQ); joinActions(map(setVerified, idxVec)); if(verbose) $display("[LSQ - verifySt] st_verifyP %d", verP); - - // make conflict with incorrect spec - wrongSpec_verify_conflict.wset(?); endrule `ifdef BSIM @@ -1437,10 +1423,7 @@ module mkSplitLSQ(SplitLSQ); endcase); endmethod - method ActionValue#(LSQHitInfo) getHit(LdStQTag t); - // Conflict with wrong spec. This makes cache pipelineResp rule - // conflict with wrong spec, and can help avoid scheduling cycle. - wrongSpec_hit_conflict.wset(?); + method ActionValue#(LSQHitInfo) getHit(LdStQTag t) if (!wrongSpec_conflict); return (case(t) matches tagged Ld .tag: (LSQHitInfo { waitWPResp: ld_waitWPResp_hit[tag], @@ -1465,7 +1448,7 @@ module mkSplitLSQ(SplitLSQ); MemInst mem_inst, Maybe#(PhyDst) dst, SpecBits spec_bits, - Bit#(16) pc_hash) if(ld_can_enq_wire); + Bit#(16) pc_hash) if(ld_can_enq_wire && !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqLd] enqP %d; ", ld_enqP, "; ", fshow(inst_tag), @@ -1518,14 +1501,12 @@ module mkSplitLSQ(SplitLSQ); ld_olderSt_enq[ld_enqP] <= Invalid; ld_olderStVerified_enq[ld_enqP] <= False; end - // make conflict with incorrect spec - wrongSpec_enq_conflict.wset(?); endmethod method Action enqSt(InstTag inst_tag, MemInst mem_inst, Maybe#(PhyDst) dst, - SpecBits spec_bits) if(st_can_enq_wire); + SpecBits spec_bits) if(st_can_enq_wire && !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqSt] enqP %d; ", st_enqP, "; ", fshow(inst_tag), @@ -1554,8 +1535,6 @@ module mkSplitLSQ(SplitLSQ); st_verified_enq[st_enqP] <= False; st_specBits_enq[st_enqP] <= spec_bits; st_atCommit_enq[st_enqP] <= False; - // make conflict with incorrect spec - wrongSpec_enq_conflict.wset(?); endmethod method Action updateData(StQTag t, MemTaggedData d); @@ -1570,7 +1549,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, Bool allowCap, Addr pa, Bool mmio, ByteOrTagEn shift_be - ); + ) if (!wrongSpec_conflict); // index vec for vector functions Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); @@ -1736,9 +1715,6 @@ module mkSplitLSQ(SplitLSQ); end end - // make conflict with incorrect spec - wrongSpec_update_conflict.wset(?); - // return waiting for wp resp bit: for deciding whether the updating Ld // can be issued return LSQUpdateAddrResult { @@ -1753,7 +1729,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQIssueLdResult) issueLd(LdQTag tag, Addr pa, ByteOrTagEn shift_be, - SBSearchRes sbRes); + SBSearchRes sbRes) if (!wrongSpec_conflict); if(verbose) begin $display("[LSQ - issueLd] ", fshow(tag), "; ", fshow(pa), "; ", fshow(shift_be), "; ", fshow(sbRes)); @@ -2022,9 +1998,6 @@ module mkSplitLSQ(SplitLSQ); end `endif - // make conflict with incorrect spec - wrongSpec_issue_conflict.wset(?); - return issRes; endmethod @@ -2041,7 +2014,7 @@ module mkSplitLSQ(SplitLSQ); return issueLdQ.first.data; endmethod - method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData); + method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData) if (!wrongSpec_conflict); let res = LSQRespLdResult { wrongPath: False, dst: Invalid, @@ -2090,8 +2063,6 @@ module mkSplitLSQ(SplitLSQ); $display("[LSQ - respLd] ", fshow(t), "; ", fshow(alignedData), "; ", fshow(res)); end - // make conflict with incorrect spec - wrongSpec_respLd_conflict.wset(?); // return return res; endmethod @@ -2116,7 +2087,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqLd if(deqLdGuard); + method Action deqLd if(deqLdGuard && !wrongSpec_conflict); LdQTag deqP = ld_deqP_deqLd; if(verbose) $display("[LSQ - deqLd] deqP %d", deqP); @@ -2163,9 +2134,6 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); - - // make conflict with incorrect spec - wrongSpec_deqLd_conflict.wset(?); endmethod method StQDeqEntry firstSt if(deqStGuard && wrongSpec_urgent_firstSt); @@ -2186,7 +2154,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqSt if(deqStGuard); + method Action deqSt if(deqStGuard && !wrongSpec_conflict); StQTag deqP = st_deqP; if(verbose) $display("[LSQ - deqSt] deqP %d", deqP); @@ -2234,13 +2202,10 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(resetSt, idxVec)); - - // make conflict with incorrect spec - wrongSpec_deqSt_conflict.wset(?); endmethod `ifdef TSO_MM - method Action cacheEvict(LineAddr lineAddr); + method Action cacheEvict(LineAddr lineAddr) if (!wrongSpec_conflict); if(verbose) $display("[LSQ - cacheEvict] ", fshow(lineAddr)); // kill a load if it satisfies the following conditions: // (1) valid @@ -2270,14 +2235,11 @@ module mkSplitLSQ(SplitLSQ); doAssert(!ld_isMMIO_evict[killTag], "cannot kill MMIO"); doAssert(ld_memFunc[killTag] == Ld, "can only kill Ld"); end - - // make conflict with incorrect spec - wrongSpec_cacheEvict_conflict.wset(?); endmethod `else - method Action wakeupLdStalledBySB(SBIndex sbIdx); + method Action wakeupLdStalledBySB(SBIndex sbIdx) if (!wrongSpec_conflict); if(verbose) begin $display("[LSQ - wakeupBySB] ", fshow(sbIdx)); end @@ -2292,8 +2254,6 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); - // make conflict with incorrect spec - wrongSpec_wakeBySB_conflict.wset(?); endmethod `endif @@ -2438,17 +2398,7 @@ module mkSplitLSQ(SplitLSQ); end // make conflict with others - wrongSpec_hit_conflict.wset(?); - wrongSpec_enqIss_conflict.wset(?); - wrongSpec_enq_conflict.wset(?); - wrongSpec_update_conflict.wset(?); - wrongSpec_issue_conflict.wset(?); - wrongSpec_respLd_conflict.wset(?); - wrongSpec_deqLd_conflict.wset(?); - wrongSpec_deqSt_conflict.wset(?); - wrongSpec_verify_conflict.wset(?); - wrongSpec_cacheEvict_conflict.wset(?); - wrongSpec_wakeBySB_conflict.wset(?); + wrongSpec_conflict.send(); // more urgent than firstSt wrongSpec_urgent_firstSt <= True; endmethod From a56deab46c81236e779db97d2b02553a393f25ed Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Thu, 9 Dec 2021 12:27:57 +0000 Subject: [PATCH 4/7] Simpelest strategy for making wrongSpec not conflict with loads of rules. This triggers some assertions in the ROB what should be dealt with properly if this is going to work. --- .../RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv index 8234e3b..28ae322 100644 --- a/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv +++ b/src_Core/RISCY_OOO/procs/lib/GlobalSpecUpdate.bsv @@ -54,10 +54,8 @@ module mkGlobalSpecUpdate#( ); // record correct spec tags Vector#(correctSpecPortNum, RWire#(SpecTag)) correctSpecTag <- replicateM(mkRWire); - // make wrong spec conflict with correct spec - Vector#(correctSpecPortNum, PulseWire) spec_conflict <- replicateM(mkPulseWire); - // let the caller of conflictWrongSpec to be conflict with wrong spec - Vector#(conflictWrongSpecPortNum, PulseWire) wrongSpec_conflict <- replicateM(mkPulseWire); + // make wrong spec conflict with correct spec and conflictWrongSpec + PulseWire spec_conflict <- mkPulseWire; // must be a single-element fifo to ensure all pushing rules cannot fire while we are waiting // to kill. SpecFifo#(2,IncorrectSpec,1,1) incorrectSpec_ff <- mkSpecFifoCF(True); @@ -81,20 +79,14 @@ module mkGlobalSpecUpdate#( incorrectSpec_ff.specUpdate.incorrectSpeculation(x.kill_all, x.spec_tag); ifc.incorrectSpeculation(x.kill_all, x.spec_tag); rob.incorrectSpeculation(x.kill_all, x.spec_tag, x.inst_tag); - // conflict with correct spec - for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin - spec_conflict[i].send; - end - // conflict with the caller of conflictWrongSpec - for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin - wrongSpec_conflict[i].send; - end + // conflict with correct spec and conflictWrongSpec + spec_conflict.send; endrule Vector#(correctSpecPortNum, Put#(SpecTag)) correctVec = ?; for(Integer i = 0; i < valueof(correctSpecPortNum); i = i+1) begin correctVec[i] = (interface Put; - method Action put(SpecTag t) if (!spec_conflict[i]); + method Action put(SpecTag t) if (!spec_conflict); correctSpecTag[i].wset(t); endmethod endinterface); @@ -103,7 +95,7 @@ module mkGlobalSpecUpdate#( Vector#(conflictWrongSpecPortNum, Put#(void)) conflictWrongVec = ?; for(Integer i = 0; i < valueof(conflictWrongSpecPortNum); i = i+1) begin conflictWrongVec[i] = (interface Put; - method Action put(void x) if (!wrongSpec_conflict[i]); + method Action put(void x) if (!spec_conflict); noAction; endmethod endinterface); From ad5d5aca0d381724b097d1a3a64c355470424e6c Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Wed, 12 Jan 2022 13:13:39 +0000 Subject: [PATCH 5/7] Also pause branch execution when there is a pending wrong speculation. --- src_Core/CPU/Core.bsv | 1 + .../procs/RV64G_OOO/AluExePipeline.bsv | 6 ++++-- src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv | 18 +++++++----------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 5c29e37..0783e1e 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -426,6 +426,7 @@ module mkCore#(CoreId coreId)(Core); ); globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag, spec_bits); endmethod + method Bool pauseExecute = globalSpecUpdate.pendingIncorrectSpec; method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put; method doStats = doStatsReg._read; `ifdef PERFORMANCE_MONITORING diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index acb59be..efb03a5 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -195,6 +195,8 @@ interface AluExeInput; method Action writeRegFile(PhyRIndx dst, CapPipe data); // redirect method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); + // pending invalidation could pause execute/redirections. + method Bool pauseExecute; // spec update method Action correctSpec(SpecTag t); @@ -354,7 +356,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); }); endrule - rule doExeAlu; + rule doExeAlu(!inIfc.pauseExecute); regToExeQ.deq; let regToExe = regToExeQ.first; let x = regToExe.data; @@ -417,7 +419,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); }); endrule - rule doFinishAlu; + rule doFinishAlu(!inIfc.pauseExecute); exeToFinQ.deq; let exeToFin = exeToFinQ.first; let x = exeToFin.data; diff --git a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv index 8eb8c0e..b043b71 100644 --- a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv @@ -25,7 +25,7 @@ import ProcTypes::*; import HasSpecBits::*; import Vector::*; import Ehr::*; -import FIFOF::*; +import DReg::*; import Assert::*; import Types::*; import ConfigReg::*; @@ -223,8 +223,8 @@ module mkSpecFifoCF#( Vector#(size, Reg#(t)) row <- replicateM(mkConfigRegU); Ehr#(3, Vector#(size, SpecBits)) specBits <- mkEhr(?); - FIFOF#(SpecBits) correctSpecF <- mkUGFIFOF; - FIFOF#(IncorrectSpeculation) incorrectSpecF <- mkUGFIFOF; + Reg#(Maybe#(SpecBits)) correctSpec <- mkDReg(Invalid); + Reg#(Maybe#(IncorrectSpeculation)) incorrectSpec <- mkDReg(Invalid); Reg#(idxT) enqP <- mkConfigReg(0); Ehr#(2, idxT) deqP_ehr <- mkEhr(0); @@ -245,17 +245,13 @@ module mkSpecFifoCF#( Vector#(size, SpecBits) newSpecBits = specBits[0]; Vector#(size, Bool) newValid = valid[0]; // Fold in CorrectSpec update: - if (correctSpecF.notEmpty) begin - SpecBits mask = correctSpecF.first(); - correctSpecF.deq(); + if (correctSpec matches tagged Valid .mask) begin // clear spec bits for all entries for (Integer i=0; i Date: Tue, 1 Feb 2022 09:10:48 +0000 Subject: [PATCH 6/7] Enable tracing of physical addresses for RVFI (if PADDR_RVFI is defined). This is done by adding a vector of padder lookup interfaces to the load store queue. This should help with targeted memory translation debugging, and also with compatability with the current Sail RVFI implemenation which is probably incorrect with respect to the RVFI spec which calls for virtual addresses in the maddr field. --- src_Core/CPU/Core.bsv | 1 + .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 14 ++- src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv | 95 ++++++++++++++++--- 3 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 0783e1e..7ce2467 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -650,6 +650,7 @@ module mkCore#(CoreId coreId)(Core); method stbEmpty = stb.isEmpty; method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; + method lookupPAddr = lsq.lookupPAddr; method pauseCommit = coreFix.pendingIncorrectSpec; method tlbNoPendingReq = iTlb.noPendingReq && dTlb.noPendingReq; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index cdc1fd1..8e14907 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -60,6 +60,7 @@ import RenameDebugIF::*; import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; +import RegFile::*; // Just for the interface `ifdef PERFORMANCE_MONITORING import StatCounters::*; `endif @@ -106,6 +107,8 @@ interface CommitInput; method Bool stqEmpty; // notify LSQ that inst has reached commit interface Vector#(SupSize, Put#(LdStQTag)) lsqSetAtCommit; + // method for getting translated addresses for tracing. + interface Vector#(SupSize, RegFile#(LdStQTag, Addr)) lookupPAddr; // TLB has stopped processing now method Bool tlbNoPendingReq; // Pause committing, probably for buffered wrongSpec @@ -213,7 +216,7 @@ typedef struct { Data mtvec; } TraceStateBundle deriving(Bits, FShow); -function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, Dii_Id traceCnt, TraceStateBundle tsb, Data next_pc); +function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, Dii_Id traceCnt, TraceStateBundle tsb, Data next_pc, Addr paddr); Addr addr = 0; Data data = 0; Data wdata = 0; @@ -230,6 +233,9 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, case (rot.ppc_vaddr_csrData) matches tagged VAddr .vaddr: begin addr = vaddr; +`ifdef PADDR_RVFI + addr = paddr; +`endif case (rot.lsqTag) matches tagged Ld .l: rmask = rot.traceBundle.memByteEn; tagged St .s: begin @@ -800,7 +806,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); }); `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); - rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc)); + rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc), inIfc.lookupPAddr[0].sub(trap.x.lsqTag)); rvfiQ.enq(rvfis); traceCnt <= traceCnt + 1; `endif @@ -969,7 +975,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Rvfi_Traces rvfis = replicate(tagged Invalid); x.ppc_vaddr_csrData = tagged PPC next_pc; CapPipe cp = cast(next_pc); - rvfis[0] = genRVFI(x, traceCnt, getTSB(), getOffset(cp)); + rvfis[0] = genRVFI(x, traceCnt, getTSB(), getOffset(cp), inIfc.lookupPAddr[0].sub(x.lsqTag)); rvfiQ.enq(rvfis); traceCnt <= traceCnt + 1; `endif @@ -1147,7 +1153,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); if (verbose) $display("%t : [doCommitNormalInst - %d] ", $time(), i, fshow(inst_tag), " ; ", fshow(x)); `ifdef RVFI CapPipe pipePc = cast(x.pc); - rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getOffset(pipePc) + (is_16b_inst(x.orig_inst) ? 2:4)); + rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getOffset(pipePc) + (is_16b_inst(x.orig_inst) ? 2:4), inIfc.lookupPAddr[i].sub(x.lsqTag)); whichTrace = whichTrace + 1; `endif diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index 6513a8c..e7d8cba 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -51,6 +51,7 @@ import StoreBuffer::*; import Exec::*; import FP_Utils::*; import CacheUtils::*; // For CLoadTags alignment +import RegFile::*; // Just for the interface // I don't want to export auxiliary functions, so manually export all types export LdQMemFunc(..); @@ -439,6 +440,8 @@ interface SplitLSQ; // Sc/Amo/Fence, and flush L1 cache. method StQDeqEntry firstSt; method Action deqSt; + // method for reporting the physical address of an entry used for tracing. + interface Vector#(SupSize, RegFile#(LdStQTag, Addr)) lookupPAddr; `ifdef TSO_MM // Kill loads when a cache line is evicted (TSO only) method Action cacheEvict(LineAddr a); @@ -949,7 +952,17 @@ module mkSplitLSQ(SplitLSQ); // make wrongSpec conflict with all others (but not correctSpec method and // findIssue) - PulseWire wrongSpec_conflict <- mkPulseWire; + RWire#(void) wrongSpec_hit_conflict <- mkRWire; + RWire#(void) wrongSpec_enqIss_conflict <- mkRWire; + RWire#(void) wrongSpec_enq_conflict <- mkRWire; + RWire#(void) wrongSpec_cacheEvict_conflict <- mkRWire; + RWire#(void) wrongSpec_update_conflict <- mkRWire; + RWire#(void) wrongSpec_issue_conflict <- mkRWire; + RWire#(void) wrongSpec_respLd_conflict <- mkRWire; + RWire#(void) wrongSpec_deqLd_conflict <- mkRWire; + RWire#(void) wrongSpec_deqSt_conflict <- mkRWire; + RWire#(void) wrongSpec_verify_conflict <- mkRWire; + RWire#(void) wrongSpec_wakeBySB_conflict <- mkRWire; // make wrongSpec more urgent than firstSt (resolve bsc error) Wire#(Bool) wrongSpec_urgent_firstSt <- mkDWire(True); Map#(Bit#(10),Bit#(6),Int#(3),2) ldKillMap <- mkMapLossy(minBound); @@ -1135,7 +1148,7 @@ module mkSplitLSQ(SplitLSQ); end endrule - rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info &&& !wrongSpec_conflict); + rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info); if(verbose) begin $display("[LSQ - enqIss] ", fshow(info)); end @@ -1177,6 +1190,8 @@ module mkSplitLSQ(SplitLSQ); spec_bits: ld_specBits_enqIss[info.tag] }); ld_inIssueQ_enqIss[info.tag] <= True; + // make conflict with incorrect spec + wrongSpec_enqIss_conflict.wset(?); endrule // Verify SQ entry one by one @@ -1199,8 +1214,7 @@ module mkSplitLSQ(SplitLSQ); // NOTE that when SQ is full and all verified, verifyP will point to a // valid and verified entry rule verifySt(st_valid_verify[st_verifyP_verify] && - !st_verified_verify[st_verifyP_verify] && - !wrongSpec_conflict); + !st_verified_verify[st_verifyP_verify]); StQTag verP = st_verifyP_verify; // check if the entry can be verified. We should not fire this rule if @@ -1250,6 +1264,9 @@ module mkSplitLSQ(SplitLSQ); joinActions(map(setVerified, idxVec)); if(verbose) $display("[LSQ - verifySt] st_verifyP %d", verP); + + // make conflict with incorrect spec + wrongSpec_verify_conflict.wset(?); endrule `ifdef BSIM @@ -1415,6 +1432,16 @@ module mkSplitLSQ(SplitLSQ); endinterface); end + RegFile#(LdStQTag, Addr) lookupAPAddr = (interface RegFile; + method Addr sub(LdStQTag t); + case (t) matches + tagged Ld .l: return ld_paddr_deqLd[l]; + tagged St .s: return st_paddr_deqSt[s]; + endcase + endmethod + method upd = ?; + endinterface); + method ByteOrTagEn getOrigBE(LdStQTag t); return (case(t) matches tagged Ld .tag: (ld_byteOrTagEn[tag]); @@ -1423,7 +1450,10 @@ module mkSplitLSQ(SplitLSQ); endcase); endmethod - method ActionValue#(LSQHitInfo) getHit(LdStQTag t) if (!wrongSpec_conflict); + method ActionValue#(LSQHitInfo) getHit(LdStQTag t); + // Conflict with wrong spec. This makes cache pipelineResp rule + // conflict with wrong spec, and can help avoid scheduling cycle. + wrongSpec_hit_conflict.wset(?); return (case(t) matches tagged Ld .tag: (LSQHitInfo { waitWPResp: ld_waitWPResp_hit[tag], @@ -1448,7 +1478,7 @@ module mkSplitLSQ(SplitLSQ); MemInst mem_inst, Maybe#(PhyDst) dst, SpecBits spec_bits, - Bit#(16) pc_hash) if(ld_can_enq_wire && !wrongSpec_conflict); + Bit#(16) pc_hash) if(ld_can_enq_wire); if(verbose) begin $display("[LSQ - enqLd] enqP %d; ", ld_enqP, "; ", fshow(inst_tag), @@ -1501,12 +1531,14 @@ module mkSplitLSQ(SplitLSQ); ld_olderSt_enq[ld_enqP] <= Invalid; ld_olderStVerified_enq[ld_enqP] <= False; end + // make conflict with incorrect spec + wrongSpec_enq_conflict.wset(?); endmethod method Action enqSt(InstTag inst_tag, MemInst mem_inst, Maybe#(PhyDst) dst, - SpecBits spec_bits) if(st_can_enq_wire && !wrongSpec_conflict); + SpecBits spec_bits) if(st_can_enq_wire); if(verbose) begin $display("[LSQ - enqSt] enqP %d; ", st_enqP, "; ", fshow(inst_tag), @@ -1535,6 +1567,8 @@ module mkSplitLSQ(SplitLSQ); st_verified_enq[st_enqP] <= False; st_specBits_enq[st_enqP] <= spec_bits; st_atCommit_enq[st_enqP] <= False; + // make conflict with incorrect spec + wrongSpec_enq_conflict.wset(?); endmethod method Action updateData(StQTag t, MemTaggedData d); @@ -1549,7 +1583,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, Bool allowCap, Addr pa, Bool mmio, ByteOrTagEn shift_be - ) if (!wrongSpec_conflict); + ); // index vec for vector functions Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); @@ -1715,6 +1749,9 @@ module mkSplitLSQ(SplitLSQ); end end + // make conflict with incorrect spec + wrongSpec_update_conflict.wset(?); + // return waiting for wp resp bit: for deciding whether the updating Ld // can be issued return LSQUpdateAddrResult { @@ -1729,7 +1766,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQIssueLdResult) issueLd(LdQTag tag, Addr pa, ByteOrTagEn shift_be, - SBSearchRes sbRes) if (!wrongSpec_conflict); + SBSearchRes sbRes); if(verbose) begin $display("[LSQ - issueLd] ", fshow(tag), "; ", fshow(pa), "; ", fshow(shift_be), "; ", fshow(sbRes)); @@ -1998,6 +2035,9 @@ module mkSplitLSQ(SplitLSQ); end `endif + // make conflict with incorrect spec + wrongSpec_issue_conflict.wset(?); + return issRes; endmethod @@ -2014,7 +2054,7 @@ module mkSplitLSQ(SplitLSQ); return issueLdQ.first.data; endmethod - method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData) if (!wrongSpec_conflict); + method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData); let res = LSQRespLdResult { wrongPath: False, dst: Invalid, @@ -2063,6 +2103,8 @@ module mkSplitLSQ(SplitLSQ); $display("[LSQ - respLd] ", fshow(t), "; ", fshow(alignedData), "; ", fshow(res)); end + // make conflict with incorrect spec + wrongSpec_respLd_conflict.wset(?); // return return res; endmethod @@ -2087,7 +2129,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqLd if(deqLdGuard && !wrongSpec_conflict); + method Action deqLd if(deqLdGuard); LdQTag deqP = ld_deqP_deqLd; if(verbose) $display("[LSQ - deqLd] deqP %d", deqP); @@ -2134,6 +2176,9 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); + + // make conflict with incorrect spec + wrongSpec_deqLd_conflict.wset(?); endmethod method StQDeqEntry firstSt if(deqStGuard && wrongSpec_urgent_firstSt); @@ -2154,7 +2199,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqSt if(deqStGuard && !wrongSpec_conflict); + method Action deqSt if(deqStGuard); StQTag deqP = st_deqP; if(verbose) $display("[LSQ - deqSt] deqP %d", deqP); @@ -2202,10 +2247,15 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(resetSt, idxVec)); + + // make conflict with incorrect spec + wrongSpec_deqSt_conflict.wset(?); endmethod + interface lookupPAddr = replicate(lookupAPAddr); + `ifdef TSO_MM - method Action cacheEvict(LineAddr lineAddr) if (!wrongSpec_conflict); + method Action cacheEvict(LineAddr lineAddr); if(verbose) $display("[LSQ - cacheEvict] ", fshow(lineAddr)); // kill a load if it satisfies the following conditions: // (1) valid @@ -2235,11 +2285,14 @@ module mkSplitLSQ(SplitLSQ); doAssert(!ld_isMMIO_evict[killTag], "cannot kill MMIO"); doAssert(ld_memFunc[killTag] == Ld, "can only kill Ld"); end + + // make conflict with incorrect spec + wrongSpec_cacheEvict_conflict.wset(?); endmethod `else - method Action wakeupLdStalledBySB(SBIndex sbIdx) if (!wrongSpec_conflict); + method Action wakeupLdStalledBySB(SBIndex sbIdx); if(verbose) begin $display("[LSQ - wakeupBySB] ", fshow(sbIdx)); end @@ -2254,6 +2307,8 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); + // make conflict with incorrect spec + wrongSpec_wakeBySB_conflict.wset(?); endmethod `endif @@ -2398,7 +2453,17 @@ module mkSplitLSQ(SplitLSQ); end // make conflict with others - wrongSpec_conflict.send(); + wrongSpec_hit_conflict.wset(?); + wrongSpec_enqIss_conflict.wset(?); + wrongSpec_enq_conflict.wset(?); + wrongSpec_update_conflict.wset(?); + wrongSpec_issue_conflict.wset(?); + wrongSpec_respLd_conflict.wset(?); + wrongSpec_deqLd_conflict.wset(?); + wrongSpec_deqSt_conflict.wset(?); + wrongSpec_verify_conflict.wset(?); + wrongSpec_cacheEvict_conflict.wset(?); + wrongSpec_wakeBySB_conflict.wset(?); // more urgent than firstSt wrongSpec_urgent_firstSt <= True; endmethod From 05df76073b3e1e86e27c33fddeb8339b53caf3e0 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Tue, 1 Feb 2022 11:08:37 +0000 Subject: [PATCH 7/7] Revert some unintended changes from the last commit. --- src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv | 80 +++++------------------ 1 file changed, 15 insertions(+), 65 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index e7d8cba..25838b1 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -952,17 +952,7 @@ module mkSplitLSQ(SplitLSQ); // make wrongSpec conflict with all others (but not correctSpec method and // findIssue) - RWire#(void) wrongSpec_hit_conflict <- mkRWire; - RWire#(void) wrongSpec_enqIss_conflict <- mkRWire; - RWire#(void) wrongSpec_enq_conflict <- mkRWire; - RWire#(void) wrongSpec_cacheEvict_conflict <- mkRWire; - RWire#(void) wrongSpec_update_conflict <- mkRWire; - RWire#(void) wrongSpec_issue_conflict <- mkRWire; - RWire#(void) wrongSpec_respLd_conflict <- mkRWire; - RWire#(void) wrongSpec_deqLd_conflict <- mkRWire; - RWire#(void) wrongSpec_deqSt_conflict <- mkRWire; - RWire#(void) wrongSpec_verify_conflict <- mkRWire; - RWire#(void) wrongSpec_wakeBySB_conflict <- mkRWire; + PulseWire wrongSpec_conflict <- mkPulseWire; // make wrongSpec more urgent than firstSt (resolve bsc error) Wire#(Bool) wrongSpec_urgent_firstSt <- mkDWire(True); Map#(Bit#(10),Bit#(6),Int#(3),2) ldKillMap <- mkMapLossy(minBound); @@ -1148,7 +1138,7 @@ module mkSplitLSQ(SplitLSQ); end endrule - rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info); + rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info &&& !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqIss] ", fshow(info)); end @@ -1190,8 +1180,6 @@ module mkSplitLSQ(SplitLSQ); spec_bits: ld_specBits_enqIss[info.tag] }); ld_inIssueQ_enqIss[info.tag] <= True; - // make conflict with incorrect spec - wrongSpec_enqIss_conflict.wset(?); endrule // Verify SQ entry one by one @@ -1214,7 +1202,8 @@ module mkSplitLSQ(SplitLSQ); // NOTE that when SQ is full and all verified, verifyP will point to a // valid and verified entry rule verifySt(st_valid_verify[st_verifyP_verify] && - !st_verified_verify[st_verifyP_verify]); + !st_verified_verify[st_verifyP_verify] && + !wrongSpec_conflict); StQTag verP = st_verifyP_verify; // check if the entry can be verified. We should not fire this rule if @@ -1264,9 +1253,6 @@ module mkSplitLSQ(SplitLSQ); joinActions(map(setVerified, idxVec)); if(verbose) $display("[LSQ - verifySt] st_verifyP %d", verP); - - // make conflict with incorrect spec - wrongSpec_verify_conflict.wset(?); endrule `ifdef BSIM @@ -1450,10 +1436,7 @@ module mkSplitLSQ(SplitLSQ); endcase); endmethod - method ActionValue#(LSQHitInfo) getHit(LdStQTag t); - // Conflict with wrong spec. This makes cache pipelineResp rule - // conflict with wrong spec, and can help avoid scheduling cycle. - wrongSpec_hit_conflict.wset(?); + method ActionValue#(LSQHitInfo) getHit(LdStQTag t) if (!wrongSpec_conflict); return (case(t) matches tagged Ld .tag: (LSQHitInfo { waitWPResp: ld_waitWPResp_hit[tag], @@ -1478,7 +1461,7 @@ module mkSplitLSQ(SplitLSQ); MemInst mem_inst, Maybe#(PhyDst) dst, SpecBits spec_bits, - Bit#(16) pc_hash) if(ld_can_enq_wire); + Bit#(16) pc_hash) if(ld_can_enq_wire && !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqLd] enqP %d; ", ld_enqP, "; ", fshow(inst_tag), @@ -1531,14 +1514,12 @@ module mkSplitLSQ(SplitLSQ); ld_olderSt_enq[ld_enqP] <= Invalid; ld_olderStVerified_enq[ld_enqP] <= False; end - // make conflict with incorrect spec - wrongSpec_enq_conflict.wset(?); endmethod method Action enqSt(InstTag inst_tag, MemInst mem_inst, Maybe#(PhyDst) dst, - SpecBits spec_bits) if(st_can_enq_wire); + SpecBits spec_bits) if(st_can_enq_wire && !wrongSpec_conflict); if(verbose) begin $display("[LSQ - enqSt] enqP %d; ", st_enqP, "; ", fshow(inst_tag), @@ -1567,8 +1548,6 @@ module mkSplitLSQ(SplitLSQ); st_verified_enq[st_enqP] <= False; st_specBits_enq[st_enqP] <= spec_bits; st_atCommit_enq[st_enqP] <= False; - // make conflict with incorrect spec - wrongSpec_enq_conflict.wset(?); endmethod method Action updateData(StQTag t, MemTaggedData d); @@ -1583,7 +1562,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, Bool allowCap, Addr pa, Bool mmio, ByteOrTagEn shift_be - ); + ) if (!wrongSpec_conflict); // index vec for vector functions Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); @@ -1749,9 +1728,6 @@ module mkSplitLSQ(SplitLSQ); end end - // make conflict with incorrect spec - wrongSpec_update_conflict.wset(?); - // return waiting for wp resp bit: for deciding whether the updating Ld // can be issued return LSQUpdateAddrResult { @@ -1766,7 +1742,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQIssueLdResult) issueLd(LdQTag tag, Addr pa, ByteOrTagEn shift_be, - SBSearchRes sbRes); + SBSearchRes sbRes) if (!wrongSpec_conflict); if(verbose) begin $display("[LSQ - issueLd] ", fshow(tag), "; ", fshow(pa), "; ", fshow(shift_be), "; ", fshow(sbRes)); @@ -2035,9 +2011,6 @@ module mkSplitLSQ(SplitLSQ); end `endif - // make conflict with incorrect spec - wrongSpec_issue_conflict.wset(?); - return issRes; endmethod @@ -2054,7 +2027,7 @@ module mkSplitLSQ(SplitLSQ); return issueLdQ.first.data; endmethod - method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData); + method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData) if (!wrongSpec_conflict); let res = LSQRespLdResult { wrongPath: False, dst: Invalid, @@ -2103,8 +2076,6 @@ module mkSplitLSQ(SplitLSQ); $display("[LSQ - respLd] ", fshow(t), "; ", fshow(alignedData), "; ", fshow(res)); end - // make conflict with incorrect spec - wrongSpec_respLd_conflict.wset(?); // return return res; endmethod @@ -2129,7 +2100,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqLd if(deqLdGuard); + method Action deqLd if(deqLdGuard && !wrongSpec_conflict); LdQTag deqP = ld_deqP_deqLd; if(verbose) $display("[LSQ - deqLd] deqP %d", deqP); @@ -2176,9 +2147,6 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); - - // make conflict with incorrect spec - wrongSpec_deqLd_conflict.wset(?); endmethod method StQDeqEntry firstSt if(deqStGuard && wrongSpec_urgent_firstSt); @@ -2199,7 +2167,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqSt if(deqStGuard); + method Action deqSt if(deqStGuard && !wrongSpec_conflict); StQTag deqP = st_deqP; if(verbose) $display("[LSQ - deqSt] deqP %d", deqP); @@ -2247,15 +2215,12 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(resetSt, idxVec)); - - // make conflict with incorrect spec - wrongSpec_deqSt_conflict.wset(?); endmethod interface lookupPAddr = replicate(lookupAPAddr); `ifdef TSO_MM - method Action cacheEvict(LineAddr lineAddr); + method Action cacheEvict(LineAddr lineAddr) if (!wrongSpec_conflict); if(verbose) $display("[LSQ - cacheEvict] ", fshow(lineAddr)); // kill a load if it satisfies the following conditions: // (1) valid @@ -2285,14 +2250,11 @@ module mkSplitLSQ(SplitLSQ); doAssert(!ld_isMMIO_evict[killTag], "cannot kill MMIO"); doAssert(ld_memFunc[killTag] == Ld, "can only kill Ld"); end - - // make conflict with incorrect spec - wrongSpec_cacheEvict_conflict.wset(?); endmethod `else - method Action wakeupLdStalledBySB(SBIndex sbIdx); + method Action wakeupLdStalledBySB(SBIndex sbIdx) if (!wrongSpec_conflict); if(verbose) begin $display("[LSQ - wakeupBySB] ", fshow(sbIdx)); end @@ -2307,8 +2269,6 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); - // make conflict with incorrect spec - wrongSpec_wakeBySB_conflict.wset(?); endmethod `endif @@ -2453,17 +2413,7 @@ module mkSplitLSQ(SplitLSQ); end // make conflict with others - wrongSpec_hit_conflict.wset(?); - wrongSpec_enqIss_conflict.wset(?); - wrongSpec_enq_conflict.wset(?); - wrongSpec_update_conflict.wset(?); - wrongSpec_issue_conflict.wset(?); - wrongSpec_respLd_conflict.wset(?); - wrongSpec_deqLd_conflict.wset(?); - wrongSpec_deqSt_conflict.wset(?); - wrongSpec_verify_conflict.wset(?); - wrongSpec_cacheEvict_conflict.wset(?); - wrongSpec_wakeBySB_conflict.wset(?); + wrongSpec_conflict.send(); // more urgent than firstSt wrongSpec_urgent_firstSt <= True; endmethod