Remove the special flush from the Fetch3 stage.
This is an intermediate simplification for moving to SupFifo-based picking.
This commit is contained in:
@@ -173,7 +173,6 @@ typedef struct {
|
||||
Dii_Parcel_Id dii_pid;
|
||||
`endif
|
||||
Maybe#(CapMem) pred_next_pc;
|
||||
Bool fetch3_epoch;
|
||||
Bool decode_epoch;
|
||||
Epoch main_epoch;
|
||||
} Fetch1ToFetch2 deriving(Bits, Eq, FShow);
|
||||
@@ -186,7 +185,6 @@ typedef struct {
|
||||
Maybe#(CapMem) pred_next_pc;
|
||||
Maybe#(Exception) cause;
|
||||
Bool access_mmio; // inst fetch from MMIO
|
||||
Bool fetch3_epoch;
|
||||
Bool decode_epoch;
|
||||
Epoch main_epoch;
|
||||
} Fetch2ToFetch3 deriving(Bits, Eq, FShow);
|
||||
@@ -368,25 +366,40 @@ function ActionValue #(Tuple4 #(SupCntX2,
|
||||
.s_dii_pid,
|
||||
`endif
|
||||
.s_lsbs, .s_mispred}) begin
|
||||
if (pc != getAddr(s_pc) + 2) begin
|
||||
$display ("FetchStage.fav_parse_insts: straddle: pc mismatch: pc = 0x%0h but s_pc = 0x%0h", pc, s_pc);
|
||||
dynamicAssert (False, "FetchStage.fav_parse_insts: straddle: pc mismatch");
|
||||
end
|
||||
pc = getAddr(s_pc);
|
||||
inst_kind = Inst_32b;
|
||||
orig_inst = { v_x16[j], s_lsbs };
|
||||
inst = orig_inst;
|
||||
j = j + 1;
|
||||
next_pc = getAddr(s_pc) + 4;
|
||||
if (!s_mispred) begin
|
||||
if (pc != getAddr(s_pc) + 2) begin
|
||||
$display ("FetchStage.fav_parse_insts: straddle: pc mismatch: pc = 0x%0h but s_pc = 0x%0h", pc, s_pc);
|
||||
dynamicAssert (False, "FetchStage.fav_parse_insts: straddle: pc mismatch");
|
||||
end
|
||||
pc = getAddr(s_pc);
|
||||
inst_kind = Inst_32b;
|
||||
orig_inst = { v_x16[j], s_lsbs };
|
||||
inst = orig_inst;
|
||||
j = j + 1;
|
||||
next_pc = getAddr(s_pc) + 4;
|
||||
`ifdef RVFI_DII
|
||||
if (dii_pid != s_dii_pid + 1) begin
|
||||
$display ("FetchStage.fav_parse_insts: straddle: dii_pid mismatch: dii_pid = %d but s_dii_pid = %d", dii_pid, s_dii_pid);
|
||||
dynamicAssert (False, "FetchStage.fav_parse_insts: straddle: dii_pid mismatch");
|
||||
end
|
||||
dii_pid = s_dii_pid;
|
||||
next_dii_pid = s_dii_pid + 2;
|
||||
if (dii_pid != s_dii_pid + 1) begin
|
||||
$display ("FetchStage.fav_parse_insts: straddle: dii_pid mismatch: dii_pid = %d but s_dii_pid = %d", dii_pid, s_dii_pid);
|
||||
dynamicAssert (False, "FetchStage.fav_parse_insts: straddle: dii_pid mismatch");
|
||||
end
|
||||
dii_pid = s_dii_pid;
|
||||
next_dii_pid = s_dii_pid + 2;
|
||||
`endif
|
||||
n_items = 1;
|
||||
n_items = 1;
|
||||
end else begin // This is a mispredicted half of a 32-bit instruction. We will flush, but just pretend it's a 16-bit instruction to keep things in sync.
|
||||
pc = getAddr(s_pc);
|
||||
inst_kind = Inst_16b;
|
||||
orig_inst = zeroExtend (s_lsbs);
|
||||
inst = orig_inst; // Expand 16b inst to 32b inst
|
||||
next_pc = getAddr(pc_start);
|
||||
`ifdef RVFI_DII
|
||||
dii_pid = s_dii_pid;
|
||||
next_dii_pid = s_dii_pid + 1;
|
||||
`endif
|
||||
n_items = 1;
|
||||
if (verbose)
|
||||
$display ("FetchStage.fav_parse_insts: mispredicted 1/2 inst 0x%0h -> inst 0x%0h", orig_inst, inst);
|
||||
end
|
||||
end
|
||||
else if (is_16b_inst (v_x16 [j])) begin
|
||||
inst_kind = Inst_16b;
|
||||
@@ -414,12 +427,17 @@ function ActionValue #(Tuple4 #(SupCntX2,
|
||||
n_items = i + 1;
|
||||
end
|
||||
else begin
|
||||
Bool mispred_first_half = isValid(pred_next_pc);
|
||||
next_straddle = tagged Valid fv_straddle(setAddrUnsafe(pc_start, pc),
|
||||
`ifdef RVFI_DII
|
||||
dii_pid,
|
||||
`endif
|
||||
v_x16[j], isValid(pred_next_pc));
|
||||
v_x16[j], mispred_first_half);
|
||||
j = j + 1;
|
||||
`ifdef RVFI_DII
|
||||
// If this is the case, we will flush this instruction but should keep the pid in sync in the mean time.
|
||||
//if (mispred_first_half) next_dii_pid = dii_pid + 2;
|
||||
`endif
|
||||
// Leave next_pc unchanged and clear pred_next_pc so we
|
||||
// return the right predicted pc for the vector, which
|
||||
// excludes the pending straddle.
|
||||
@@ -464,8 +482,8 @@ module mkFetchStage(FetchStage);
|
||||
// rule ordering: Fetch1 (BTB+TLB) < Fetch3 (decode & dir pred) < redirect method
|
||||
// Fetch1 < Fetch3 to avoid bypassing path on PC and epochs
|
||||
|
||||
Bool verbose = False;
|
||||
Integer verbosity = 0;
|
||||
Bool verbose = True;
|
||||
Integer verbosity = 2;
|
||||
|
||||
// Basic State Elements
|
||||
Reg#(Bool) started <- mkReg(False);
|
||||
@@ -494,7 +512,6 @@ module mkFetchStage(FetchStage);
|
||||
Integer pc_redirect_port = 3;
|
||||
|
||||
// Epochs
|
||||
Reg#(Bool) fetch3_epoch <- mkReg(False);
|
||||
Ehr#(2, Bool) decode_epoch <- mkEhr(False);
|
||||
Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch
|
||||
|
||||
@@ -616,7 +633,6 @@ module mkFetchStage(FetchStage);
|
||||
dii_pid: dii_pid,
|
||||
`endif
|
||||
pred_next_pc: pred_next_pc,
|
||||
fetch3_epoch: fetch3_epoch,
|
||||
decode_epoch: decode_epoch[0],
|
||||
main_epoch: f_main_epoch};
|
||||
|
||||
@@ -687,7 +703,6 @@ module mkFetchStage(FetchStage);
|
||||
pred_next_pc: in.pred_next_pc,
|
||||
cause: cause,
|
||||
access_mmio: access_mmio,
|
||||
fetch3_epoch: in.fetch3_epoch,
|
||||
decode_epoch: in.decode_epoch,
|
||||
main_epoch: in.main_epoch };
|
||||
f22f3.enq(tuple2(nbSupX2,out));
|
||||
@@ -754,8 +769,7 @@ module mkFetchStage(FetchStage);
|
||||
|
||||
let drop_f22f3 = f22f3.notEmpty
|
||||
&& ( fetch3In.main_epoch != f_main_epoch
|
||||
|| fetch3In.decode_epoch != decode_epoch[1]
|
||||
|| fetch3In.fetch3_epoch != fetch3_epoch);
|
||||
|| fetch3In.decode_epoch != decode_epoch[1]);
|
||||
|
||||
let parse_f22f3 = !drop_f22f3 && (pending_n_items == 0 || can_merge);
|
||||
|
||||
@@ -791,14 +805,14 @@ module mkFetchStage(FetchStage);
|
||||
end
|
||||
if (verbosity >= 2) begin
|
||||
$display ("----------------");
|
||||
$display ("Fetch3: Drop: main_epoch: %d decode epoch: %d fetch3 epoch %d", f_main_epoch, decode_epoch[1], fetch3_epoch);
|
||||
$display ("Fetch3: Drop: main_epoch: %d decode epoch: %d", f_main_epoch, decode_epoch[1]);
|
||||
$display ("Fetch3: f22f3.first: ", fshow (f22f3.first));
|
||||
$display ("Fetch3: inst_d: ", fshow (inst_d));
|
||||
end
|
||||
end
|
||||
else if (parse_f22f3) begin
|
||||
Vector#(SupSizeX2, Instruction16) v_x16 = map(fromMaybe(?), inst_d);
|
||||
SupCntX2 n_x16s = min(zeroExtend(nbSupX2In) + 1, pack(countIf(isValid, inst_d)));
|
||||
SupCntX2 n_x16s = zeroExtend(nbSupX2In) + 1;
|
||||
|
||||
// Parse v_x16 into 32-bit and 16-bit instructions
|
||||
CapMem pred_next_pc;
|
||||
@@ -821,22 +835,6 @@ module mkFetchStage(FetchStage);
|
||||
end else begin
|
||||
out.pred_next_pc = pred_next_pc;
|
||||
end
|
||||
|
||||
// Redirect doFetch1 if we predicted a taken compressed branch
|
||||
// but this is an uncompressed instruction. We will tell decode
|
||||
// to retrain when we issue the full instruction next time.
|
||||
if (pending_straddle matches tagged Valid {.s_pc,
|
||||
`ifdef RVFI_DII
|
||||
.s_dii_pid,
|
||||
`endif
|
||||
.s_lsbs, .s_mispred}
|
||||
&&& s_mispred) begin
|
||||
pc_reg[pc_fetch3_port] <= addPc(s_pc, 2);
|
||||
`ifdef RVFI_DII
|
||||
dii_pid_reg[pc_fetch3_port] <= s_dii_pid + 1;
|
||||
`endif
|
||||
fetch3_epoch <= ! fetch3_epoch;
|
||||
end
|
||||
end
|
||||
|
||||
SupCntX2S1 next_pending_n_items = 0;
|
||||
@@ -893,6 +891,7 @@ module mkFetchStage(FetchStage);
|
||||
// This means we started fetching from a line straddling
|
||||
// instruction; need another cycle to have something to
|
||||
// issue.
|
||||
|
||||
dynamicAssert(isValid(pending_straddle), "Decoded no instructions and no straddle!");
|
||||
end
|
||||
end
|
||||
@@ -945,7 +944,19 @@ module mkFetchStage(FetchStage);
|
||||
|
||||
// do decode and branch prediction
|
||||
// Drop here if does not match the decode_epoch.
|
||||
if (in.decode_epoch == decode_epoch_local) begin
|
||||
|
||||
// We predicted a taken branch for PC, but this is an
|
||||
// uncompressed instruction, so we redirect to this PC and
|
||||
// train it to fetch the other half in future.
|
||||
if (in.decode_epoch == decode_epoch_local && i==0 && decodeIn.mispred_first_half) begin
|
||||
if (verbose) $display("mispredicted first half in decode: pc : %h", in.pc);
|
||||
decode_epoch_local = !decode_epoch_local;
|
||||
redirectPc = Valid (in.pc); // record redirect to the first PC in this bundle.
|
||||
trainNAP = Valid (TrainNAP {pc: in.pc, nextPc: addPc(in.pc, 2)});
|
||||
`ifdef RVFI_DII
|
||||
redirectDiiPid = Valid (in.dii_pid);
|
||||
`endif
|
||||
end else if (in.decode_epoch == decode_epoch_local) begin
|
||||
doAssert(in.main_epoch == f_main_epoch, "main epoch must match");
|
||||
|
||||
let decode_result = decode(in.inst, getFlags(inst_data[i].pc)==1); // Decode 32b inst, or 32b expansion of 16b inst
|
||||
@@ -1011,22 +1022,15 @@ module mkFetchStage(FetchStage);
|
||||
ras.ras[i].popPush(False, Valid (push_addr));
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(verbose) begin
|
||||
$display("Branch prediction: ", fshow(dInst.iType), " ; ", fshow(in.pc), " ; ",
|
||||
fshow(in.ppc), " ; ", fshow(pred_taken), " ; ", fshow(nextPc));
|
||||
end
|
||||
|
||||
if (i == 0 && decodeIn.mispred_first_half) begin
|
||||
// We predicted a taken branch for PC, but this is an
|
||||
// uncompressed instruction, so we train it to fetch
|
||||
// the other half in future.
|
||||
trainNAP = Valid (TrainNAP {pc: in.pc, nextPc: addPc(in.pc, 2)});
|
||||
end
|
||||
|
||||
// check previous mispred
|
||||
if (nextPc matches tagged Valid .decode_pred_next_pc &&& decode_pred_next_pc != in.ppc) begin
|
||||
if (nextPc matches tagged Valid .decode_pred_next_pc &&& (decode_pred_next_pc != in.ppc)) begin
|
||||
if (verbose) $display("ppc and decodeppc : %h %h", in.ppc, decode_pred_next_pc);
|
||||
decode_epoch_local = !decode_epoch_local;
|
||||
redirectPc = Valid (decode_pred_next_pc); // record redirect next pc
|
||||
@@ -1036,8 +1040,7 @@ module mkFetchStage(FetchStage);
|
||||
in.ppc = decode_pred_next_pc;
|
||||
// train next addr pred when mispredict
|
||||
let last_x16_pc = addPc(in.pc, ((inst_data[i].inst_kind == Inst_32b) ? 2 : 0));
|
||||
if (!decodeIn.mispred_first_half)
|
||||
trainNAP = Valid (TrainNAP {pc: last_x16_pc, nextPc: decode_pred_next_pc});
|
||||
trainNAP = Valid (TrainNAP {pc: last_x16_pc, nextPc: decode_pred_next_pc});
|
||||
`ifdef PERF_COUNT
|
||||
// performance stats: record decode redirect
|
||||
doAssert(redirectInst == Invalid, "at most 1 decode redirect per cycle");
|
||||
|
||||
Reference in New Issue
Block a user