|
|
|
|
@@ -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 #(3, 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);
|
|
|
|
|
@@ -853,6 +853,7 @@ module mkFetchStage(FetchStage);
|
|
|
|
|
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);
|
|
|
|
|
pc_reg[pc_redirect_port] <= new_pc;
|
|
|
|
|
f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1;
|
|
|
|
|
ehr_pending_straddle[2] <= False;
|
|
|
|
|
// redirect comes, stop stalling for redirect
|
|
|
|
|
waitForRedirect <= False;
|
|
|
|
|
setWaitRedirect_redirect_conflict.wset(?); // conflict with setWaitForRedirect
|
|
|
|
|
|