Merge branch 'master' into RVFI_DII, a complex merge for the fetch stage!

This commit is contained in:
Jonathan Woodruff
2020-03-18 11:35:59 +00:00
1059 changed files with 1467937 additions and 324026 deletions

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
// Portions Copyright (c) 2019-2020 Bluespec, Inc.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -21,8 +22,6 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Portions Copyright (c) Bluespec, Inc.
`include "ProcConfig.bsv"
import Vector::*;
@@ -88,6 +87,29 @@ import Toooba_RVFI_DII_Bridge::*;
import CsrFile :: *;
// ================================================================
// Toooba
import Cur_Cycle :: *;
import FIFOF :: *;
import GetPut_Aux :: *;
`ifdef INCLUDE_GDB_CONTROL
import DM_CPU_Req_Rsp :: *;
`endif
`ifdef INCLUDE_TANDEM_VERIF
import Trace_Data2 :: *;
`endif
// ================================================================
`ifdef SECURITY
`define SECURITY_OR_INCLUDE_GDB_CONTROL
`elsif INCLUDE_GDB_CONTROL
`define SECURITY_OR_INCLUDE_GDB_CONTROL
`endif
interface CoreReq;
method Action start(
Addr startpc,
@@ -139,13 +161,28 @@ interface Core;
// Bluespec: external interrupt requests targeting Machine and Supervisor modes
method Action setMEIP (Bit #(1) v);
method Action setSEIP (Bit #(1) v);
// Bluespec: external interrupt to enter debug mode
method Action setDEIP (Bit #(1) v);
`ifdef RVFI_DII
interface Toooba_RVFI_DII_Server rvfi_dii_server;
`endif
`ifdef INCLUDE_GDB_CONTROL
interface Server #(Bool, Bool) hart0_run_halt_server;
interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_gpr_mem_server;
`ifdef ISA_F
interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_fpr_mem_server;
`endif
interface Server #(DM_CPU_Req #(12, 64), DM_CPU_Rsp #(64)) hart0_csr_mem_server;
`endif
`ifdef INCLUDE_TANDEM_VERIF
// Note: this is a SupSize vector of streams of Trace_Data2 structs,
// each of which has a serialnum field. Each of the SupSize
// streams has serialnums in increasing order. Each serialnum
// appears exactly once in exactly one of the streams. Thus, the
// channels can easily be merged into a single program-order stream.
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
`endif
endinterface
// fixpoint to instantiate modules
@@ -157,9 +194,22 @@ interface CoreFixPoint;
interface Reg#(Bool) doStatsIfc;
endinterface
typedef enum {
`ifdef INCLUDE_GDB_CONTROL
CORE_HALTING,
CORE_HALTED,
`endif
CORE_RUNNING
} Core_Run_State
deriving (Bits, Eq, FShow);
(* synthesize *)
module mkCore#(CoreId coreId)(Core);
let verbose = False;
// ================================================================
Integer verbosity = 0; // More levels of verbosity control than 'Bool verbose'
Reg#(Bool) outOfReset <- mkReg(False);
rule rl_outOfReset if (!outOfReset);
$fwrite(stderr, "mkProc came out of reset\n");
@@ -168,6 +218,19 @@ module mkCore#(CoreId coreId)(Core);
Reg#(Bool) started <- mkReg(False);
// ================================================================
`ifdef INCLUDE_GDB_CONTROL
// Using a ConfigReg since scheduling of reads/writes not critical (TODO: verify this)
Reg #(Core_Run_State) rg_core_run_state <- mkConfigReg (CORE_RUNNING);
`endif
`ifdef INCLUDE_TANDEM_VERIF
Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF);
`endif
// ================================================================
// front end
FetchStage fetchStage <- mkFetchStage;
ITlb iTlb = fetchStage.iTlbIfc;
@@ -244,18 +307,6 @@ module mkCore#(CoreId coreId)(Core);
// whether perf data is collected
Reg#(Bool) doStatsReg <- mkConfigReg(False);
// redirect func
//function Action redirectFunc(Addr trap_pc, Maybe#(SpecTag) spec_tag, InstTag inst_tag );
//action
// if (verbose) $fdisplay(stdout, "[redirect_action] new pc = 0x%8x, spec_tag = ", trap_pc, fshow(spec_tag));
// epochManager.redirect;
// fetchStage.redirect(trap_pc);
// if (spec_tag matches tagged Valid .valid_spec_tag) begin
// globalSpecUpdate.incorrectSpec(valid_spec_tag, inst_tag);
// end
//endaction
//endfunction
// write aggressive elements + wakupe reservation stations
function Action writeAggr(Integer wrAggrPort, PhyRIndx dst);
action
@@ -332,7 +383,7 @@ module mkCore#(CoreId coreId)(Core);
let train <- toGet(trainBPQ[i]).get;
fetchStage.train_predictors(
train.pc, train.nextPc, train.iType, train.taken,
train.dpTrain, train.mispred
train.dpTrain, train.mispred, train.isCompressed
);
endrule
end
@@ -363,6 +414,9 @@ module mkCore#(CoreId coreId)(Core);
method csrf_rd = csrf.rd;
method rob_getPC = rob.getOrigPC[valueof(AluExeNum)].get; // last getPC port
method rob_setExecuted_doFinishMem = rob.setExecuted_doFinishMem;
`ifdef INCLUDE_TANDEM_VERIF
method rob_setExecuted_doFinishMem_RegData = rob.setExecuted_doFinishMem_RegData;
`endif
method rob_setExecuted_deqLSQ = rob.setExecuted_deqLSQ;
method isMMIOAddr = mmio.isMMIOAddr;
method mmioReq = mmio.dataReq;
@@ -407,13 +461,15 @@ module mkCore#(CoreId coreId)(Core);
Reg#(Bool) flush_tlbs <- mkReg(False);
Reg#(Bool) update_vm_info <- mkReg(False);
Reg#(Bool) flush_reservation <- mkReg(False);
`ifdef SECURITY
`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL
Reg#(Bool) flush_caches <- mkReg(False);
Reg#(Bool) flush_brpred <- mkReg(False);
`else
Reg#(Bool) flush_caches <- mkReadOnlyReg(False);
Reg#(Bool) flush_brpred <- mkReadOnlyReg(False);
`endif
`ifdef SELF_INV_CACHE
Reg#(Bool) reconcile_i <- mkReg(False);
`else
@@ -500,6 +556,9 @@ module mkCore#(CoreId coreId)(Core);
`endif
endmethod
method doStats = coreFix.doStatsIfc._read;
`ifdef INCLUDE_GDB_CONTROL
method Bool core_is_running = (rg_core_run_state == CORE_RUNNING);
`endif
endinterface);
RenameStage renameStage <- mkRenameStage(renameInput);
@@ -512,16 +571,50 @@ module mkCore#(CoreId coreId)(Core);
method stqEmpty = lsq.stqEmpty;
method lsqSetAtCommit = lsq.setAtCommit;
method tlbNoPendingReq = iTlb.noPendingReq && dTlb.noPendingReq;
method setFlushTlbs = flush_tlbs._write(True);
method setUpdateVMInfo = update_vm_info._write(True);
method setFlushReservation = flush_reservation._write(True);
method setFlushBrPred = flush_brpred._write(True);
method setFlushCaches = flush_caches._write(True);
method setFlushTlbs;
action
flush_tlbs <= True;
// $display ("%0d: %m.commitInput.setFlushTlbs", cur_cycle);
endaction
endmethod
method setUpdateVMInfo;
action
update_vm_info <= True;
// $display ("%0d: %m.commitInput.setUpdateVMInfo", cur_cycle);
endaction
endmethod
method setFlushReservation;
action
flush_reservation <= True;
// $display ("%0d: %m.commitInput.setFlushReservation", cur_cycle);
endaction
endmethod
method setFlushBrPred;
action
flush_brpred <= True;
// $display ("%0d: %m.commitInput.setFlushBrPred", cur_cycle);
endaction
endmethod
method setFlushCaches;
action
flush_caches <= True;
// $display ("%0d: %m.commitInput.setFlushCaches", cur_cycle);
endaction
endmethod
method setReconcileI = reconcile_i._write(True);
method setReconcileD = reconcile_d._write(True);
method killAll = coreFix.killAll;
method redirectPc = fetchStage.redirect;
method setFetchWaitRedirect = fetchStage.setWaitRedirect;
`ifdef INCLUDE_GDB_CONTROL
method setFetchWaitFlush = fetchStage.setWaitFlush;
`endif
method incrementEpoch = epochManager.incrementEpoch;
method commitCsrInstOrInterrupt = csrInstOrInterruptInflight_commit._write(False);
method doStats = coreFix.doStatsIfc._read;
@@ -532,6 +625,11 @@ module mkCore#(CoreId coreId)(Core);
return False;
`endif
endmethod
`ifdef INCLUDE_TANDEM_VERIF
interface v_to_TV = map (toPut, v_f_to_TV);
`endif
endinterface);
CommitStage commitStage <- mkCommitStage(commitInput);
@@ -568,11 +666,13 @@ module mkCore#(CoreId coreId)(Core);
if (flush_reservation) begin
flush_reservation <= False;
dMem.resetLinkAddr;
// $display ("%0d: %m.rule prepareCachesAndTlbs: flushing reservation", cur_cycle);
end
if (flush_tlbs) begin
flush_tlbs <= False;
iTlb.flush;
dTlb.flush;
// $display ("%0d: %m.rule prepareCachesAndTlbs: flushing iTlb and dTlb", cur_cycle);
end
if (update_vm_info) begin
update_vm_info <= False;
@@ -581,10 +681,11 @@ module mkCore#(CoreId coreId)(Core);
iTlb.updateVMInfo(vmI);
dTlb.updateVMInfo(vmD);
l2Tlb.updateVMInfo(vmI, vmD);
// $display ("%0d: %m.rule prepareCachesAndTlbs: updating VMInfo", cur_cycle);
end
endrule
`ifdef SECURITY
`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL
// Use wires to capture flush regs and empty signals. This is ok because
// there cannot be any activity to make empty -> not-empty or need-flush ->
// no-need-flush when we are trying to flush.
@@ -593,6 +694,7 @@ module mkCore#(CoreId coreId)(Core);
rule setDoFlushCaches(flush_caches && fetchStage.emptyForFlush && lsq.noWrongPathLoads);
doFlushCaches.send;
// $display ("%0d: %m.rl_setDoFlushCaches", cur_cycle);
endrule
rule setDoFlushBrPred(flush_brpred && fetchStage.emptyForFlush);
@@ -605,6 +707,7 @@ module mkCore#(CoreId coreId)(Core);
flush_caches <= False;
iMem.flush;
dMem.flush;
// $display ("%0d: %m.rule flushCaches (imem and dmem)", cur_cycle);
endrule
// security flush branch predictors: wait for wrong path inst fetches to
@@ -612,6 +715,7 @@ module mkCore#(CoreId coreId)(Core);
rule flushBrPred(doFlushBrPred);
flush_brpred <= False;
fetchStage.flush_predictors;
// $display ("%0d: %m.rule flushBrPred", cur_cycle);
endrule
`endif
@@ -656,9 +760,12 @@ module mkCore#(CoreId coreId)(Core);
`endif // SELF_INV_CACHE
rule readyToFetch(
`ifdef INCLUDE_GDB_CONTROL
(rg_core_run_state == CORE_RUNNING) &&
`endif
!flush_reservation && !flush_tlbs && !update_vm_info
&& iTlb.flush_done && dTlb.flush_done
`ifdef SECURITY
`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL
&& !flush_caches && !flush_brpred
&& iMem.flush_done && dMem.flush_done
&& fetchStage.flush_predictors_done
@@ -671,6 +778,15 @@ module mkCore#(CoreId coreId)(Core);
`endif
);
fetchStage.done_flushing();
`ifdef INCLUDE_GDB_CONTROL
if (commitStage.is_debug_halted) begin
started <= False;
rg_core_run_state <= CORE_HALTING;
if (verbosity >= 1)
$display ("%0d: %m.rule readyToFetch: halting for debug mode", cur_cycle);
end
`endif
endrule
`ifdef PERF_COUNT
@@ -930,6 +1046,280 @@ module mkCore#(CoreId coreId)(Core);
endrule
`endif
`ifdef INCLUDE_GDB_CONTROL
// ================================================================
// DEBUG MODULE INTERFACE
Bool show_DM_interactions = False; // for debugging the interactions
// ----------------------------------------------------------------
// Debug Module GPR read/write
FIFOF #(DM_CPU_Req #(5, 64)) f_gpr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(64)) f_gpr_rsps <- mkFIFOF1;
rule rl_debug_gpr_read ( (rg_core_run_state == CORE_HALTED)
&& f_gpr_reqs.notEmpty
&& (! f_gpr_reqs.first.write));
let req <- pop (f_gpr_reqs);
Bit #(5) regnum = req.address;
let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr regnum),
src2: tagged Invalid,
src3: tagged Invalid,
dst: tagged Invalid};
let rename_result = regRenamingTable.rename[0].getRename (arch_regs);
let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1);
let data_out = rf.read [debuggerPort].rd1 (phy_rindx);
let rsp = DM_CPU_Rsp {ok: True, data: data_out};
f_gpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out);
endrule
rule rl_debug_gpr_write ( (rg_core_run_state == CORE_HALTED)
&& f_gpr_reqs.notEmpty
&& f_gpr_reqs.first.write);
let req <- pop (f_gpr_reqs);
Bit #(5) regnum = req.address;
let data_in = req.data;
let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr regnum),
src2: tagged Invalid,
src3: tagged Invalid,
dst: tagged Invalid};
let rename_result = regRenamingTable.rename[0].getRename (arch_regs);
let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1);
rf.write [debuggerPort].wr (phy_rindx, data_in);
let rsp = DM_CPU_Rsp {ok: True, data: ?};
f_gpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_gpr_write: reg %0d <= 0x%0h (phy_rindx = %0d)",
cur_cycle, regnum, data_in, phy_rindx);
endrule
rule rl_debug_gpr_access_busy (rg_core_run_state == CORE_RUNNING);
let req <- pop (f_gpr_reqs);
let rsp = DM_CPU_Rsp {ok: False, data: ?};
f_gpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_gpr_access_busy", cur_cycle);
endrule
`ifdef ISA_F
// ----------------------------------------------------------------
// Debug Module FPR read/write
FIFOF #(DM_CPU_Req #(5, 64)) f_fpr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(64)) f_fpr_rsps <- mkFIFOF1;
rule rl_debug_fpr_read ( (rg_core_run_state == CORE_HALTED)
&& (! f_gpr_reqs.notEmpty) // prioritize gpr reqs
&& (! f_fpr_reqs.first.write));
let req <- pop (f_fpr_reqs);
Bit #(5) regnum = req.address;
let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu regnum),
src2: tagged Invalid,
src3: tagged Invalid,
dst: tagged Invalid};
let rename_result = regRenamingTable.rename[0].getRename (arch_regs);
let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1);
let data_out = rf.read [debuggerPort].rd1 (phy_rindx);
let rsp = DM_CPU_Rsp {ok: True, data: data_out};
f_fpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out);
endrule
rule rl_debug_fpr_write ( (rg_core_run_state == CORE_HALTED)
&& (! f_gpr_reqs.notEmpty) // prioritize gpr reqs
&& f_fpr_reqs.first.write);
let req <- pop (f_fpr_reqs);
Bit #(5) regnum = req.address;
let data_in = req.data;
let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu regnum),
src2: tagged Invalid,
src3: tagged Invalid,
dst: tagged Invalid};
let rename_result = regRenamingTable.rename[0].getRename (arch_regs);
let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1);
rf.write [debuggerPort].wr (phy_rindx, data_in);
let rsp = DM_CPU_Rsp {ok: True, data: ?};
f_fpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h (phy_rindx %0d)",
cur_cycle, regnum, data_in, phy_rindx);
endrule
rule rl_debug_fpr_access_busy ( (rg_core_run_state == CORE_RUNNING)
&& f_fpr_reqs.notEmpty);
let req <- pop (f_fpr_reqs);
let rsp = DM_CPU_Rsp {ok: False, data: ?};
f_fpr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_fpr_access_busy", cur_cycle);
endrule
`endif
// ----------------------------------------------------------------
// Debug Module CSR read/write
// Debugger CSR read/write request/response
FIFOF #(DM_CPU_Req #(12, 64)) f_csr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(64)) f_csr_rsps <- mkFIFOF1;
rule rl_debug_csr_read ( (rg_core_run_state == CORE_HALTED)
&& (! f_csr_reqs.first.write));
let req <- pop (f_csr_reqs);
Bit #(12) csr_addr = req.address;
let data_out = csrf.rd (unpack (csr_addr));
let rsp = DM_CPU_Rsp {ok: True, data: data_out};
f_csr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_read_csr: csr [%0h] => 0x%0h", cur_cycle, csr_addr, data_out);
endrule
rule rl_debug_csr_write ( (rg_core_run_state == CORE_HALTED)
&& f_csr_reqs.first.write);
let req <- pop (f_csr_reqs);
Bit #(12) csr_addr = req.address;
let data_in = req.data;
csrf.csrInstWr (unpack (csr_addr), data_in);
let rsp = DM_CPU_Rsp {ok: True, data: ?};
f_csr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_write_csr: csr [%0h] <= 0x%0h", cur_cycle, csr_addr, data_in);
endrule
rule rl_debug_csr_access_busy (rg_core_run_state == CORE_RUNNING);
let req <- pop (f_csr_reqs);
let rsp = DM_CPU_Rsp {ok: False, data: ?};
f_csr_rsps.enq (rsp);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_csr_access_busy", cur_cycle);
endrule
// ----------------------------------------------------------------
// Debug Module run-halt control
FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF;
FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF;
// ----------------
// Debug Module Halt control
rule rl_debug_halt_req ( (rg_core_run_state == CORE_RUNNING)
&& (f_run_halt_reqs.first == False));
f_run_halt_reqs.deq;
// Debugger 'halt' request (e.g., GDB '^C' command)
// This is initiated just like an interrupt.
renameStage.debug_halt_req;
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_halt_req", cur_cycle);
endrule
rule rl_debug_halt_req_already_halted ( (rg_core_run_state != CORE_RUNNING)
&& (f_run_halt_reqs.first == False));
f_run_halt_reqs.deq;
// Notify debugger that we're halted, but otherwise ignore the request
f_run_halt_rsps.enq (False);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_halt_req_already_halted", cur_cycle);
endrule
// Monitors when we've reached halted state while running
// (due to halt, step or EBREAK) and notifies DM
rule rl_debug_halted (rg_core_run_state == CORE_HALTING);
// Notify debugger that we've halted
f_run_halt_rsps.enq (False);
rg_core_run_state <= CORE_HALTED;
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_halted", cur_cycle);
endrule
// ----------------
// Debug Module Resume (run) control
// Resume command when in debug mode
rule rl_debug_resume ( (rg_core_run_state == CORE_HALTED)
&& (f_run_halt_reqs.first == True)
// prioritise gpr/fpr/csr read/write requests before resuming
&& (! f_gpr_reqs.notEmpty)
`ifdef ISA_F
&& (! f_fpr_reqs.notEmpty)
`endif
&& (! f_csr_reqs.notEmpty));
f_run_halt_reqs.deq;
// In Debug Mode, debugger may have updated DCSR (hence privilege level, DCSR[1:0]),
// and also other VM-related state.
// The following TLB actions update to a consistent state.
iTlb.flush;
dTlb.flush;
let vmI = csrf.vmI;
let vmD = csrf.vmD;
iTlb.updateVMInfo(vmI);
dTlb.updateVMInfo(vmD);
l2Tlb.updateVMInfo(vmI, vmD);
let startpc = csrf.dpc_read;
fetchStage.redirect (startpc);
renameStage.debug_resume;
commitStage.debug_resume;
started <= True;
rg_core_run_state <= CORE_RUNNING;
// Notify debugger that we've started running
f_run_halt_rsps.enq (True);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_resume, dpc = 0x%0h", cur_cycle, startpc);
endrule
// Run command when already running
rule rl_debug_run_redundant ( (rg_core_run_state == CORE_RUNNING)
&& (f_run_halt_reqs.first == True));
f_run_halt_reqs.deq;
// Notify debugger that we're running
f_run_halt_rsps.enq (True);
if (show_DM_interactions)
$display ("%0d: %m.rl_debug_run_redundant", cur_cycle);
endrule
// ================================================================
`endif
// ================================================================
// INTERFACE
interface CoreReq coreReq;
method Action start(
Bit#(64) startpc,
@@ -941,8 +1331,11 @@ module mkCore#(CoreId coreId)(Core);
`endif
);
started <= True;
`ifdef INCLUDE_GDB_CONTROL
rg_core_run_state <= CORE_RUNNING;
`endif
mmio.setHtifAddrs(toHostAddr, fromHostAddr);
// start rename debug
commitStage.startRenameDebug;
endmethod
@@ -1013,7 +1406,17 @@ module mkCore#(CoreId coreId)(Core);
method Action setMEIP (v) = csrf.setMEIP (v);
method Action setSEIP (v) = csrf.setSEIP (v);
// Bluespec: external interrupt to enter debug mode
method Action setDEIP (v) = csrf.setDEIP (v);
endmodule
`ifdef INCLUDE_GDB_CONTROL
interface Server hart0_run_halt_server = toGPServer (f_run_halt_reqs, f_run_halt_rsps);
interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps);
`ifdef ISA_F
interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps);
`endif
interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps);
`endif
`ifdef INCLUDE_TANDEM_VERIF
interface v_to_TV = map (toGet, v_f_to_TV);
`endif
endmodule

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
// Portions Copyright (c) 2019-2020 Bluespec, Inc.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -21,8 +22,6 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Portions Copyright (c) Bluespec, Inc.
`include "ProcConfig.bsv"
import Types::*;
import ProcTypes::*;
@@ -37,6 +36,46 @@ import GetPut::*;
import BuildVector::*;
//import TRNG::*;
// ================================================================
// BSV additional libs
import Cur_Cycle :: *;
// ================================================================
// Project imports from Toooba
import SoC_Map :: *;
// ================================================================
// Information returned on traps and mret/sret/uret
typedef struct {
Addr new_pc;
`ifdef INCLUDE_TANDEM_VERIF
// The fields below are for tandem verification only
Bit #(2) prv;
Data status;
Data cause;
Data epc;
Data tval;
`endif
} Trap_Updates
deriving (Bits, FShow);
typedef struct {
Addr new_pc;
`ifdef INCLUDE_TANDEM_VERIF
// The fields below are for tandem verification only
Bit #(2) prv;
Data status;
`endif
} RET_Updates
deriving (Bits, FShow);
// ================================================================
interface CsrFile;
// Read
method Data rd(CSR csr);
@@ -45,12 +84,23 @@ interface CsrFile;
// normal write by FPU inst to FPU CSR
method Bool fpuInstNeedWr(Bit#(5) fflags, Bool fpu_dirty);
method Action fpuInstWr(Bit#(5) fflags); // FPU must become dirty
`ifdef INCLUDE_TANDEM_VERIF
// Returns new fcsr and mstatus (pure function)
method Tuple2 #(Bit #(5), Data) fpuInst_csr_updates (Bit #(5) fflags,
Bool init_for_way0,
Bit #(5) old_fflags,
Data old_mstatus);
method Data getMIP;
`endif
// The WARL transform performed during CSRRx writes to a CSR
method Data warl_xform (CSR csr, Data x);
// Methods for handling traps
method Maybe#(Interrupt) pending_interrupt;
method ActionValue#(Addr) trap(Trap t, Addr pc, Addr faultAddr);
method ActionValue#(Addr) sret;
method ActionValue#(Addr) mret;
method ActionValue#(Trap_Updates) trap(Trap t, Addr pc, Addr faultAddr, Bit #(32) orig_inst);
method ActionValue#(RET_Updates) sret;
method ActionValue#(RET_Updates) mret;
// Outputs for CSRs that the rest of the processor needs to know about
method VMInfo vmI;
@@ -79,9 +129,6 @@ interface CsrFile;
method Action setMEIP (Bit #(1) v);
method Action setSEIP (Bit #(1) v);
// Bluespec: external interrupt to enter debug mode
method Action setDEIP (Bit #(1) v);
// performance stats is collected or not
method Bool doPerfStats;
// send/recv updates on stats CSR globally
@@ -90,6 +137,26 @@ interface CsrFile;
// terminate
method ActionValue#(void) terminate;
`ifdef INCLUDE_GDB_CONTROL
// Read dpc
method Addr dpc_read ();
// Update dpc
method Action dpc_write (Addr pc);
// Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku}
method Bit #(1) dcsr_break_bit;
// Read dcsr[2], the step bit
method Bit #(1) dcsr_step_bit;
// Update 'cause' in DCSR
// Is invoked by logic that stops a hart, to enter Debug Mode
(* always_ready *)
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
`endif
endinterface
// Fancy Reg functions
@@ -244,10 +311,13 @@ module mkCsrFile #(Data hartid)(CsrFile);
// Machine level CSRs
// mstatus
Reg#(Bit#(2)) xs_reg <- mkReadOnlyReg(0); // XXX no extension
Reg#(Bit#(2)) fs_reg <- (isa.f || isa.d) ? mkCsrReg(0) : mkReadOnlyReg(0);
Reg#(Bit#(2)) fs_reg <- (isa.f || isa.d) ? mkCsrReg(2'b01) : mkReadOnlyReg(0);
Reg#(Bit#(1)) sd_reg = readOnlyReg(
((xs_reg == 2'b11) || (fs_reg == 2'b11)) ? 1 : 0
);
function Bit #(1) fn_sd_val (Bit #(2) xs_val, Bit #(2) fs_val);
return (((xs_val == 2'b11) || (fs_val == 2'b11)) ? 1 : 0);
endfunction
Reg#(Bit#(2)) sxl_reg = readOnlyReg(getXLBits);
Reg#(Bit#(2)) uxl_reg = readOnlyReg(getXLBits);
Reg#(Bit#(1)) tsr_reg <- mkCsrReg(0);
@@ -286,6 +356,25 @@ module mkCsrFile #(Data hartid)(CsrFile);
ie_vec[prvM], readOnlyReg(1'b0),
ie_vec[prvS], ie_vec[prvU]
);
function Data fn_mstatus_val (Bit #(2) sxl_val, Bit #(2) uxl_val,
Bit #(1) tsr_val, Bit #(1) tw_val, Bit #(1) tvm_val,
Bit #(1) mxr_val, Bit #(1) sum_val, Bit #(1) mprv_val,
Bit #(2) xs_val, Bit #(2) fs_val,
Bit #(2) mpp_val, Bit #(1) spp_val,
Bit #(1) prev_ie_vec_prvM_val,
Bit #(1) prev_ie_vec_prvS_val, Bit #(1) prev_ie_vec_prvU_val,
Bit #(1) ie_vec_prvM_val,
Bit #(1) ie_vec_prvS_val, Bit #(1) ie_vec_prvU_val);
return {fn_sd_val (xs_val, fs_val),
27'b0, sxl_val, uxl_val, 9'b0,
tsr_val, tw_val, tvm_val, mxr_val, sum_val, mprv_val, xs_val, fs_val,
mpp_val, 2'b0, spp_val,
prev_ie_vec_prvM_val, 1'b0,
prev_ie_vec_prvS_val, prev_ie_vec_prvU_val,
ie_vec_prvM_val, 1'b0,
ie_vec_prvS_val, ie_vec_prvU_val};
endfunction
// misa
Reg#(Data) misa_csr = readOnlyReg({getXLBits, 36'b0, getExtensionBits(isa)});
// medeleg: some exceptions don't exist, fix corresponding bits to 0
@@ -309,7 +398,6 @@ module mkCsrFile #(Data hartid)(CsrFile);
readOnlyReg(1'b0), mideleg_1_0_reg
);
// mie
Reg #(Bit #(1)) debug_int_en = readOnlyReg (1);
Vector#(4, Reg#(Bit#(1))) external_int_en_vec = replicate(readOnlyReg(0));
external_int_en_vec[prvU] <- mkCsrReg(0);
external_int_en_vec[prvS] <- mkCsrReg(0);
@@ -322,16 +410,14 @@ module mkCsrFile #(Data hartid)(CsrFile);
software_int_en_vec[prvU] <- mkCsrReg(0);
software_int_en_vec[prvS] <- mkCsrReg(0);
software_int_en_vec[prvM] <- mkCsrReg(0);
Reg#(Data) mie_csr = concatReg15(
readOnlyReg(49'b0),
debug_int_en, // mie [14]
readOnlyReg(2'b0),
Reg#(Data) mie_csr = concatReg13(
readOnlyReg(52'b0),
external_int_en_vec[prvM], readOnlyReg(1'b0),
external_int_en_vec[prvS], external_int_en_vec[prvU],
external_int_en_vec[prvS], readOnlyReg(1'b0), // only if misa.N: external_int_en_vec[prvU],
timer_int_en_vec[prvM], readOnlyReg(1'b0),
timer_int_en_vec[prvS], timer_int_en_vec[prvU],
timer_int_en_vec[prvS], readOnlyReg(1'b0), // only if misa.N: timer_int_en_vec[prvU],
software_int_en_vec[prvM], readOnlyReg(1'b0),
software_int_en_vec[prvS], software_int_en_vec[prvU]
software_int_en_vec[prvS], readOnlyReg(1'b0) // only if misa.N: software_int_en_vec[prvU]
);
// mtvec
Reg#(Bit#(62)) mtvec_base_hi_reg <- mkCsrReg(0); // this is BASE[63:2]
@@ -359,34 +445,48 @@ module mkCsrFile #(Data hartid)(CsrFile);
Reg#(Data) mcause_csr = concatReg3(
mcause_interrupt_reg, readOnlyReg(59'b0), mcause_code_reg
);
function Data fn_mcause_val (Bit #(1) mcause_interrupt_val, Bit #(4) mcause_code_val);
return { mcause_interrupt_val, 59'b0, mcause_code_val };
endfunction
// mtval (mbadaddr in spike)
Reg#(Data) mtval_csr <- mkCsrReg(0);
// mip
Reg #(Bit #(1)) debug_int_pend <- mkCsrReg (0);
Vector#(4, Reg#(Bit#(1))) external_int_pend_vec = replicate(readOnlyReg(0));
external_int_pend_vec[prvU] <- mkCsrReg(0);
external_int_pend_vec[prvS] <- mkCsrReg(0);
external_int_pend_vec[prvM] <- mkCsrReg(0);
external_int_pend_vec[prvM] <- mkCsrReg(0); // TODO: bug (writeable by CSRRx)?
Vector#(4, Reg#(Bit#(1))) timer_int_pend_vec = replicate(readOnlyReg(0));
timer_int_pend_vec[prvU] <- mkCsrReg(0);
timer_int_pend_vec[prvS] <- mkCsrReg(0);
timer_int_pend_vec[prvM] <- mkCsrReg(0);
timer_int_pend_vec[prvM] <- mkCsrReg(0); // TODO: bug (writeable by CSRRx)?
Vector#(4, Reg#(Bit#(1))) software_int_pend_vec = replicate(readOnlyReg(0));
software_int_pend_vec[prvU] <- mkCsrReg(0);
software_int_pend_vec[prvS] <- mkCsrReg(0);
software_int_pend_vec[prvM] <- mkCsrReg(0);
Reg#(Data) mip_csr = concatReg15(
readOnlyReg(49'b0),
debug_int_pend,
readOnlyReg(2'b0),
external_int_pend_vec[prvM], readOnlyReg(1'b0),
external_int_pend_vec[prvS], external_int_pend_vec[prvU],
readOnlyReg(timer_int_pend_vec[prvM]), // MTIP is read-only to software
software_int_pend_vec[prvM] <- mkCsrReg(0); // TODO: bug (writeable by CSRRx)?
Reg#(Data) mip_csr = concatReg13(
readOnlyReg(52'b0),
// External interrupts
readOnlyReg(external_int_pend_vec[prvM]), // MEIP is read-only to software
readOnlyReg(1'b0),
timer_int_pend_vec[prvS], timer_int_pend_vec[prvU],
software_int_pend_vec[prvM], readOnlyReg(1'b0),
software_int_pend_vec[prvS], software_int_pend_vec[prvU]
external_int_pend_vec[prvS],
readOnlyReg(1'b0), // only if misa.N: external_int_pend_vec[prvU],
// Timer interrupts
readOnlyReg(timer_int_pend_vec[prvM]), // MTIP is read-only to software
readOnlyReg(1'b0),
timer_int_pend_vec[prvS],
readOnlyReg(1'b0), // only if misa.N: timer_int_pend_vec[prvU],
// Software interrupts
readOnlyReg(software_int_pend_vec[prvM]), // MSIP is read-only to software
readOnlyReg(1'b0),
software_int_pend_vec[prvS],
readOnlyReg(1'b0) // only if misa.N: software_int_pend_vec[prvU]
);
// MIP and MIE fields are WARL (Write Any Read Legal)
// We support M-privilege and S-privilege bits only;
// this mask allows only those bits through.
Data mip_mie_warl_mask = zeroExtend (12'h_222);
// minstret
Ehr#(2, Data) minstret_ehr <- mkCsrEhr(0);
Reg#(Data) minstret_csr = minstret_ehr[0];
@@ -411,14 +511,32 @@ module mkCsrFile #(Data hartid)(CsrFile);
readOnlyReg(2'b0), prev_ie_vec[prvS], prev_ie_vec[prvU],
readOnlyReg(2'b0), ie_vec[prvS], ie_vec[prvU]
);
function Data fn_sstatus_val (Bit #(2) uxl_val,
Bit #(1) mxr_val, Bit #(1) sum_val,
Bit #(2) xs_val, Bit #(2) fs_val,
Bit #(1) spp_val,
Bit #(1) prev_ie_vec_prvS_val,
Bit #(1) prev_ie_vec_prvU_val,
Bit #(1) ie_vec_prvS_val,
Bit #(1) ie_vec_prvU_val);
return {fn_sd_val (xs_val, fs_val),
27'b0, 2'b0, uxl_val, 12'b0,
mxr_val, sum_val, 1'b0, xs_val, fs_val,
4'b0, spp_val,
2'b0,
prev_ie_vec_prvS_val, prev_ie_vec_prvU_val,
2'b0,
ie_vec_prvS_val, ie_vec_prvU_val};
endfunction
// sie: restricted view of mie
Reg#(Data) sie_csr = concatReg9(
readOnlyReg(54'b0),
external_int_en_vec[prvS], external_int_en_vec[prvU],
external_int_en_vec[prvS], readOnlyReg(1'b0), // only if misa.N: external_int_en_vec[prvU],
readOnlyReg(2'b0),
timer_int_en_vec[prvS], timer_int_en_vec[prvU],
timer_int_en_vec[prvS], readOnlyReg(1'b0), // only if misa.N: timer_int_en_vec[prvU],
readOnlyReg(2'b0),
software_int_en_vec[prvS], software_int_en_vec[prvU]
software_int_en_vec[prvS], readOnlyReg(1'b0) // only if misa.N: software_int_en_vec[prvU]
);
// stvec
Reg#(Bit#(62)) stvec_base_hi_reg <- mkCsrReg(0); // BASE[63:2]
@@ -446,17 +564,27 @@ module mkCsrFile #(Data hartid)(CsrFile);
Reg#(Data) scause_csr = concatReg3(
scause_interrupt_reg, readOnlyReg(59'b0), scause_code_reg
);
function Data fn_scause_val (Bit #(1) scause_interrupt_val, Bit #(4) scause_code_val);
return { scause_interrupt_val, 59'b0, scause_code_val };
endfunction
// stval (sbadaddr in spike)
Reg#(Data) stval_csr <- mkCsrReg(0);
// sip: restricted view of mip
Reg#(Data) sip_csr = concatReg9(
readOnlyReg(54'b0),
external_int_pend_vec[prvS], external_int_pend_vec[prvU],
external_int_pend_vec[prvS], readOnlyReg(1'b0), // only if misa.N: external_int_pend_vec[prvU],
readOnlyReg(2'b0),
timer_int_pend_vec[prvS], timer_int_pend_vec[prvU],
timer_int_pend_vec[prvS], readOnlyReg(1'b0), // only if misa.N: timer_int_pend_vec[prvU],
readOnlyReg(2'b0),
software_int_pend_vec[prvS], software_int_pend_vec[prvU]
software_int_pend_vec[prvS], readOnlyReg(1'b0) // only if misa.N: software_int_pend_vec[prvU]
);
// SIP and SIE fields are WARL (Write Any Read Legal)
// We support S-privilege bits only;
// this mask allows only those bits through.
Data sip_sie_warl_mask = zeroExtend (12'h_222);
// satp (sptbr in spike): FIXME we only support Bare and Sv39, so we hack
// the encoding of mode[3:0] field. Only mode[3] is relevant, other bits
// are always 0
@@ -501,6 +629,43 @@ module mkCsrFile #(Data hartid)(CsrFile);
StatsCsr stats_module <- mkStatsCsr;
Reg#(Data) stats_csr = stats_module.reg_ifc;
Reg #(Data) rg_tselect <- mkConfigReg (0);
// Note: ISA test rv64mi-p-breakpoint assumes tdata1's reset value == 0
// Until we implement trigger functionality,
// force 'tdata1.type' field ([xlen-1:xlen-4]) to zero
// meaning: 'There is no trigger at this tselect'
Reg #(Bit #(4)) rg_tdata1_type <- mkReadOnlyReg (0);
Reg #(Bit #(1)) rg_tdata1_dmode <- mkCsrReg (0);
Reg #(Bit #(59)) rg_tdata1_data <- mkCsrReg (0);
Reg #(Data) rg_tdata1 = concatReg3 (rg_tdata1_type, rg_tdata1_dmode, rg_tdata1_data);
Reg #(Data) rg_tdata2 <- mkConfigRegU;
Reg #(Data) rg_tdata3 <- mkConfigRegU;
`ifdef INCLUDE_GDB_CONTROL
// DCSR is 32b even in RV64
Bit #(32) dcsr_reset_value = {4'h4, // [31:28] xdebugver
12'h0, // [27:16] reserved
1'h0, // [15] ebreakm
1'h0, // [14] reserved
1'h0, // [13] ebreaks
1'h0, // [12] ebreaku
1'h0, // [11] stepie
1'h0, // [10] stopcount
1'h0, // [9] stoptime
3'h0, // [8:6] cause // WARNING: 0 is non-standard
1'h0, // [5] reserved
1'h1, // [4] mprven
1'h0, // [3] nmip // non-maskable interrupt pending
1'h0, // [2] step
2'h3}; // [1:0] prv (machine mode)
// RV64: dcsr's upper 32b zeroExtended/ignored
Reg #(Data) rg_dcsr <- mkConfigReg (zeroExtend (dcsr_reset_value));
Reg #(Data) rg_dpc <- mkConfigReg (truncate (soc_map_struct.pc_reset_value));
Reg #(Data) rg_dscratch0 <- mkConfigRegU;
Reg #(Data) rg_dscratch1 <- mkConfigRegU;
`endif
`ifdef SECURITY
// sanctum machine CSRs
@@ -607,16 +772,117 @@ module mkCsrFile #(Data hartid)(CsrFile);
CSRmspec: mspec_csr;
CSRtrng: trng_csr;
`endif
CSRtselect: rg_tselect;
CSRtdata1: rg_tdata1;
CSRtdata2: rg_tdata2;
CSRtdata3: rg_tdata3;
`ifdef INCLUDE_GDB_CONTROL
CSRdcsr: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute)
CSRdpc: rg_dpc;
CSRdscratch0: rg_dscratch0;
CSRdscratch1: rg_dscratch1;
`endif
default: readOnlyReg(64'b0);
endcase);
endfunction
// ================================================================
// This function is the WARL (Write Any Read Legal) transform
// performed during CSR writes. Currently it duplicates the logic
// in the _write method of CSRs; ideally this function should be
// separate from the _write method, which should remain as an
// ordinary _write. The WARL'd value is needed for Tandem
// Verification.
function Data fv_warl_xform (CSR csr, Data x);
Asid x_asid = truncate (x [59:44]);
Bit #(16) asid = zeroExtend (x_asid);
return (
case (csr)
// Machine CSRs
CSRmisa: {getXLBits, 36'b0, getExtensionBits(isa)};
CSRmvendorid: 0;
CSRmarchid: 0;
CSRmimpid: 0;
CSRmhartid: hartid;
CSRmstatus: fn_mstatus_val (getXLBits, // sxl
getXLBits, // uxl
x [22], // tsr
x [21], // tw
x [20], // tvm
x [19], // mxr
x [18], // sum
x [17], // mprv
2'b0, // xs
((isa.f || isa.d) ? x [14:13] : 2'b0), // fs
x [12:11], // mpp
x [8], // spp
x [7], // prev_ie_vec[prvM]
x [5], // prev_ie_vec[prvS]
x [4], // prev_ie_vec[prvU]
x [3], // ie_vec[prvM]
x [1], // ie_vec[prvS]
x [0]); // ie_vec[prvU]
CSRmtvec: { x[63:2], 1'b0, x[0]};
CSRmedeleg: { 48'b0, x[15], 1'b0, x[13:12], x[11], 1'b0, x[9:0]};
CSRmideleg: { 52'b0, x[11], 1'b0, x[9:8], x[7], 1'b0, x[5:4], x[3], 1'b0, x[1:0]};
CSRmip: ((mip_csr & (~ mip_mie_warl_mask)) | (x & mip_mie_warl_mask));
CSRmie: (x & mip_mie_warl_mask);
CSRmcounteren: { 61'b0, x[2:0]};
CSRmcause: { x[63], 59'b0, x[3:0] };
CSRtdata1: { 4'b0, x [59:0] }; // Force tdata.type == 0 ("no trigger at this tselect")
// Supervisor level CSRs
CSRsstatus: fn_sstatus_val (getXLBits, // uxl
x [19], // mxr
x [18], // sum
2'b0, // xs
((isa.f || isa.d) ? x [14:13] : 2'b0), // fs
x [8], // spp
x [5], // prev_ie_vec[prvS]
x [4], // prev_ie_vec[prvU]
x [1], // ie_vec[prvS]
x [0]); // ie_vec[prvU]
CSRstvec: { x[63:2], 1'b0, x[0]};
CSRsip: ((sip_csr & (~ sip_sie_warl_mask)) | (x & sip_sie_warl_mask));
CSRsie: (x & sip_sie_warl_mask);
CSRscounteren: { 61'b0, x[2:0]};
CSRscause: { x[63], 59'b0, x[3:0] };
CSRsatp: { x[63], 3'b0, asid, x [43:0] };
// User level CSRs
CSRfflags: { 59'b0, x [4:0] };
CSRfrm: { 61'b0, x [2:0] };
CSRfcsr: { 56'b0, x [7:0] };
`ifdef INCLUDE_GDB_CONTROL
// Debug Mode CSRs
CSRdcsr: { 32'b0, x[31:28], 12'b0, x[14], 1'b0, x[13:6], 1'b0, x[4:0] };
`endif
default: x;
endcase);
endfunction
// ================================================================
// INTERFACE
method Data rd(CSR csr);
return get_csr(csr)._read;
endmethod
method Action csrInstWr(CSR csr, Data x);
get_csr(csr)._write(x);
`ifdef INCLUDE_GDB_CONTROL
if (csr == CSRdcsr) begin
let prv = x [1:0];
prv_reg <= prv;
end
`endif
endmethod
method Bool fpuInstNeedWr(Bit#(5) fflags, Bool fpu_dirty);
@@ -633,6 +899,35 @@ module mkCsrFile #(Data hartid)(CsrFile);
fflags_reg <= fflags_reg | fflags;
endmethod
`ifdef INCLUDE_TANDEM_VERIF
method Tuple2 #(Bit #(5), Data) fpuInst_csr_updates (Bit #(5) fflags,
Bool init_for_way0,
Bit #(5) old_fflags,
Data old_mstatus);
// Note: old_fflags and old_mstatus are accumulated in
// sequential program order, and so may differ from fflags_reg
// and mstatus_csr, which only change after superscalar-wide
// retirement.
Bit #(5) old_fflags1 = (init_for_way0 ? fflags_reg : old_fflags);
Data old_mstatus1 = (init_for_way0 ? mstatus_csr : old_mstatus);
Bit #(5) new_fflags = (old_fflags1 | fflags);
Data new_mstatus = { 1'b1, old_mstatus1 [62:15], 2'b11, old_mstatus1 [12:0] };
return tuple2 (new_fflags, new_mstatus);
endmethod
method Data getMIP;
return mip_csr;
endmethod
`endif
method Data warl_xform (CSR csr, Data x);
return fv_warl_xform (csr, x);
endmethod
method Maybe#(Interrupt) pending_interrupt;
// first get all the pending interrupts
Bit#(InterruptNum) pend_ints = truncate(mie_csr & mip_csr);
@@ -662,7 +957,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
end
endmethod
method ActionValue#(Addr) trap(Trap t, Addr pc, Addr addr);
method ActionValue#(Trap_Updates) trap(Trap t, Addr pc, Addr addr, Bit #(32) orig_inst);
// figure out trap cause & trap val
Bit#(1) cause_interrupt = 0;
Bit#(4) cause_code = 0;
@@ -671,6 +966,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
tagged Exception .e: begin
cause_code = pack(e);
trap_val = (case(e)
IllegalInst: zeroExtend (orig_inst);
InstAddrMisaligned, Breakpoint: return pc;
InstAccessFault, InstPageFault,
@@ -716,7 +1012,25 @@ module mkCsrFile #(Data hartid)(CsrFile);
scause_code_reg <= cause_code;
stval_csr <= trap_val;
// return next pc
return getNextPc(stvec_mode_low_reg, stvec_base_hi_reg);
// return getNextPc(stvec_mode_low_reg, stvec_base_hi_reg);
Data sstatus_val = fn_sstatus_val (uxl_reg,
mxr_reg, sum_reg,
xs_reg, fs_reg,
/* spp_reg */ prv_reg [0],
/* prev_ie_vec_[prvS] */ ie_vec[prvS],
prev_ie_vec [prvU],
/* ie_vec [prvS] */ 0,
ie_vec [prvU]);
Data scause_val = fn_scause_val (cause_interrupt, cause_code);
return Trap_Updates {new_pc: getNextPc(stvec_mode_low_reg, stvec_base_hi_reg)
`ifdef INCLUDE_TANDEM_VERIF
, prv: prvS,
status: sstatus_val,
cause: scause_val,
epc: pc,
tval: trap_val
`endif
};
end
else begin
// ie/prv stack
@@ -730,25 +1044,85 @@ module mkCsrFile #(Data hartid)(CsrFile);
mcause_code_reg <= cause_code;
mtval_csr <= trap_val;
// return next pc
return getNextPc(mtvec_mode_low_reg, mtvec_base_hi_reg);
// return getNextPc(mtvec_mode_low_reg, mtvec_base_hi_reg);
Data mstatus_val = fn_mstatus_val (sxl_reg, uxl_reg,
tsr_reg, tw_reg, tvm_reg,
mxr_reg, sum_reg, mprv_reg,
xs_reg, fs_reg,
/* mpp */ prv_reg, spp_reg,
/* prev_ie_vec [prvM] */ ie_vec [prvM],
prev_ie_vec [prvS],
prev_ie_vec [prvU],
/* ie_vec [prvM] */ 0,
ie_vec [prvS],
ie_vec [prvU]);
Data mcause_val = fn_mcause_val (cause_interrupt, cause_code);
return Trap_Updates {new_pc: getNextPc(mtvec_mode_low_reg, mtvec_base_hi_reg)
`ifdef INCLUDE_TANDEM_VERIF
, prv: prvM,
status: mstatus_val,
cause: mcause_val,
epc: pc,
tval: trap_val
`endif
};
end
// XXX yield load reservation should be done outside this method
endmethod
method ActionValue#(Addr) mret;
method ActionValue#(RET_Updates) mret;
prv_reg <= prev_prv_vec[prvM];
prev_prv_vec[prvM] <= prvU;
ie_vec[prvM] <= prev_ie_vec[prvM];
prev_ie_vec[prvM] <= 1;
return mepc_csr;
Data mstatus_val = fn_mstatus_val(sxl_reg, uxl_reg,
tsr_reg, tw_reg, tvm_reg,
mxr_reg, sum_reg, mprv_reg,
xs_reg, fs_reg,
/* mpp */ prvU,
spp_reg,
/* prev_ie_vec [prvM] */ 1,
prev_ie_vec [prvS],
prev_ie_vec [prvU],
/* ie_vec [prvM] */ prev_ie_vec[prvM],
ie_vec [prvS],
ie_vec [prvU]);
return RET_Updates {new_pc: mepc_csr
`ifdef INCLUDE_TANDEM_VERIF
, prv: prev_prv_vec[prvM],
status: mstatus_val
`endif
};
endmethod
method ActionValue#(Addr) sret;
method ActionValue#(RET_Updates) sret;
prv_reg <= prev_prv_vec[prvS];
prev_prv_vec[prvS] <= prvU;
ie_vec[prvS] <= prev_ie_vec[prvS];
prev_ie_vec[prvS] <= 1;
return sepc_csr;
// For Tandem Verification, we return the full underlying MSTATUS register
Data mstatus_val = fn_mstatus_val(sxl_reg, uxl_reg,
tsr_reg, tw_reg, tvm_reg,
mxr_reg, sum_reg, mprv_reg,
xs_reg, fs_reg,
mpp_reg,
/* spp_reg */ prvU [0],
prev_ie_vec [prvM],
/* prev_ie_vec_[prvS] */ 1,
prev_ie_vec [prvU],
ie_vec [prvM],
/* ie_vec [prvS] */ prev_ie_vec[prvS],
ie_vec [prvU]);
return RET_Updates {new_pc: sepc_csr
`ifdef INCLUDE_TANDEM_VERIF
, prv: prev_prv_vec[prvS],
status: mstatus_val
`endif
};
endmethod
method VMInfo vmI;
@@ -845,15 +1219,53 @@ module mkCsrFile #(Data hartid)(CsrFile);
external_int_pend_vec[prvS] <= v;
endmethod
// Bluespec: external interrupt to enter debug mode
method Action setDEIP (Bit #(1) v);
debug_int_pend <= v;
endmethod
method terminate = terminate_module.terminate;
// performance stats
method doPerfStats = stats_module.doPerfStats;
method sendDoStats = stats_module.sendDoStats;
method recvDoStats = stats_module.recvDoStats;
// ----------------
// Bluespec:
// Methods when Debug Module is present
`ifdef INCLUDE_GDB_CONTROL
// Read dpc
method Addr dpc_read ();
return rg_dpc;
endmethod
// Update dpc
method Action dpc_write (Addr pc);
rg_dpc <= pc;
endmethod
// Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku}
method Bit #(1) dcsr_break_bit;
return case (prv_reg)
prvM: rg_dcsr [15];
prvS: rg_dcsr [13];
prvU: rg_dcsr [12];
endcase;
endmethod
// Check whether to enter Debug Mode based on dcsr.step
method Bit #(1) dcsr_step_bit;
return rg_dcsr [2];
endmethod
// Update 'cause' in DCSR
// Is invoked by logic that stops a hart, to enter Debug Mode
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
rg_dcsr <= { 32'b0, rg_dcsr [31:9], dcsr_cause, rg_dcsr [5:2], prv_reg };
/*
$display ("%0d: %m mkCsrFile.method-dcsr_cause_write: cause %0d, prv %0d",
cur_cycle, dcsr_cause, prv_reg);
*/
endmethod
`endif
endmodule

View File

@@ -107,8 +107,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
awregion: fabric_default_region,
awuser: fabric_default_user};
let mem_req_wr_data = AXI4_Wr_Data {wid: fabric_default_id,
wdata: st_val,
let mem_req_wr_data = AXI4_Wr_Data {wdata: st_val,
wstrb: strb,
wlast: True,
wuser: fabric_default_user};

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2018 Massachusetts Institute of Technology
// Portions (c) 2019-2020 Bluespec, Inc.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -21,8 +22,6 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Portions (c) 2019 Bluespec, Inc.
// This file is adapted from: MIT-riscy/riscy-OOO/procs/lib/MMIOPlatform.bsv
// Modifications to fit into Bluespec's RISC-V execution environments.
@@ -289,7 +288,8 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
// To avoid posting timer interrupt repeatedly, we keep a copy of MTIP
// here. Since each core cannot write MTIP by CSRXXX inst, the only way to
// change MTIP is through here.
Vector#(CoreNum, Reg#(Bool)) mtip <- replicateM(mkReg(False));
// We initialize to True to avoid an timer interrupt at start of time.
Vector#(CoreNum, Reg#(Bool)) mtip <- replicateM(mkReg(True));
// pass mtime to each core
rule propagateTime(state != Init);

View File

@@ -1,5 +1,14 @@
// Copyright (c) 2019-2020 Bluespec, Inc.
package MMIO_AXI4_Adapter;
// ================================================================
// This is an adapter to connect MIT's RISCY-OOO to an AXI4 fabric in
// Bluespec's Toooba setup. All IO traffic to the fabric flows through
// this. Note: a few IO addresses (e.g., MTIME, MTIMECMP, MSIP,
// TOHOST, FROMHOST are intercepted and handled before they reach this
// adapter).
// ================================================================
// BSV lib imports
@@ -30,6 +39,7 @@ import ProcTypes :: *;
import AXI4_Types :: *;
import Fabric_Defs :: *;
import SoC_Map :: *;
// ================================================================
@@ -56,6 +66,8 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
FIFOF #(MMIOCRq) f_reqs_from_core <- mkFIFOF;
FIFOF #(MMIODataPRs) f_rsps_to_core <- mkFIFOF;
SoC_Map_IFC soc_map <- mkSoC_Map; // for m_is_IO_addr
// ================================================================
// Fabric request/response
@@ -108,12 +120,26 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
awregion: fabric_default_region,
awuser: fabric_default_user};
let mem_req_wr_data = AXI4_Wr_Data {wid: fabric_default_id,
wdata: st_val,
let mem_req_wr_data = AXI4_Wr_Data {wdata: st_val,
wstrb: strb,
wlast: True,
wuser: fabric_default_user};
`ifdef FABRIC64
// Work-around for a misbehavior on Xilinx UART and its
// Xilinx AXI4 adapter. On 64-bit fabrics, for a write where
// axsize says '8 bytes' but wstrb is for <= 4 bytes, the
// adapter converts it two 32-bit writes, one of which has
// wstrb=4'b0000. The Xilinx UART, in turn ignores wstrb and
// therefore performs a spurious write. This workaround
// changes axsize for such writes to '4 bytes', avoiding this
// problem.
if (strb [7:4] == 0 || strb [3:0] == 0) begin
mem_req_wr_addr.awsize = axsize_4;
end
`endif
master_xactor.i_wr_addr.enq (mem_req_wr_addr);
master_xactor.i_wr_data.enq (mem_req_wr_data);
@@ -122,8 +148,8 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
// Debugging
if (cfg_verbosity > 0) begin
$display (" To fabric: ", fshow (mem_req_wr_addr));
$display (" ", fshow (mem_req_wr_data));
$display (" To fabric: ", fshow (mem_req_wr_addr));
$display (" ", fshow (mem_req_wr_data));
end
endaction
endfunction
@@ -138,11 +164,25 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
let req <- pop (f_reqs_from_core);
if (cfg_verbosity > 0) begin
$display ("%0d: MMIO_AXI4_Adapter.rl_handle_read_req: Ld request", cur_cycle);
$display ("%0d: %m.rl_handle_read_req: Ld request", cur_cycle);
$display (" ", fshow (req));
end
fa_fabric_send_read_req (req.addr);
// Technically the following check for legal IO addrs is not
// necessary; the AXI4 fabric should return a DECERR for illegal
// addrs; but not all AXI4 fabrics do the right thing.
if (soc_map.m_is_IO_addr (req.addr))
fa_fabric_send_read_req (req.addr);
else begin
let rsp = MMIODataPRs {valid: False,
data: req.addr}; // For debugging convenience only
f_rsps_to_core.enq (rsp);
if (cfg_verbosity > 0) begin
$display ("%0d: %m.rl_handle_read_req: unmapped IO address; returning error response",
cur_cycle);
$display (" ", fshow (req));
end
end
endrule
// ----------------
@@ -151,12 +191,12 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
let mem_rsp <- pop_o (master_xactor.o_rd_data);
if (cfg_verbosity > 0) begin
$display ("%0d: MMIO_AXI4_Adapter.rl_handle_read_rsps ", cur_cycle);
$display ("%0d: %m.rl_handle_read_rsps ", cur_cycle);
$display (" ", fshow (mem_rsp));
end
if ((cfg_verbosity > 0) && (mem_rsp.rresp != axi4_resp_okay)) begin
$display ("%0d: MMIO_AXI4_Adapter.rl_handle_read_rsp: fabric response error", cur_cycle);
$display ("%0d: %m.rl_handle_read_rsp: fabric response error", cur_cycle);
$display (" ", fshow (mem_rsp));
end
@@ -175,11 +215,25 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
let req <- pop (f_reqs_from_core);
if (cfg_verbosity > 0) begin
$display ("%d: MMIO_AXI4_Adapter.rl_handle_write_req: St request:", cur_cycle);
$display ("%d: %m.rl_handle_write_req: St request:", cur_cycle);
$display (" ", fshow (req));
end
fa_fabric_send_write_req (req.addr, pack (req.byteEn), req.data);
// Technically the following check for legal IO addrs is not
// necessary; the AXI4 fabric should return a DECERR for illegal
// addrs; but not all AXI4 fabrics do the right thing.
if (soc_map.m_is_IO_addr (req.addr))
fa_fabric_send_write_req (req.addr, pack (req.byteEn), req.data);
else begin
let rsp = MMIODataPRs {valid: False,
data: req.addr}; // For debugging convenience only
f_rsps_to_core.enq (rsp);
if (cfg_verbosity > 0) begin
$display ("%0d: %m.rl_handle_write_req: unmapped IO address; returning error response",
cur_cycle);
$display (" ", fshow (req));
end
end
endrule
// ----------------
@@ -189,12 +243,12 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
let wr_resp <- pop_o (master_xactor.o_wr_resp);
if (cfg_verbosity > 0) begin
$display ("%0d: MMIO_AXI4_Adapter.rl_discard_write_rsp", cur_cycle);
$display ("%0d: %m.rl_discard_write_rsp", cur_cycle);
$display (" ", fshow (wr_resp));
end
if (ctr_wr_rsps_pending.value == 0) begin
$display ("%0d: ERROR: MMIO_AXI4_Adapter.rl_discard_write_rsp: unexpected Wr response (ctr_wr_rsps_pending.value == 0)",
$display ("%0d:%m.rl_discard_write_rsp: ERROR:unexpected Wr response (ctr_wr_rsps_pending.value == 0)",
cur_cycle);
$display (" ", fshow (wr_resp));
$finish (1); // Assertion failure
@@ -204,7 +258,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
if (wr_resp.bresp != axi4_resp_okay) begin
// TODO: need to raise a non-maskable interrupt (NMI) here
$display ("%0d: MMIO_AXI4_Adapter.rl_discard_write_rsp: fabric response error: exit", cur_cycle);
$display ("%0d:%m.rl_discard_write_rsp: ERROR: fabric response error: exit.", cur_cycle);
$display (" ", fshow (wr_resp));
$finish (1);
end
@@ -228,8 +282,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
rule rl_handle_non_Ld_St (! fn_is_Ld_or_St (f_reqs_from_core.first));
let req <- pop (f_reqs_from_core);
$display ("%0d: ERROR: MMIO_AXI4_Adapter.rl_handle_non_Ld_St",
cur_cycle);
$display ("%0d:%m.rl_handle_non_Ld_St: ERROR: neither Ld nor St? exit.", cur_cycle);
$display (" ", fshow (req));
$finish (1); // Assertion failure
endrule

View File

@@ -1,6 +1,9 @@
package Proc;
// Note: this module corresponds to module 'mkCPU' in Piccolo/Flute.
// Copyright (c) 2018 Massachusetts Institute of Technology
// Portions Copyright (c) 2019-2020 Bluespec, Inc.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -22,8 +25,6 @@ package Proc;
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Portions Copyright (c) 2019 Bluespec, Inc.
// ================================================================
// BSV lib imports
@@ -77,17 +78,13 @@ import SoC_Map :: *;
import AXI4_Types :: *;
import Fabric_Defs :: *;
`ifdef INCLUDE_GDB_CONTROL
import DM_CPU_Req_Rsp :: *;
`endif
`ifdef INCLUDE_TANDEM_VERIF
import TV_Info :: *;
`endif
`ifdef EXTERNAL_DEBUG_MODULE
`undef INCLUDE_GDB_CONTROL
import ProcTypes :: *;
import Trace_Data2 :: *;
`endif
// ================================================================
@@ -108,50 +105,6 @@ module mkProc (Proc_IFC);
// Verbosity: 0=quiet; 1=instruction trace; 2=more detail
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0);
// ----------------
// Reset requests and responses (TODO: to be implemented)
FIFOF #(Bit #(0)) f_reset_reqs <- mkFIFOF;
FIFOF #(Bit #(0)) f_reset_rsps <- mkFIFOF;
// ----------------
// Communication to/from External debug module (TODO: to be implemented)
`ifdef INCLUDE_GDB_CONTROL
// Debugger run-control
FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF;
FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF;
// Stop-request from debugger (e.g., GDB ^C or Dsharp 'stop')
Reg #(Bool) rg_stop_req <- mkReg (False);
// Count instrs after step-request from debugger (via dcsr.step)
Reg #(Bit #(1)) rg_step_count <- mkReg (0);
// Debugger GPR read/write request/response
FIFOF #(DM_CPU_Req #(5, XLEN)) f_gpr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(XLEN)) f_gpr_rsps <- mkFIFOF1;
`ifdef ISA_F
// Debugger FPR read/write request/response
FIFOF #(DM_CPU_Req #(5, FLEN)) f_fpr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(FLEN)) f_fpr_rsps <- mkFIFOF1;
`endif
// Debugger CSR read/write request/response
FIFOF #(DM_CPU_Req #(12, XLEN)) f_csr_reqs <- mkFIFOF1;
FIFOF #(DM_CPU_Rsp #(XLEN)) f_csr_rsps <- mkFIFOF1;
`endif
// ----------------
// Tandem Verification (TODO: to be implemented)
`ifdef INCLUDE_TANDEM_VERIF
FIFOF #(Trace_Data) f_trace_data <- mkFIFOF;
`endif
// ----------------
// MMIO
@@ -185,16 +138,11 @@ module mkProc (Proc_IFC);
tlbToMem[i] = core[i].tlbToMem;
end
// Stub out memLoader (TODO: can be Debug Module's access)
let memLoaderStub = interface MemLoaderMemClient;
interface memReq = nullFifoDeq;
interface respSt = nullFifoEnq;
endinterface;
mkLLCDmaConnect(llc.dma, memLoaderStub, tlbToMem);
// Note: mkLLCDmaConnect is Toooba version, different from riscy-ooo version
let llc_mem_server <- mkLLCDmaConnect(llc.dma, tlbToMem);
// ================================================================
// interface LLC to AXI4
// interface Back-side of LLC to AXI4
LLC_AXI4_Adapter_IFC llc_axi4_adapter <- mkLLC_AXi4_Adapter (llc.to_mem);
@@ -249,18 +197,6 @@ module mkProc (Proc_IFC);
end
// ================================================================
// Reset
rule rl_reset;
let x <- pop (f_reset_reqs);
llc_axi4_adapter.reset;
mmio_axi4_adapter.reset;
f_reset_rsps.enq (?);
endrule
// ----------------
// Termination detection
for(Integer i = 0; i < valueof(CoreNum); i = i+1) begin
@@ -270,7 +206,9 @@ module mkProc (Proc_IFC);
endrule
end
// ================================================================
// Print out values written 'tohost'
rule rl_tohost;
let x <- mmioPlatform.to_host;
$display ("%0d: mmioPlatform.rl_tohost: 0x%0x (= %0d)", cur_cycle, x, x);
@@ -292,11 +230,9 @@ module mkProc (Proc_IFC);
// ================================================================
// INTERFACE
// Reset
interface Server hart0_server_reset = toGPServer (f_reset_reqs, f_reset_rsps);
// ----------------
// Start the cores running
// Use toHostAddr = 0 if not monitoring tohost
method Action start (Addr startpc, Addr tohostAddr, Addr fromhostAddr);
action
for(Integer i = 0; i < valueof(CoreNum); i = i+1)
@@ -305,8 +241,8 @@ module mkProc (Proc_IFC);
mmioPlatform.start (tohostAddr, fromhostAddr);
$display ("Proc.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h",
startpc, tohostAddr, fromhostAddr);
$display ("%0d: %m.method start: startpc %0h, tohostAddr %0h, fromhostAddr %0h",
cur_cycle, startpc, tohostAddr, fromhostAddr);
endmethod
// ----------------
@@ -329,13 +265,6 @@ module mkProc (Proc_IFC);
core[0].setSEIP (pack (x));
endmethod
// ----------------
// External interrupt [14] to go into Debug Mode
method Action debug_external_interrupt_req (Bool set_not_clear);
core[0].setDEIP (pack (set_not_clear));
endmethod
// ----------------
// Non-maskable interrupt
@@ -350,11 +279,9 @@ module mkProc (Proc_IFC);
endmethod
// ----------------
// Optional interface to Tandem Verifier
// Coherent port into LLC (used by Debug Module, DMA engines, ... to read/write memory)
`ifdef INCLUDE_TANDEM_VERIF
interface Get trace_data_out = toGet (f_trace_data);
`endif
interface debug_module_mem_server = llc_mem_server;
`ifdef RVFI_DII
interface Toooba_RVFI_DII_Server rvfi_dii_server = core[0].rvfi_dii_server;
@@ -364,8 +291,8 @@ module mkProc (Proc_IFC);
// Optional interface to Debug Module
`ifdef INCLUDE_GDB_CONTROL
// run-control, other
interface Server hart0_server_run_halt = toGPServer (f_run_halt_reqs, f_run_halt_rsps);
// run/halt, gpr, mem and csr control goes to core
interface Server hart0_run_halt_server = core [0].hart0_run_halt_server;
interface Put hart0_put_other_req;
method Action put (Bit #(4) req);
@@ -373,16 +300,16 @@ module mkProc (Proc_IFC);
endmethod
endinterface
// GPR access
interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps);
interface Server hart0_gpr_mem_server = core[0].hart0_gpr_mem_server;
`ifdef ISA_F
// FPR access
interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps);
interface Server hart0_fpr_mem_server = core[0].hart0_fpr_mem_server;
`endif
interface Server hart0_csr_mem_server = core[0].hart0_csr_mem_server;
`endif
// CSR access
interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps);
`ifdef INCLUDE_TANDEM_VERIF
interface v_to_TV = core [0].v_to_TV;
`endif
endmodule: mkProc

View File

@@ -1,10 +1,11 @@
// Copyright (c) 2016-2019 Bluespec, Inc. All Rights Reserved
// Copyright (c) 2016-2020 Bluespec, Inc. All Rights Reserved
package Proc_IFC;
// ================================================================
// BSV library imports
import Vector :: *;
import GetPut :: *;
import ClientServer :: *;
@@ -21,7 +22,8 @@ import DM_CPU_Req_Rsp :: *;
`endif
`ifdef INCLUDE_TANDEM_VERIF
import TV_Info :: *;
import ProcTypes :: *;
import Trace_Data2 :: *;
`endif
`ifdef RVFI_DII
@@ -36,11 +38,10 @@ import Types :: *;
// because the RISCY-OOO mkProc contains those elements.
interface Proc_IFC;
// Reset
interface Server #(Token, Token) hart0_server_reset;
// ----------------
// Start the cores running
// Use toHostAddr = 0 if not monitoring tohost
method Action start (Addr startpc, Addr tohostAddr, Addr fromhostAddr);
// ----------------
@@ -61,12 +62,6 @@ interface Proc_IFC;
(* always_ready, always_enabled *)
method Action s_external_interrupt_req (Bool set_not_clear);
// ----------------
// External interrupt [14] to go into Debug Mode
(* always_ready, always_enabled *)
method Action debug_external_interrupt_req (Bool set_not_clear);
// ----------------
// Non-maskable interrupt
@@ -79,11 +74,9 @@ interface Proc_IFC;
method Action set_verbosity (Bit #(4) verbosity);
// ----------------
// Optional interface to Tandem Verifier
// Coherent port into LLC (used by Debug Module, DMA engines, ... to read/write memory)
`ifdef INCLUDE_TANDEM_VERIF
interface Get #(Trace_Data) trace_data_out;
`endif
interface AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) debug_module_mem_server;
`ifdef RVFI_DII
interface Toooba_RVFI_DII_Server rvfi_dii_server;
@@ -93,20 +86,24 @@ interface Proc_IFC;
// Optional interface to Debug Module
`ifdef INCLUDE_GDB_CONTROL
// run-control, other
interface Server #(Bool, Bool) hart0_server_run_halt;
interface Put #(Bit #(4)) hart0_put_other_req;
// GPR access
interface Server #(Bool, Bool) hart0_run_halt_server;
interface Server #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_server;
`ifdef ISA_F
// FPR access
interface Server #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_server;
`endif
// CSR access
interface Server #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_server;
// Non-standard
interface Put #(Bit #(4)) hart0_put_other_req;
`endif
`ifdef INCLUDE_TANDEM_VERIF
// Note: this is a SupSize vector of streams of Trace_Data2 structs,
// each of which has a serialnum field. Each of the SupSize
// streams has serialnums in increasing order. Each serialnum
// appears exactly once in exactly one of the streams. Thus, the
// channels can easily be merged into a single program-order stream.
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
`endif
endinterface