Bump BSV-RVFI-DII and refactor to support new parcel-based interface

This means FetchStage should now behave in the same way with RVFI-DII as
with an I-Cache. A Dii_Parcel_Id is fed alongside PC everywhere relevant
and follows very similar logic, but, importantly it's just extra state
on the side, it doesn't affect what we do with the branch predictor and
parcel combining/instruction decoding logic.
This commit is contained in:
Jessica Clarke
2020-07-21 13:24:39 +01:00
parent 7d98946103
commit 0516db5e8d
13 changed files with 247 additions and 184 deletions

View File

@@ -270,10 +270,7 @@ module mkCore#(CoreId coreId)(Core);
// bridge that can insert instructions.
`ifdef RVFI_DII
Toooba_RVFI_DII_Bridge_IFC rvfi_bridge <- mkTooobaRVFIDIIBridge;
mkConnection(rvfi_bridge.dii, fetchStage.dii);
rule rl_passLastId;
fetchStage.lastTraceId(rvfi_bridge.lastId);
endrule
mkConnection(rvfi_bridge.dii, fetchStage.diiIfc);
`endif
// back end
@@ -399,7 +396,7 @@ module mkCore#(CoreId coreId)(Core);
epochManager.incrementEpoch;
fetchStage.redirect(new_pc
`ifdef RVFI_DII
, inst_tag.diid + 1
, inst_tag.dii_next_pid
`endif
);
globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag);

View File

@@ -43,7 +43,7 @@ import Trace_Data2 :: *;
`endif
`ifdef RVFI_DII
import Types :: *;
import ProcTypes :: *;
`endif
`ifdef DEBUG_WEDGE

View File

@@ -54,7 +54,7 @@ import Debug_Module :: *;
`endif
`ifdef RVFI_DII
import Types :: *;
import ProcTypes :: *;
`endif
`ifdef INCLUDE_TANDEM_VERIF

View File

@@ -116,7 +116,7 @@ interface CommitInput;
method Action killAll;
method Action redirectPc(CapMem trap_pc
`ifdef RVFI_DII
, Dii_Id diid
, Dii_Parcel_Id dii_pid
`endif
);
method Action setFetchWaitRedirect;
@@ -768,9 +768,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
CapPipe new_pc = cast(trap_updates.new_pcc);
inIfc.redirectPc(cast(new_pc)
`ifdef RVFI_DII
, trap.x.diid + 1
, 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));
@@ -818,7 +818,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
inIfc.killAll;
inIfc.redirectPc(x.pc
`ifdef RVFI_DII
, x.diid
, x.dii_pid
`endif
);
inIfc.incrementEpoch;
@@ -938,7 +938,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
end
inIfc.redirectPc(next_pc
`ifdef RVFI_DII
, x.diid + 1
, x.dii_pid + (is_16b_inst(x.orig_inst) ? 1 : 2)
`endif
);

View File

@@ -84,6 +84,30 @@ import CPU_Decode_C :: *;
// ================================================================
`ifdef RVFI_DII
interface RvfiDiiServer;
interface Client#(Dii_Parcel_Id, Dii_Parcels) toCore;
interface Server#(Dii_Parcel_Id, Vector#(SupSize, Maybe#(Instruction))) fromDii;
endinterface
module mkRvfiDiiServer(RvfiDiiServer);
Fifo#(2, Dii_Parcel_Id) reqs <- mkCFFifo;
Fifo#(2, Vector#(SupSize, Maybe#(Instruction))) resps <- mkCFFifo;
interface Client toCore;
interface Get request = toGet(reqs);
interface Put response;
method Action put(Dii_Parcels parcels);
function Maybe#(a) toMaybe(a x) = tagged Valid x;
resps.enq(map(toMaybe, unpack(pack(parcels))));
endmethod
endinterface
endinterface
interface fromDii = toGPServer(reqs, resps);
endmodule
`endif
interface FetchStage;
// pipeline
interface Vector#(SupSize, SupFifoDeq#(FromFetchStage)) pipelines;
@@ -92,11 +116,14 @@ interface FetchStage;
interface ITlb iTlbIfc;
interface ICoCache iMemIfc;
interface MMIOInstToCore mmioIfc;
`ifdef RVFI_DII
interface Client#(Dii_Parcel_Id, Dii_Parcels) diiIfc;
`endif
// starting and stopping
method Action start(CapMem pc
`ifdef RVFI_DII
, Dii_Id id
, Dii_Parcel_Id parcel_id
`endif
);
method Action stop();
@@ -105,7 +132,7 @@ interface FetchStage;
method Action setWaitRedirect;
method Action redirect(CapMem pc
`ifdef RVFI_DII
, Dii_Id id
, Dii_Parcel_Id parcel_id
`endif
);
`ifdef INCLUDE_GDB_CONTROL
@@ -124,10 +151,6 @@ interface FetchStage;
// debug
method FetchDebugState getFetchState;
`ifdef RVFI_DII
interface Client#(Dii_Ids, InstsAndIDs) dii;
method Action lastTraceId(Dii_Id in);
`endif
`ifdef DEBUG_WEDGE
method Tuple3#(Bit#(32), Addr, Addr) debugFetch;
@@ -146,6 +169,9 @@ typedef struct {
typedef struct {
CapMem pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
Maybe#(CapMem) pred_next_pc;
Bool fetch3_epoch;
Bool decode_epoch;
@@ -154,6 +180,9 @@ typedef struct {
typedef struct {
CapMem pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
Maybe#(CapMem) pred_next_pc;
Maybe#(Exception) cause;
Bool access_mmio; // inst fetch from MMIO
@@ -174,6 +203,9 @@ typedef struct {
// Used purely internally in doDecode.
typedef struct {
CapMem pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
CapMem ppc;
Bool decode_epoch;
Epoch main_epoch;
@@ -183,6 +215,9 @@ typedef struct {
typedef struct {
CapMem pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
CapMem ppc;
Epoch main_epoch;
DirPredTrainInfo dpTrain;
@@ -192,9 +227,6 @@ typedef struct {
ArchRegs regs;
Maybe#(Exception) cause;
Addr tval; // in case of exception
`ifdef RVFI_DII
Dii_Id diid;
`endif
} FromFetchStage deriving (Bits, Eq, FShow);
// train next addr pred (BTB)
@@ -260,6 +292,9 @@ deriving (Bits, Eq, FShow);
typedef struct {
CapMem pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid;
`endif
Inst_Kind inst_kind;
Bit #(32) orig_inst; // inst_kind => 0, 16b or 32b relevant
Bit #(32) inst; // Original 32b instruction, or expansion of 16b instruction
@@ -268,7 +303,11 @@ deriving (Bits, Eq, FShow);
instance DefaultValue #(Inst_Item);
function Inst_Item defaultValue = Inst_Item {
pc: nullCap, inst_kind: Inst_None, orig_inst: 0, inst: 0
pc: nullCap,
`ifdef RVFI_DII
dii_pid: 0,
`endif
inst_kind: Inst_None, orig_inst: 0, inst: 0
};
endinstance
@@ -293,7 +332,18 @@ function ActionValue #(Tuple2 #(SupCntX2,
endactionvalue
endfunction
typedef Maybe #(Tuple3 #(CapMem, Bit #(16), Bool)) MStraddle;
`ifdef RVFI_DII
typedef Tuple4 #(CapMem, Dii_Parcel_Id, Bit #(16), Bool) Straddle;
function Straddle fv_straddle (CapMem pc, Dii_Parcel_Id dii_pid, Bit #(16) lsbs, Bool mispred);
return tuple4 (pc, dii_pid, lsbs, mispred);
endfunction
`else
typedef Tuple3 #(CapMem, Bit #(16), Bool) Straddle;
function Straddle fv_straddle (CapMem pc, Bit #(16) lsbs, Bool mispred);
return tuple3 (pc, lsbs, mispred);
endfunction
`endif
typedef Maybe #(Straddle) MStraddle;
// Parse 16b parcels (v_x16) into a sequence of 16b or 32b instructions.
// This is a pure function; ActionValue is used only to allow $displays for debugging.
@@ -303,6 +353,9 @@ function ActionValue #(Tuple4 #(SupCntX2,
MStraddle))
fav_parse_insts (Bool verbose,
CapMem pc_start,
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid_start,
`endif
Maybe #(CapMem) pred_next_pc,
MStraddle pending_straddle,
SupCntX2 n_x16s,
@@ -310,6 +363,9 @@ function ActionValue #(Tuple4 #(SupCntX2,
actionvalue
// Parse up to SupSizeX2 instructions (v_items) from fetched v_x16 parcels (v_x16).
Vector #(SupSizeX2, Inst_Item) v_items = replicate (Inst_Item {pc: pc_start,
`ifdef RVFI_DII
dii_pid: dii_pid_start,
`endif
inst_kind: Inst_None,
orig_inst: 0,
inst: 0});
@@ -317,15 +373,24 @@ function ActionValue #(Tuple4 #(SupCntX2,
// Start parse at parcel 0/1 depending on pc lsbs.
SupCntX2 j = (getAddr(pc_start) [1:0] == 2'b00 ? 0 : 1);
Addr pc = getAddr(pc_start);
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid = dii_pid_start;
`endif
Integer n_items = 0;
`ifndef RVFI_DII
for (Integer i = 0; i < valueOf (SupSizeX2); i = i + 1) begin
Inst_Kind inst_kind = Inst_None;
Bit #(32) orig_inst = 0;
Bit #(32) inst = 0;
Addr next_pc = pc;
`ifdef RVFI_DII
Dii_Parcel_Id next_dii_pid = dii_pid;
`endif
if (j < n_x16s) begin
if (i == 0 &&& pending_straddle matches tagged Valid {.s_pc, .s_lsbs, .s_mispred}) begin
if (i == 0 &&& pending_straddle matches tagged Valid {.s_pc,
`ifdef RVFI_DII
.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");
@@ -336,6 +401,14 @@ function ActionValue #(Tuple4 #(SupCntX2,
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;
`endif
n_items = 1;
end
else if (is_16b_inst (v_x16 [j])) begin
@@ -344,6 +417,9 @@ function ActionValue #(Tuple4 #(SupCntX2,
inst = fv_decode_C (misa, misa_mxl_64, v_x16 [j]); // Expand 16b inst to 32b inst
j = j + 1;
next_pc = pc + 2;
`ifdef RVFI_DII
next_dii_pid = dii_pid + 1;
`endif
n_items = i + 1;
if (verbose)
$display ("FetchStage.fav_parse_insts: C inst 0x%0h -> inst 0x%0h", orig_inst, inst);
@@ -355,10 +431,17 @@ function ActionValue #(Tuple4 #(SupCntX2,
inst = orig_inst;
j = j + 2;
next_pc = pc + 4;
`ifdef RVFI_DII
next_dii_pid = dii_pid + 2;
`endif
n_items = i + 1;
end
else begin
next_straddle = tagged Valid tuple3(setAddrUnsafe(pc_start, pc), v_x16[j], 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));
j = j + 1;
// Leave next_pc unchanged and clear pred_next_pc so we
// return the right predicted pc for the vector, which
@@ -374,23 +457,16 @@ function ActionValue #(Tuple4 #(SupCntX2,
dynamicAssert (False, "FetchStage.fav_parse_insts: instuction is not 16b or 32b?");
end
end
v_items [i] = Inst_Item {pc: setAddrUnsafe(pc_start, pc), inst_kind: inst_kind, orig_inst: orig_inst, inst: inst};
pc = next_pc;
end
`else
Addr increment = 0;
for (Integer i = 0; i < valueOf(SupSize); i = i + 1) begin
Bit #(32) inst = { v_x16 [(2*i)+1], v_x16 [2*i] };
Bool compressed = is_16b_inst (v_x16 [2*i]);
v_items[i].inst_kind = compressed ? Inst_16b:Inst_32b;
increment = (compressed ? 2:4);
v_items[i].orig_inst = inst;
v_items[i].inst = (compressed) ? fv_decode_C (misa, misa_mxl_64, v_x16 [2*i]):inst;
v_items[i].pc = setAddrUnsafe(pc_start, pc);
pc = pc + increment;
end
n_items = 2;
v_items [i] = Inst_Item {pc: setAddrUnsafe(pc_start, pc),
`ifdef RVFI_DII
dii_pid: dii_pid,
`endif
inst_kind: inst_kind, orig_inst: orig_inst, inst: inst};
pc = next_pc;
`ifdef RVFI_DII
dii_pid = next_dii_pid;
`endif
end
if (verbose) begin
$display ("FetchStage.fav_parse_insts:");
@@ -432,6 +508,9 @@ module mkFetchStage(FetchStage);
Reg#(Bool) waitForFlush <- mkReg(False);
Ehr#(4, CapMem) pc_reg <- mkEhr(nullCap);
`ifdef RVFI_DII
Ehr#(4, Dii_Parcel_Id) dii_pid_reg <- mkEhr(0);
`endif
Integer pc_fetch1_port = 0;
Integer pc_decode_port = 1;
Integer pc_fetch3_port = 2;
@@ -448,9 +527,6 @@ module mkFetchStage(FetchStage);
Reg #(Vector #(SupSizeX2S1, Inst_Item)) rg_pending_decode <- mkReg(replicate(defaultValue));
Reg #(SupCntX2S1) rg_pending_n_items <- mkReg(0);
Reg #(Fetch3ToDecode) rg_pending_f32d <- mkRegU;
`ifdef RVFI_DII
Reg #(Maybe#(Tuple2#(Epoch,CapMem))) rg_f3_next_consecutive_pc <- mkReg(Invalid);
`endif
// Pipeline Stage FIFOs
Fifo#(2, Tuple2#(Bit#(TLog#(SupSizeX2)),Fetch1ToFetch2)) f12f2 <- mkCFFifo;
@@ -477,6 +553,9 @@ module mkFetchStage(FetchStage);
ITlb iTlb <- mkITlb;
ICoCache iMem <- mkICoCache;
MMIOInst mmio <- mkMMIOInst;
`ifdef RVFI_DII
RvfiDiiServer dii <- mkRvfiDiiServer;
`endif
Server#(Addr, TlbResp) tlb_server = iTlb.to_proc;
Server#(Addr, Vector#(SupSize, Maybe#(Instruction))) mem_server = iMem.to_proc;
@@ -508,15 +587,6 @@ module mkFetchStage(FetchStage);
endrule
`endif
`ifdef RVFI_DII
Ehr#(4, Dii_Id) dii_id_next <- mkEhr(0);
Fifo#(2, Dii_Ids) dii_instIds <- mkCFFifo;
Fifo#(2, InstsAndIDs) dii_insts <- mkCFFifo;
Fifo#(2, Dii_Ids) dii_fetched_ids <- mkCFFifo;
Reg#(Dii_Id) last_trace_id <- mkRegU;
`endif
`ifdef DEBUG_WEDGE
Reg#(Addr) lastItlbReq <- mkConfigReg(0);
Reg#(Addr) lastImemReq <- mkConfigReg(0);
@@ -535,9 +605,6 @@ module mkFetchStage(FetchStage);
if (! done) begin
Bool isLastX2 = (i == (valueOf (SupSizeX2) - 1)) || ((getAddr(pc)[1:0] != 2'b00) && (i == (valueOf (SupSizeX2) - 2)));
Bool lastInstInCacheLine = (getLineInstOffset (getAddr(prev_PC)) == maxBound) && (getAddr(prev_PC)[1:0] != 2'b00);
`ifdef RVFI_DII
lastInstInCacheLine = False;
`endif
Bool isJump = isValid(pred_next_pc);
done = isLastX2 || lastInstInCacheLine || isJump;
posLastSupX2 = i;
@@ -587,13 +654,8 @@ module mkFetchStage(FetchStage);
pc_reg[pc_fetch1_port] <= next_fetch_pc;
`ifdef RVFI_DII
Dii_Id next_id = dii_id_next[pc_fetch1_port];
Dii_Ids reqs = replicate(tagged Invalid);
for (Integer i = 0; i < valueOf(SupSize); i = i + 1)
reqs[i] = tagged Valid (next_id + fromInteger(i));
if (verbosity > 0) $display("Requested from DII", fshow(reqs));
dii_instIds.enq(reqs);
dii_id_next[pc_fetch1_port] <= next_id + fromInteger(valueOf(SupSize));
Dii_Parcel_Id dii_pid = dii_pid_reg[pc_fetch1_port];
dii_pid_reg[pc_fetch1_port] <= dii_pid + (fromInteger(posLastSupX2) + 1);
`endif
// Send TLB request.
@@ -606,6 +668,9 @@ module mkFetchStage(FetchStage);
let out = Fetch1ToFetch2 {
pc: pc,
`ifdef RVFI_DII
dii_pid: dii_pid,
`endif
pred_next_pc: pred_next_pc,
fetch3_epoch: fetch3_epoch,
decode_epoch: decode_epoch[0],
@@ -625,7 +690,15 @@ module mkFetchStage(FetchStage);
// Access main mem or boot rom if no TLB exception
Bool access_mmio = False;
`ifndef RVFI_DII
`ifdef RVFI_DII
if (!isValid(cause)) begin
// We 32-bit align PC (and increment nbSupX2 accordingly) in
// doFetch1 for the real MMIO and ICache require 32-bit, so make
// DII look like that by decrementing pid if PC is "odd"; this
// extra parcel on the front will be discarded by fav_parse_insts.
dii.fromDii.request.put(in.dii_pid - (getAddr(in.pc)[1:0] == 2'b00 ? 0 : 1));
end
`else
if (!isValid(cause)) begin
case(mmio.getFetchTarget(phys_pc))
MainMem: begin
@@ -666,6 +739,9 @@ module mkFetchStage(FetchStage);
let out = Fetch2ToFetch3 {
pc: in.pc,
`ifdef RVFI_DII
dii_pid: in.dii_pid,
`endif
pred_next_pc: in.pred_next_pc,
cause: cause,
access_mmio: access_mmio,
@@ -713,10 +789,19 @@ module mkFetchStage(FetchStage);
SupCntX2 parsed_n_items = 0;
CapMem pc = fetch3In.pc;
`ifdef RVFI_DII
Dii_Parcel_Id dii_pid = fetch3In.dii_pid;
`endif
Inst_Item inst_item_none = ?;
Vector #(SupSizeX2, Inst_Item) parsed_v_items = ?;
let mispred_first_half = pending_straddle matches tagged Valid {.s_pc, .s_lsbs, .s_mispred} &&& s_mispred ? True : False;
let mispred_first_half = pending_straddle matches tagged Valid {.s_pc,
`ifdef RVFI_DII
.s_dii_pid,
`endif
.s_lsbs, .s_mispred}
&&& s_mispred ? True : False;
let can_merge = pending_n_items > 0
&& pending_n_items < fromInteger(valueOf(SupSize))
&& f22f3.notEmpty
@@ -732,7 +817,6 @@ module mkFetchStage(FetchStage);
let parse_f22f3 = !drop_f22f3 && (pending_n_items == 0 || can_merge);
`ifndef RVFI_DII
// 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
@@ -741,6 +825,9 @@ module mkFetchStage(FetchStage);
if (drop_f22f3 || parse_f22f3) begin
f22f3.deq();
if (!isValid(fetch3In.cause)) begin
`ifdef RVFI_DII
inst_d <- dii.fromDii.response.get;
`else
if(fetch3In.access_mmio) begin
if(verbose) $display("get answer from MMIO 0x%0x", getAddr(pc));
inst_d <- mmio.bootRomResp;
@@ -749,17 +836,9 @@ module mkFetchStage(FetchStage);
if(verbose) $display("get answer from memory 0x%0x", getAddr(pc));
inst_d <- mem_server.response.get;
end
`endif
end
end
`else
f22f3.deq();
Vector#(SupSize,Maybe#(Instruction)) inst_d = replicate(tagged Valid dii_nop);
InstsAndIDs ii <- toGet(dii_insts).get();
inst_d = ii.insts;
if (verbosity > 0) $display("Got from DII: ", fshow (ii));
if(verbose) $display("PC is %x", pc);
Maybe#(Tuple2#(Epoch, CapMem)) next_consecutive_pc = Invalid;
`endif
if (verbosity >= 2) begin
$display ("----------------");
$display ("Fetch3: f22f3.first: ", fshow (f22f3.first));
@@ -778,11 +857,11 @@ module mkFetchStage(FetchStage);
end
end
else if (parse_f22f3) begin
inst_item_none = Inst_Item {pc: pc,
`ifdef RVFI_DII
if (rg_f3_next_consecutive_pc matches tagged Valid .epoch_pc &&& tpl_1(epoch_pc) == fetch3In.main_epoch)
pc = tpl_2(epoch_pc);
dii_pid: dii_pid,
`endif
inst_item_none = Inst_Item {pc: pc, inst_kind: Inst_None, orig_inst: 0, inst: 0};
inst_kind: Inst_None, orig_inst: 0, inst: 0};
parsed_v_items = replicate (inst_item_none);
// Re-interpret fetched 32b parcels (inst_d) as 16b parcels
let { n_x16s, v_x16 } <- fav_inst_d_to_x16s (inst_d);
@@ -799,7 +878,11 @@ module mkFetchStage(FetchStage);
// Parse v_x16 into 32-bit and 16-bit instructions
CapMem pred_next_pc;
{parsed_n_items, parsed_v_items, pred_next_pc, pending_straddle} <-
fav_parse_insts (verbose, pc, fetch3In.pred_next_pc, pending_straddle, n_x16s, v_x16);
fav_parse_insts (verbose, pc,
`ifdef RVFI_DII
dii_pid,
`endif
fetch3In.pred_next_pc, pending_straddle, n_x16s, v_x16);
if (pending_n_items == 0) begin
out = Fetch3ToDecode {
@@ -812,16 +895,20 @@ module mkFetchStage(FetchStage);
};
end
out.pred_next_pc = pred_next_pc;
`ifdef RVFI_DII
next_consecutive_pc = isValid(fetch3In.pred_next_pc) ? Invalid : Valid(tuple2(fetch3In.main_epoch, out.pred_next_pc));
`endif
// 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, .s_lsbs, .s_mispred}
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
@@ -866,9 +953,6 @@ module mkFetchStage(FetchStage);
end
if (n_items > 0) begin
`ifdef RVFI_DII
dii_fetched_ids.enq(ii.ids);
`endif
instdata.enq(take(v_items));
f32d.enq(tuple2(nbSupOut, out));
if (verbosity >= 2) begin
@@ -888,9 +972,6 @@ module mkFetchStage(FetchStage);
end
rg_pending_n_items <= next_pending_n_items;
ehr_pending_straddle[0] <= pending_straddle;
`ifdef RVFI_DII
rg_f3_next_consecutive_pc <= next_consecutive_pc;
`endif
endrule: doFetch3
rule doDecode;
@@ -898,16 +979,14 @@ module mkFetchStage(FetchStage);
f32d.deq();
let inst_data = instdata.first();
instdata.deq();
`ifdef RVFI_DII
let ids = dii_fetched_ids.first();
dii_fetched_ids.deq();
Dii_Id nextId = dii_id_next[pc_decode_port];
`endif
// 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 (decodeIn.main_epoch == f_main_epoch) begin
Bool decode_epoch_local = decode_epoch[0]; // next value for decode epoch
Maybe#(CapMem) redirectPc = Invalid; // next pc redirect by branch predictor
`ifdef RVFI_DII
Maybe#(Dii_Parcel_Id) redirectDiiPid = Invalid;
`endif
Maybe#(TrainNAP) trainNAP = Invalid; // training data sent to next addr pred
`ifdef PERF_COUNT
// performance counter: inst being redirect by decode stage
@@ -922,6 +1001,9 @@ module mkFetchStage(FetchStage);
let inst_data_shifted = shiftInAtN (inst_data, ?); // for predicted PCs
let in = InstrFromFetch3 {
pc: inst_data[i].pc,
`ifdef RVFI_DII
dii_pid: inst_data[i].dii_pid,
`endif
// last inst, next pc may not be pc+2/pc+4
ppc: ((fromInteger(i) == nbSup)
? decodeIn.pred_next_pc
@@ -1022,14 +1104,14 @@ module mkFetchStage(FetchStage);
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
`ifdef RVFI_DII
redirectDiiPid = Valid (in.dii_pid + ((inst_data[i].inst_kind == Inst_32b) ? 2 : 1));
`endif
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});
`ifdef RVFI_DII
nextId = fromMaybe(nextId,ids[i]) + 1;
`endif
`ifdef PERF_COUNT
// performance stats: record decode redirect
doAssert(redirectInst == Invalid, "at most 1 decode redirect per cycle");
@@ -1038,6 +1120,9 @@ module mkFetchStage(FetchStage);
end
end // if (!isValid(cause))
let out = FromFetchStage{pc: in.pc,
`ifdef RVFI_DII
dii_pid: in.dii_pid,
`endif
ppc: in.ppc,
main_epoch: in.main_epoch,
dpTrain: dp_train,
@@ -1047,9 +1132,6 @@ module mkFetchStage(FetchStage);
regs: decode_result.regs,
cause: cause,
tval: decodeIn.tval
`ifdef RVFI_DII
, diid: fromMaybe(?,ids[i])
`endif
};
out_fifo.enqS[i].enq(out);
if (verbosity >= 1) begin
@@ -1076,10 +1158,13 @@ module mkFetchStage(FetchStage);
// update PC and epoch
if(redirectPc matches tagged Valid .nextPc) begin
pc_reg[pc_decode_port] <= nextPc;
`ifdef RVFI_DII
dii_id_next[pc_decode_port] <= nextId;
`endif
end
`ifdef RVFI_DII
doAssert(isValid(redirectPc) == isValid(redirectDiiPid), "PC and DII redirections always happen together");
if(redirectDiiPid matches tagged Valid .nextDiiPid) begin
dii_pid_reg[pc_decode_port] <= nextDiiPid;
end
`endif
decode_epoch[0] <= decode_epoch_local;
// send training data for next addr pred
if (trainNAP matches tagged Valid .x) begin
@@ -1132,16 +1217,19 @@ module mkFetchStage(FetchStage);
interface iTlbIfc = iTlb;
interface iMemIfc = iMem;
interface mmioIfc = mmio.toCore;
`ifdef RVFI_DII
interface diiIfc = dii.toCore;
`endif
method Action start(
CapMem start_pc
`ifdef RVFI_DII
, Dii_Id id
, Dii_Parcel_Id dii_pid
`endif
);
pc_reg[0] <= start_pc;
`ifdef RVFI_DII
dii_id_next[0] <= id;
dii_pid_reg[0] <= dii_pid;
`endif
started <= True;
waitForRedirect <= False;
@@ -1158,14 +1246,14 @@ module mkFetchStage(FetchStage);
method Action redirect(
CapMem new_pc
`ifdef RVFI_DII
, Dii_Id id
, 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);
pc_reg[pc_redirect_port] <= new_pc;
`ifdef RVFI_DII
dii_id_next[pc_redirect_port] <= id;
if (verbose) $display("%t Redirect: dii_id_next %d", $time(), id);
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;
ehr_pending_straddle[1] <= tagged Invalid;
@@ -1273,16 +1361,6 @@ module mkFetchStage(FetchStage);
`endif
endinterface
`ifdef RVFI_DII
interface Client dii;
interface Get request = toGet(dii_instIds);
interface Put response = toPut(dii_insts);
endinterface
method Action lastTraceId(Dii_Id in);
last_trace_id <= in;
endmethod
`endif
`ifdef DEBUG_WEDGE
method Tuple3#(Bit#(32), Addr, Addr) debugFetch;
Bit#(7) flags = {pack(out_fifo.deqS[1].canDeq), pack(out_fifo.deqS[0].canDeq), pack(f32d.notEmpty), pack(f22f3.notEmpty), pack(f12f2.notEmpty), pack(waitForFlush), pack(waitForRedirect)};

View File

@@ -374,7 +374,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
epochIncremented: True, // we have incremented epoch
spec_bits: specTagManager.currentSpecBits
`ifdef RVFI_DII
, diid: x.diid
, dii_pid: x.dii_pid
`endif
};
rob.enqPort[0].enq(y);
@@ -495,7 +495,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
// get ROB tag
let inst_tag = rob.enqPort[0].getEnqInstTag;
`ifdef RVFI_DII
inst_tag.diid = x.diid;
inst_tag.dii_next_pid = x.dii_pid + ((x.orig_inst[1:0] == 2'b11) ? 2 : 1);
`endif
// CSR inst will be sent to ALU exe pipeline
@@ -574,7 +574,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
epochIncremented: True, // system inst has incremented epoch
spec_bits: spec_bits
`ifdef RVFI_DII
, diid: x.diid
, dii_pid: x.dii_pid
`endif
};
rob.enqPort[0].enq(y);
@@ -670,7 +670,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
// get ROB tag
let inst_tag = rob.enqPort[0].getEnqInstTag;
`ifdef RVFI_DII
inst_tag.diid = x.diid;
inst_tag.dii_next_pid = x.dii_pid + ((x.orig_inst[1:0] == 2'b11) ? 2 : 1);
`endif
// LSQ tag
@@ -752,7 +752,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
epochIncremented: False,
spec_bits: spec_bits
`ifdef RVFI_DII
, diid: x.diid
, dii_pid: x.dii_pid
`endif
};
rob.enqPort[0].enq(y);
@@ -936,7 +936,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
// get ROB tag
let inst_tag = rob.enqPort[i].getEnqInstTag;
`ifdef RVFI_DII
inst_tag.diid = x.diid;
inst_tag.dii_next_pid = x.dii_pid + ((x.orig_inst[1:0] == 2'b11) ? 2 : 1);
`endif
// LSQ tag
@@ -1116,7 +1116,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
epochIncremented: False,
spec_bits: spec_bits
`ifdef RVFI_DII
, diid: x.diid
, dii_pid: x.dii_pid
`endif
};
rob.enqPort[i].enq(y);

View File

@@ -47,6 +47,7 @@ import CHERICap::*;
import CHERICC_Fat::*;
import ISA_Decls_CHERI::*;
`ifdef RVFI_DII
import GetPut::*;
import RVFI_DII_Types::*;
`endif
import ISA_Decls_CHERI::*;
@@ -80,10 +81,22 @@ typedef struct {
SingleScalarPtr ptr; // pointer within a way
InstTime t; // inst time in ROB (for dispatch in reservation station)
`ifdef RVFI_DII
Dii_Id diid;
Dii_Parcel_Id dii_next_pid;
`endif
} InstTag deriving(Bits, Eq, FShow);
`ifdef RVFI_DII
typedef Vector#(SupSize, Maybe#(RVFI_DII_Execution #(64, 64))) Rvfi_Traces;
typedef Vector#(TMul#(SupSize, 2), RVFI_DII_Parcel_Resp) Dii_Parcel_Resps;
typedef Vector#(TMul#(SupSize, 2), Bit#(16)) Dii_Parcels;
interface Toooba_RVFI_DII_Server;
interface Get#(Dii_Parcel_Id) seqReqFirst;
interface Put#(Dii_Parcel_Resps) parcelResps;
interface Get#(Rvfi_Traces) trace_report;
endinterface
`endif
typedef `SB_SIZE SBSize;
typedef Bit#(TLog#(SBSize)) SBIndex;

View File

@@ -112,7 +112,7 @@ typedef struct {
// speculation
SpecBits spec_bits;
`ifdef RVFI_DII
Dii_Id diid;
Dii_Parcel_Id dii_pid;
`endif
`ifdef RVFI
ExtraTraceBundle traceBundle;
@@ -277,7 +277,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
Reg#(Bool) epochIncremented <- mkRegU;
Ehr#(3, SpecBits) spec_bits <- mkEhr(?);
`ifdef RVFI_DII
Reg#(Dii_Id) diid <- mkRegU;
Reg#(Dii_Parcel_Id) dii_pid <- mkRegU;
`endif
`ifdef RVFI
Ehr#(TAdd#(2, TAdd#(fpuMulDivExeNum, aluExeNum)), ExtraTraceBundle) traceBundle <- mkEhr(?);
@@ -437,7 +437,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
lsqAtCommitNotified[lsqNotified_enq_port] <= False;
nonMMIOStDone[nonMMIOSt_enq_port] <= False;
`ifdef RVFI_DII
diid <= x.diid;
dii_pid <= x.dii_pid;
`endif
`ifdef RVFI
//$display("%t : traceBundle = ", $time(), fshow(x.traceBundle), " in write_enq for %x", pc);
@@ -476,7 +476,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
nonMMIOStDone: nonMMIOStDone[nonMMIOSt_deq_port],
epochIncremented: epochIncremented,
`ifdef RVFI_DII
diid: diid,
dii_pid: dii_pid,
`endif
`ifdef RVFI
traceBundle: case (ppc_vaddr_csrData[pvc_deq_port]) matches

View File

@@ -177,20 +177,3 @@ function Action doAssert(Bool b, String s) = action if(!b) $fdisplay(stderr, "\n
`else
function Action doAssert(Bool b, String s) = dynamicAssert(b, s);
`endif
`ifdef RVFI_DII
typedef Vector#(`sizeSup, Maybe#(RVFI_DII_Execution #(64, 64))) Rvfi_Traces;
typedef Vector#(`sizeSup, Maybe#(Dii_Id)) Dii_Ids;
typedef Vector#(`sizeSup, Maybe#(Bit#(32))) Dii_Insts;
typedef struct {
Dii_Insts insts;
Dii_Ids ids;
} InstsAndIDs deriving(Bits, Eq, FShow);
interface Toooba_RVFI_DII_Server;
interface Get#(Dii_Ids) seqReq;
interface Put#(InstsAndIDs) inst;
interface Get#(Rvfi_Traces) trace_report;
endinterface
`endif

View File

@@ -79,7 +79,7 @@ import TV_Info :: *;
`ifdef RVFI_DII
import RVFI_DII_Types :: *;
import Types :: *;
import ProcTypes :: *;
`endif
`ifdef INCLUDE_GDB_CONTROL

View File

@@ -70,8 +70,9 @@ import Debug_Module :: *;
`endif
`ifdef RVFI_DII
import RVFI_DII :: *;
import Types :: *;
import RVFI_DII :: *;
import Types :: *;
import ProcTypes :: *;
`endif
// ================================================================
@@ -458,14 +459,14 @@ module mkTop_HW_Side(Empty)
rg_banner_printed <= True;
endrule
RVFI_DII_Bridge #(DataSz, DataSz, `sizeSup) bridge <- mkRVFI_DII_Bridge("", 5001);
RVFI_DII_Bridge #(DataSz, DataSz, TMul#(SupSize, 2), SupSize) bridge <- mkRVFI_DII_Bridge("", 5001);
let dut <- mkPre_Top_HW_Side(reset_by bridge.new_rst);
mkConnection(bridge.client.report, dut.trace_report);
rule rl_provide_instr;
Dii_Ids reqs <- dut.seqReq.get;
Dii_Insts insts <- bridge.client.getInst(reqs);
dut.inst.put(InstsAndIDs{insts: insts, ids: reqs});
Dii_Parcel_Id req <- dut.seqReqFirst.get;
Dii_Parcel_Resps resps <- bridge.client.getParcels(req);
dut.parcelResps.put(resps);
endrule
endmodule

View File

@@ -46,7 +46,7 @@ import ConfigReg :: *;
`include "ProcConfig.bsv"
import Types::*;
import ProcTypes::*;
import ProcTypes::*;
//import Verifier :: *;
import RVFI_DII :: *;
@@ -55,19 +55,17 @@ import RVFI_DII :: *;
interface Toooba_RVFI_DII_Bridge_IFC;
interface Toooba_RVFI_DII_Server rvfi_dii_server;
interface Server#(Dii_Ids, InstsAndIDs) dii;
interface Server#(Dii_Parcel_Id, Dii_Parcels) dii;
interface Put#(Rvfi_Traces) rvfi;
method Dii_Id lastId;
endinterface
module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC);
// DII state
FIFOF#(InstsAndIDs) instrs <- mkSizedFIFOF(2048);
FIFOF#(Dii_Parcel_Resps) parcel_resps <- mkSizedFIFOF(2048);
// RVFI state
FIFO#(Rvfi_Traces) report_vectors <- mkSizedFIFO(2048);
// Request ID
FIFO#(Dii_Ids) seq_req <- mkFIFO;
Reg#(Dii_Id) last_id <- mkReg(0);
FIFO#(Dii_Parcel_Id) seq_req_first <- mkFIFO;
Bool verbose = False;
@@ -78,8 +76,11 @@ module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC);
// These two functions convert beteween "Invalid" instructions and "nops".
// This is because the pipeline currently isn't able to handle Invalid injections,
// so we replace them with special nops in the bridge that we can filter out in the rvfi trace stream.
function Maybe#(Bit#(32)) maybeToNop(Maybe#(Bit#(32)) in);
return tagged Valid fromMaybe(dii_nop, in);
function Bit#(16) noParcelToNop(RVFI_DII_Parcel_Resp in);
case (in) matches
tagged DIIParcel .parcel: return parcel;
tagged DIINoParcel .is_second: return is_second ? dii_nop[31:16] : dii_nop[15:0];
endcase
endfunction
function Maybe#(RVFI_DII_Execution #(DataSz,DataSz)) nopToMaybe(Maybe#(RVFI_DII_Execution #(DataSz,DataSz)) in);
@@ -89,42 +90,32 @@ module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC);
endfunction
interface Toooba_RVFI_DII_Server rvfi_dii_server;
interface Get seqReq = toGet(seq_req);
interface Put inst = toPut(instrs);
interface Get seqReqFirst = toGet(seq_req_first);
interface Put parcelResps = toPut(parcel_resps);
interface Get trace_report = toGet(report_vectors);
endinterface
interface Server dii;
interface Put request = toPut(seq_req);
interface Put request = toPut(seq_req_first);
interface Get response;
method ActionValue#(InstsAndIDs) get;
InstsAndIDs insts = instrs.first();
insts.insts = map(maybeToNop, insts.insts);
instrs.deq();
method ActionValue#(Dii_Parcels) get;
let resps = parcel_resps.first;
parcel_resps.deq;
let parcels = map(noParcelToNop, resps);
if (verbose)
$display("%t DII injection: ", $time,
fshow(insts)
fshow(parcels)
);
return insts;
return parcels;
endmethod
endinterface
endinterface
interface Put rvfi;
method Action put(Rvfi_Traces in);
Rvfi_Traces out = map(nopToMaybe,in);
report_vectors.enq(out);
Dii_Id next_id = last_id;
for (Integer i = 0; i < `sizeSup; i = i + 1) begin
if (out[i] matches tagged Valid .rpt) begin
Dii_Id this_id = unpack(truncate(rpt.rvfi_order));
if (this_id > next_id) next_id = this_id;
end
end
last_id <= next_id;
report_vectors.enq(map(nopToMaybe,in));
endmethod
endinterface
method Dii_Id lastId = last_id;
endmodule
endpackage