Don't decode redirected streams until they are non-speculative.

This commit is contained in:
Jonathan Woodruff
2021-12-17 16:29:14 +00:00
parent 4cc86b1e56
commit 54d1a204f0
6 changed files with 85 additions and 38 deletions

View File

@@ -89,7 +89,7 @@ BSC_COMPILATION_FLAGS += \
-D RISCV \
-D PERFORMANCE_MONITORING \
-D RAS_HIT_TRACING \
-D TSO_MM \
-D TSO_MM -D NO_SPEC_TRAINING -D NO_SPEC_REDIRECT \
-keep-fires -aggressive-conditions -no-warn-action-shadowing -check-assert \
-suppress-warnings G0020 -steps-max-intervals 10000000 \
-steps-warn-interval 1000000 \

View File

@@ -353,7 +353,8 @@ module mkCore#(CoreId coreId)(Core);
end
GlobalSpecUpdate#(CorrectSpecPortNum, ConflictWrongSpecPortNum) globalSpecUpdate <- mkGlobalSpecUpdate(
joinSpeculationUpdate(
append(append(append(vec(regRenamingTable.specUpdate,
append(append(append(vec(fetchStage.specUpdate,
regRenamingTable.specUpdate,
specTagManager.specUpdate,
fix.memExeIfc.specUpdate), aluSpecUpdate), fpuMulDivSpecUpdate), btqSpecUpdate)
),
@@ -417,15 +418,16 @@ 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));
end
epochManager.incrementEpoch;
fetchStage.redirect(new_pc
fetchStage.redirect(new_pc,
spec_bits
`ifdef RVFI_DII
, inst_tag.dii_next_pid
, inst_tag.dii_next_pid
`endif
);
globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag);
@@ -1447,7 +1449,7 @@ module mkCore#(CoreId coreId)(Core);
l2Tlb.updateVMInfo(vmI, vmD);
let startpc = csrf.dpc_read;
fetchStage.redirect (cast(startpc));
fetchStage.redirect (cast(startpc), 0);
renameStage.debug_resume;
commitStage.debug_resume;

View File

@@ -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);
@@ -484,7 +484,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(ToSpecFifo {

View File

@@ -118,7 +118,9 @@ interface CommitInput;
method Action setReconcileD; // recocile D$
// redirect
method Action killAll;
method Action redirectPc(CapMem trap_pc
method Action redirectPc(
CapMem trap_pc,
SpecBits specBits
`ifdef RVFI_DII
, Dii_Parcel_Id dii_pid
`endif
@@ -157,6 +159,13 @@ typedef struct {
SpecBits specBits;
} RenameErrInfo deriving(Bits, Eq, FShow);
typedef struct {
CapMem trap_pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
} RedirectInfo deriving(Bits, Eq, FShow);
interface CommitStage;
// performance
method Data getPerf(ComStagePerfType t);
@@ -519,6 +528,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// cycle handles trap, redirect and handles system consistency
Reg#(Maybe#(CommitTrap)) commitTrap <- mkReg(Invalid); // saves new pc here
FIFO#(RedirectInfo) redirectQ <- mkFIFO;
// maintain system consistency when system state (CSR) changes or for security
function Action makeSystemConsistent(Bool flushTlb,
Bool flushSecurity,
@@ -780,11 +791,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// trap handling & redirect
let trap_updates <- csrf.trap(trap.trap, cast(trap.pc), trap.addr, trap.orig_inst);
CapPipe new_pc = cast(trap_updates.new_pcc);
inIfc.redirectPc(cast(new_pc)
redirectQ.enq(RedirectInfo{trap_pc: cast(new_pc)
`ifdef RVFI_DII
, trap.x.dii_pid + (is_16b_inst(trap.orig_inst) ? 1 : 2)
, dii_pid: trap.x.dii_pid + (is_16b_inst(trap.orig_inst) ? 1 : 2)
`endif
);
});
`ifdef RVFI
Rvfi_Traces rvfis = replicate(tagged Invalid);
rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc));
@@ -825,11 +836,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// kill everything, redirect, and increment epoch
inIfc.killAll;
inIfc.redirectPc(x.pc
`ifdef RVFI_DII
, x.dii_pid
`endif
);
redirectQ.enq(RedirectInfo{trap_pc: x.pc
`ifdef RVFI_DII
, dii_pid: x.dii_pid
`endif
});
inIfc.incrementEpoch;
// the killed Ld should have claimed phy reg, we should not commit it;
@@ -945,11 +956,12 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
m_ret_updates = tagged Valid ret_updates;
`endif
end
inIfc.redirectPc(next_pc
`ifdef RVFI_DII
, x.dii_pid + (is_16b_inst(x.orig_inst) ? 1 : 2)
`endif
);
redirectQ.enq(RedirectInfo{trap_pc: next_pc
`ifdef RVFI_DII
, x.dii_pid + (is_16b_inst(x.orig_inst) ? 1 : 2)
`endif
});
`ifdef RVFI
Rvfi_Traces rvfis = replicate(tagged Invalid);
@@ -1343,6 +1355,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
`endif
endrule
rule pass_redirect;
RedirectInfo ri <- toGet(redirectQ).get;
inIfc.redirectPc(ri.trap_pc, 0
`ifdef RVFI_DII
, ri.rii_pid
`endif
);
endrule
// ================================================================
// INTERFACE

View File

@@ -62,6 +62,8 @@ import Vector::*;
import Assert::*;
import Cntrs::*;
import ConfigReg::*;
import HasSpecBits::*;
import SpecFifo::*;
import TlbTypes::*;
import ITlb::*;
import CCTypes::*;
@@ -131,7 +133,9 @@ interface FetchStage;
// redirection methods
method Action setWaitRedirect;
method Action redirect(CapMem pc
method Action redirect(
CapMem pc,
SpecBits specBits
`ifdef RVFI_DII
, Dii_Parcel_Id parcel_id
`endif
@@ -144,6 +148,7 @@ interface FetchStage;
CapMem pc, CapMem next_pc, IType iType, Bool taken,
PredTrainInfo trainInfo, Bool mispred, Bool isCompressed
);
interface SpeculationUpdate specUpdate;
// security
method Bool emptyForFlush;
@@ -336,7 +341,7 @@ module mkFetchStage(FetchStage);
Integer verbosity = 0;
// Basic State Elements
Reg#(Bool) started <- mkReg(False);
Reg#(Bool) started <- mkConfigReg(False);
// Stall fetch when trap happens or system inst is renamed
// All inst younger than the trap/system inst will be killed
@@ -364,7 +369,14 @@ module mkFetchStage(FetchStage);
function CapMem decompressPc(PcCompressed p) = {pcBlocks.lookup(p.idx),p.lsb};
// Epochs
Ehr#(2, Bool) decode_epoch <- mkEhr(False);
Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch
// fetch estimate of main epoch
Reg#(Epoch) f_main_epoch <- mkConfigReg(0);
SpecFifo#(2, Bit#(0), 1, 1) main_epoch_spec <- mkSpecFifoUG(True);
function Action set_main_epoch(Epoch e, SpecBits sb) = (action
f_main_epoch <= e;
if (main_epoch_spec.notEmpty) main_epoch_spec.deq;
main_epoch_spec.enq(ToSpecFifo{data: ?, spec_bits: sb});
endaction);
// Pipeline Stage FIFOs
Fifo#(2, Fetch1ToFetch2) f12f2 <- mkCFFifo;
@@ -549,12 +561,6 @@ module mkFetchStage(FetchStage);
$display("Fetch3: Nothing else from Fetch2");
end
let drop_f22f3 = f22f3.notEmpty
&& ( fetch3In.main_epoch != f_main_epoch
|| fetch3In.decode_epoch != decode_epoch[1]);
let parse_f22f3 = !drop_f22f3;
// Get ICache/MMIO response if no exception
// In case of exception, we still need to process at least inst_data[0]
// (it will be turned to an exception later), so inst_data[0] must be
@@ -593,7 +599,15 @@ module mkFetchStage(FetchStage);
end
endrule: doFetch3
function Bool isCurrent(Fetch3ToDecode in) = (in.main_epoch == f_main_epoch && in.decode_epoch == decode_epoch[0]);
Bool delay_epoch = False;
`ifdef NO_SPEC_REDIRECT
// Delay decode if the head of this buffer matches the current epoch;
// this means the source of this epoch is still speculative.
delay_epoch = (main_epoch_spec.first.spec_bits != 0);
`endif
function Bool isCurrent(Fetch3ToDecode in) = (main_epoch_spec.notEmpty &&
in.main_epoch == f_main_epoch &&
in.decode_epoch == decode_epoch[0]);
rule doDecodeFlush(f32d.deqS[0].canDeq && !isCurrent(f32d.deqS[0].first));
for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1)
@@ -603,7 +617,12 @@ module mkFetchStage(FetchStage);
end
endrule: doDecodeFlush
rule doDecode(f32d.deqS[0].canDeq && isCurrent(f32d.deqS[0].first));
rule printStuff;
$display("main_epoch_spec.first.spec_bits: %x, main_epoch_spec.notEmpty: %x, isCurrent: %x, f_main_epoch: %x, next_epoch: %x",
main_epoch_spec.first.spec_bits, main_epoch_spec.notEmpty, isCurrent(f32d.deqS[0].first), f_main_epoch, f32d.deqS[0].first.main_epoch);
endrule
rule doDecode(f32d.deqS[0].canDeq && isCurrent(f32d.deqS[0].first) && !delay_epoch);
Vector#(SupSize, Maybe#(InstrFromFetch3)) decodeIn = replicate(Invalid);
// Express the incoming fragments as a vector of maybes.
Vector#(SupSizeX2, Maybe#(Fetch3ToDecode)) frags;
@@ -886,6 +905,7 @@ module mkFetchStage(FetchStage);
started <= True;
waitForRedirect[0] <= False;
waitForFlush[0] <= False;
set_main_epoch(0,0);
endmethod
method Action stop();
started <= False;
@@ -895,18 +915,20 @@ module mkFetchStage(FetchStage);
waitForRedirect[0] <= True;
endmethod
method Action redirect(
CapMem new_pc
CapMem new_pc,
SpecBits specBits
`ifdef RVFI_DII
, Dii_Parcel_Id dii_pid
`endif
);
if (verbose) $display("Redirect: newpc %h, old f_main_epoch %d, new f_main_epoch %d",new_pc,f_main_epoch,f_main_epoch+1);
//if (verbose)
$display("Redirect: newpc %h, old f_main_epoch %d, new f_main_epoch %d, specBits %x",new_pc,f_main_epoch,f_main_epoch+1, specBits);
pc_reg[pc_redirect_port] <= new_pc;
`ifdef RVFI_DII
dii_pid_reg[pc_redirect_port] <= dii_pid;
if (verbose) $display("%t Redirect: dii_pid_reg %d", $time(), dii_pid);
`endif
f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1;
set_main_epoch((f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1, specBits);
// redirect comes, stop stalling for redirect
waitForRedirect[1] <= False;
// this redirect may be caused by a trap/system inst in commit stage
@@ -958,6 +980,8 @@ module mkFetchStage(FetchStage);
end
endmethod
interface SpeculationUpdate specUpdate = main_epoch_spec.specUpdate;
// security
method Bool emptyForFlush;
return empty_for_flush;

View File

@@ -46,10 +46,10 @@ export mkBht;
typedef Bit#(0) BhtTrainInfo; // no training info needs to be remembered
// Local BHT Typedefs
typedef 2048 BhtEntries;
typedef 128 BhtEntries;
typedef Bit#(TLog#(BhtEntries)) BhtIndex;
//(* synthesize *)
(* synthesize *)
module mkBht(DirPredictor#(BhtTrainInfo));
// Read and Write ordering doesn't matter since this is a predictor
// mkRegFileWCF is the RegFile version of mkConfigReg