FetchStage: Use EHRs to remove conflicts between doDecode and doFetch3
This conflict was introduced by 53aacff7c when compressed support was
added. Previously, doDecode could be scheduled in the same cycle as
doFetch3 (and only in that order), but the Reg reads added to doDecode
prevented this. Instead, use EHRs to allow a bypass path from doDecode
to doFetch3. This means we can issue every cycle again, rather than only
every other cycle.
This commit is contained in:
@@ -321,13 +321,13 @@ module mkFetchStage(FetchStage);
|
||||
Integer pc_redirect_port = 2;
|
||||
|
||||
// Epochs
|
||||
Reg#(Bool) decode_epoch <- mkReg(False);
|
||||
Ehr#(2, Bool) decode_epoch <- mkEhr(False);
|
||||
Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch
|
||||
|
||||
// Regs to hold the first half of an instruction that straddles a cache line boundary
|
||||
Reg #(Bool) rg_pending_straddle <- mkReg (False);
|
||||
Reg #(Addr) rg_half_inst_pc <- mkRegU; // The PC of the straddling instruction
|
||||
Reg #(Bit #(16)) rg_half_inst_lsbs <- mkRegU; // The 16 lsbs of the straddling instruction
|
||||
// Regs/wires to hold the first half of an instruction that straddles a cache line boundary
|
||||
Ehr #(2, Bool) ehr_pending_straddle <- mkEhr (False);
|
||||
Ehr #(2, Addr) ehr_half_inst_pc <- mkEhr (?); // The PC of the straddling instruction
|
||||
Ehr #(2, Bit #(16)) ehr_half_inst_lsbs <- mkEhr (?); // The 16 lsbs of the straddling instruction
|
||||
|
||||
// Pipeline Stage FIFOs
|
||||
Fifo#(2, Tuple2#(Bit#(TLog#(SupSize)),Fetch1ToFetch2)) f12f2 <- mkCFFifo;
|
||||
@@ -456,7 +456,7 @@ module mkFetchStage(FetchStage);
|
||||
let out = Fetch1ToFetch2 {
|
||||
pc: pc,
|
||||
pred_next_pc: pred_next_pc,
|
||||
decode_epoch: decode_epoch,
|
||||
decode_epoch: decode_epoch[0],
|
||||
main_epoch: f_main_epoch};
|
||||
f12f2.enq(tuple2(fromInteger(posLastSup),out));
|
||||
if (verbose) $display("Fetch1: ", fshow(out));
|
||||
@@ -539,11 +539,11 @@ module mkFetchStage(FetchStage);
|
||||
end
|
||||
end
|
||||
|
||||
if (fetch3In.decode_epoch != decode_epoch) begin
|
||||
if (fetch3In.decode_epoch != decode_epoch[1]) begin
|
||||
// Just drop it.
|
||||
if (verbosity > 0) begin
|
||||
$display ("----------------");
|
||||
$display ("Fetch3: Drop: decode epoch: %d", decode_epoch);
|
||||
$display ("Fetch3: Drop: decode epoch: %d", decode_epoch[1]);
|
||||
$display ("Fetch3: f22f3.first: ", fshow (f22f3.first));
|
||||
$display ("Fetch3: inst_d: ", fshow (inst_d));
|
||||
end
|
||||
@@ -554,8 +554,8 @@ module mkFetchStage(FetchStage);
|
||||
Addr start_PC = fetch3In.pc;
|
||||
|
||||
// Handle cache-line boundary straddling instruction, if one is pending
|
||||
if (rg_pending_straddle) begin
|
||||
if (fetch3In.pc != rg_half_inst_pc + 4) begin
|
||||
if (ehr_pending_straddle[1]) begin
|
||||
if (fetch3In.pc != ehr_half_inst_pc[1] + 4) begin
|
||||
$display ("----------------");
|
||||
$display ("Fetch3: straddle: pc mismatch");
|
||||
$display ("Fetch3: f22f3.first: ", fshow (f22f3.first));
|
||||
@@ -564,17 +564,17 @@ module mkFetchStage(FetchStage);
|
||||
end
|
||||
else begin
|
||||
// Prepend onto the sequence: { first-half of the instruction , 0 }
|
||||
v_x16 = shiftInAt0 (shiftInAt0 (v_x16, rg_half_inst_lsbs), 0);
|
||||
v_x16 = shiftInAt0 (shiftInAt0 (v_x16, ehr_half_inst_lsbs[1]), 0);
|
||||
let bound = valueOf (SupSizeX2) - 1;
|
||||
if (n_x16s < (fromInteger (bound) - 1))
|
||||
n_x16s = n_x16s + 2;
|
||||
else if (n_x16s < fromInteger (bound))
|
||||
n_x16s = n_x16s + 1;
|
||||
start_PC = rg_half_inst_pc;
|
||||
rg_pending_straddle <= False;
|
||||
start_PC = ehr_half_inst_pc[1];
|
||||
ehr_pending_straddle[1] <= False;
|
||||
if (verbosity > 0) begin
|
||||
$display ("----------------");
|
||||
$display ("Fetch3: straddle: prepend x16 %0h", rg_half_inst_lsbs);
|
||||
$display ("Fetch3: straddle: prepend x16 %0h", ehr_half_inst_lsbs[1]);
|
||||
$display ("Fetch3: f22f3.first: ", fshow (f22f3.first));
|
||||
$display ("Fetch3: inst_d: ", fshow (inst_d));
|
||||
$display ("Fetch3: v_x16: ", fshow (v_x16));
|
||||
@@ -606,7 +606,7 @@ module mkFetchStage(FetchStage);
|
||||
// The main_epoch check is required to make sure this stage doesn't
|
||||
// redirect the PC if a later stage already redirected the PC.
|
||||
if (fetch3In.main_epoch == f_main_epoch) begin
|
||||
Bool decode_epoch_local = decode_epoch; // next value for decode epoch
|
||||
Bool decode_epoch_local = decode_epoch[0]; // next value for decode epoch
|
||||
Maybe#(Addr) redirectPc = Invalid; // next pc redirect by branch predictor
|
||||
Maybe#(TrainNAP) trainNAP = Invalid; // training data sent to next addr pred
|
||||
`ifdef PERF_COUNT
|
||||
@@ -619,9 +619,9 @@ module mkFetchStage(FetchStage);
|
||||
if ((inst_data[i].inst_kind == Inst_32b_Lsbs) && (fromInteger(i) <= nbSup)) begin
|
||||
if (fetch3In.decode_epoch == decode_epoch_local) begin
|
||||
// Save the half-instruction and redirect doFetch1 to get the next cache line
|
||||
rg_pending_straddle <= True;
|
||||
rg_half_inst_pc <= inst_data[i].pc;
|
||||
rg_half_inst_lsbs <= inst_data[i].orig_inst [15:0];
|
||||
ehr_pending_straddle[0] <= True;
|
||||
ehr_half_inst_pc[0] <= inst_data[i].pc;
|
||||
ehr_half_inst_lsbs[0] <= inst_data[i].orig_inst [15:0];
|
||||
decode_epoch_local = ! decode_epoch_local;
|
||||
let next_PC = inst_data[i].pc + 4;
|
||||
redirectPc = tagged Valid (next_PC);
|
||||
@@ -782,7 +782,7 @@ module mkFetchStage(FetchStage);
|
||||
if(redirectPc matches tagged Valid .nextPc) begin
|
||||
pc_reg[pc_decode_port] <= nextPc;
|
||||
end
|
||||
decode_epoch <= decode_epoch_local;
|
||||
decode_epoch[0] <= decode_epoch_local;
|
||||
// send training data for next addr pred
|
||||
if (trainNAP matches tagged Valid .x) begin
|
||||
napTrainByDecQ.enq(x);
|
||||
|
||||
Reference in New Issue
Block a user