Merge branch 'CHERI' into ifetch-cleanup

This commit is contained in:
jon
2021-01-13 15:21:20 +00:00
35 changed files with 1335 additions and 607 deletions

View File

@@ -93,10 +93,10 @@ library RTL can be found in the directory `src_bsc_lib_RTL`.
- `src_Core/`, for the CPU core, with sub-directories:
- `Core/`: the top-level of the CPU Core (specifically, the files CoreW_IFC.bsv and CoreW.bsv)
- 'CPU/': more CPU core sources
- 'RISCY_OOO': the bulk of the code, taken from MIT's riscy-ooo design, with local modifications.
- `CPU/`: more CPU core sources
- `RISCY_OOO/`: the bulk of the code, taken from MIT's riscy-ooo design, with local modifications.
- `ISA/`: generic types/constants/functions for the RISC-V ISA (not CPU-implementation-specific)
- 'PLIC/': Platform-Level Interrupt Controller (standard RISC-V spec)
- `PLIC/`: Platform-Level Interrupt Controller (standard RISC-V spec)
- `BSV_Additional_Libs/`: generic utilities (not CPU-specific)
- `Debug_Module/`: RISC-V Debug Module to debug the CPU from GDB or other debuggers

View File

@@ -249,9 +249,9 @@ void c_mem_load_elf (char *elf_filename,
#define MIN_MEM_ADDR_16MB BASE_ADDR_B
#define MAX_MEM_ADDR_16MB (BASE_ADDR_B + 0x1000000lu)
// For 256 MB memory at 0x_8000_0000
#define MIN_MEM_ADDR_256MB BASE_ADDR_B
#define MAX_MEM_ADDR_256MB (BASE_ADDR_B + 0x10000000lu)
// For 1 GB memory at 0x_8000_0000
#define MIN_MEM_ADDR_1GB BASE_ADDR_B
#define MAX_MEM_ADDR_1GB (BASE_ADDR_B + 0x40000000lu)
// ================================================================
@@ -282,8 +282,8 @@ void write_mem_hex_file (FILE *fp, uint64_t addr1, uint64_t addr2)
}
// Write last word, if necessary, to avoid warnings about missing locations
if (addr < (MAX_MEM_ADDR_256MB - bytes_per_raw_mem_word)) {
addr = MAX_MEM_ADDR_256MB - bytes_per_raw_mem_word;
if (addr < (MAX_MEM_ADDR_1GB - bytes_per_raw_mem_word)) {
addr = MAX_MEM_ADDR_1GB - bytes_per_raw_mem_word;
fprintf (fp, "@%07" PRIx64 " // last raw_mem addr; byte addr: %08" PRIx64 "\n",
((addr - BASE_ADDR_B) / bytes_per_raw_mem_word),
addr - BASE_ADDR_B);
@@ -304,8 +304,8 @@ void print_usage (FILE *fp, int argc, char *argv [])
fprintf (fp, " %s <ELF filename> <mem hex filename>\n", argv [0]);
fprintf (fp, "Reads ELF file and writes a Verilog Hex Memory image file\n");
fprintf (fp, "ELF file should have addresses within this range:\n");
fprintf (fp, "< Max: 0x%8" PRIx64 "\n", MAX_MEM_ADDR_256MB);
fprintf (fp, ">= Min: 0x%8" PRIx64 "\n", MIN_MEM_ADDR_256MB);
fprintf (fp, "< Max: 0x%8" PRIx64 "\n", MAX_MEM_ADDR_1GB);
fprintf (fp, ">= Min: 0x%8" PRIx64 "\n", MIN_MEM_ADDR_1GB);
}
// ================================================================
@@ -327,7 +327,7 @@ int main (int argc, char *argv [])
c_mem_load_elf (argv [1], "_start", "exit", "tohost");
if ((min_addr < BASE_ADDR_B) || (MAX_MEM_ADDR_256MB <= max_addr)) {
if ((min_addr < BASE_ADDR_B) || (MAX_MEM_ADDR_1GB <= max_addr)) {
print_usage (stderr, argc, argv);
exit (1);
}
@@ -340,7 +340,7 @@ int main (int argc, char *argv [])
fprintf (stdout, "Writing mem hex to file '%s'\n", argv [2]);
write_mem_hex_file (fp_out, BASE_ADDR_B, max_addr);
// write_mem_hex_file (fp_out, BASE_ADDR_B, MAX_MEM_ADDR_256MB);
// write_mem_hex_file (fp_out, BASE_ADDR_B, MAX_MEM_ADDR_1GB);
fclose (fp_out);
}

View File

@@ -38,6 +38,7 @@ BSC_COMPILATION_FLAGS += \
-D CheriMasterIDWidth=1 \
-D CheriTransactionIDWidth=5 \
-D CAP128 -D BLUESIM \
-D PERFORMANCE_MONITORING \
-D MEM64 \
-D RISCV \
-D RVFI_DII \

View File

@@ -59,6 +59,10 @@ import TlbTypes::*;
import SynthParam::*;
import VerificationPacket::*;
import Performance::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import BlueUtils::*;
`endif
import HasSpecBits::*;
import Exec::*;
import FetchStage::*;
@@ -212,6 +216,10 @@ interface Core;
method Bit#(32) debugRename;
`endif
`ifdef PERFORMANCE_MONITORING
method Action events_llc(EventsCache events);
method Action events_tgc(EventsCache events);
`endif
endinterface
// fixpoint to instantiate modules
@@ -232,6 +240,21 @@ typedef enum {
} Core_Run_State
deriving (Bits, Eq, FShow);
`ifdef PERFORMANCE_MONITORING
instance BitVectorable #(EventsCore, SizeOf#(SupCnt), EventsCoreElements) provisos (Bits #(EventsCore, m));
function Vector#(EventsCoreElements, SupCnt) to_vector(EventsCore e) =
reverse(unpack(pack(e)));
endinstance
instance BitVectorable #(EventsCoreMem, SizeOf#(HpmRpt), EventsCoreMemElements) provisos (Bits #(EventsCoreMem, m));
function Vector#(EventsCoreMemElements, HpmRpt) to_vector(EventsCoreMem e) =
reverse(unpack(pack(e)));
endinstance
instance BitVectorable #(EventsCache, SizeOf#(HpmRpt), EventsCacheElements) provisos (Bits #(EventsCache, m));
function Vector#(EventsCacheElements, HpmRpt) to_vector(EventsCache e) =
reverse(unpack(pack(e)));
endinstance
`endif
(* synthesize *)
module mkCore#(CoreId coreId)(Core);
let verbose = False;
@@ -258,6 +281,10 @@ module mkCore#(CoreId coreId)(Core);
Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF);
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCore)) hpm_core_events <- mkDRegOR (5, unpack (0));
`endif
// ================================================================
// front end
@@ -400,6 +427,11 @@ module mkCore#(CoreId coreId)(Core);
`endif
);
globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag);
`ifdef PERFORMANCE_MONITORING
EventsCore events = unpack (0);
events.evt_REDIRECT = 1;
hpm_core_events[1] <= events;
`endif
endmethod
method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put;
method doStats = doStatsReg._read;
@@ -1075,6 +1107,41 @@ module mkCore#(CoreId coreId)(Core);
endrule
`endif
`ifdef PERFORMANCE_MONITORING
// ================================================================
// Performance counters
Reg#(EventsCache) events_llc_reg <- mkRegU;
Reg#(EventsCache) events_tgc_reg <- mkRegU;
rule report_events;
hpm_core_events[2] <= unpack(pack(commitStage.events));
endrule
Vector #(1, Bit #(Report_Width)) null_evt = replicate (0);
Vector #(31, Bit #(Report_Width)) mem_core_evts_vec = to_large_vector (coreFix.memExeIfc.events);
Vector #(31, Bit #(Report_Width)) other_core_evts_vec = to_large_vector (hpm_core_events[0]);
Vector #(31, Bit #(Report_Width)) core_evts_vec = unpack(pack(mem_core_evts_vec) | pack(other_core_evts_vec));
EventsCache instMem = unpack(pack(iMem.events) | pack(iTlb.events));
Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (instMem);
EventsCache dataMem = unpack(pack(dMem.events) | pack(dTlb.events));
Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dataMem);
Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts);
Vector #(16, Bit #(Report_Width)) llc_evts_vec = to_large_vector (events_llc_reg);
Vector #(16, Bit #(Report_Width)) tgc_evts_vec = to_large_vector (events_tgc_reg);
let events = append (null_evt, core_evts_vec);
events = append (events, imem_evts_vec);
events = append (events, dmem_evts_vec);
events = append (events, external_evts_vec);
events = append (events, llc_evts_vec);
events = append (events, tgc_evts_vec);
(* fire_when_enabled, no_implicit_conditions *)
rule rl_send_perf_evts;
csrf.send_performance_events (events);
endrule
`endif
`ifdef INCLUDE_GDB_CONTROL
// ================================================================
// DEBUG MODULE INTERFACE
@@ -1467,4 +1534,9 @@ module mkCore#(CoreId coreId)(Core);
endmethod
`endif
`ifdef PERFORMANCE_MONITORING
method events_llc = events_llc_reg._write;
method events_tgc = events_tgc_reg._write;
`endif
endmodule

View File

@@ -58,6 +58,10 @@ import ISA_Decls_CHERI::*;
import Cur_Cycle :: *;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor :: *;
`endif
// ================================================================
// Project imports from Toooba
@@ -179,6 +183,10 @@ interface CsrFile;
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
`endif
`ifdef PERFORMANCE_MONITORING
(* always_ready, always_enabled *)
method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Report_Width)) evts);
`endif
endinterface
// Fancy Reg functions
@@ -233,6 +241,38 @@ function Reg#(t) addWriteSideEffect(Reg#(t) r, Action a);
endinterface);
endfunction
`ifdef PERFORMANCE_MONITORING
interface PerfCountersVec;
interface Vector#(No_Of_Ctrs, Reg#(Data)) counter_vec;
interface Vector#(No_Of_Ctrs, Reg#(Data)) event_vec;
interface Reg#(Data) inhibit;
method Action send_performance_events (Vector #(No_Of_Evts, Bit#(Report_Width)) evts);
endinterface
(* synthesize *)
module mkPerfCountersToooba (PerfCountersVec);
PerfCounters_IFC #(No_Of_Ctrs, Counter_Width, Report_Width, No_Of_Evts) perf_counters <- mkPerfCounters;
Vector#(No_Of_Ctrs, Reg#(Data)) counters = ?;
for (Bit#(TLog#(No_Of_Ctrs)) i = 0; i < 29; i = i + 1) counters[i] =
interface Reg;
method Action _write(Data x) = perf_counters.write_counter(i,x);
method Data _read = perf_counters.read_counters[i];
endinterface;
Vector#(No_Of_Ctrs, Reg#(Data)) events = ?;
for (Bit#(TLog#(No_Of_Ctrs)) i = 0; i < 29; i = i + 1) events[i] =
interface Reg;
method Action _write(Data x) = perf_counters.write_ctr_sel(i,truncate(x));
method Data _read = zeroExtend(perf_counters.read_ctr_sels[i]);
endinterface;
interface counter_vec = counters;
interface event_vec = events;
interface inhibit = interface Reg;
method Action _write(Data x) = perf_counters.write_ctr_inhibit(truncate(x));
method Data _read = zeroExtend(perf_counters.read_ctr_inhibit);
endinterface;
method send_performance_events = perf_counters.send_performance_events;
endmodule
`endif
function Bool has_csr_permission(CSR csr, Bit#(2) prv, Bool write);
Bit#(12) csr_index = pack(csr);
return ((prv >= csr_index[9:8]) && (!write || (csr_index[11:10] != 2'b11)));
@@ -682,6 +722,16 @@ module mkCsrFile #(Data hartid)(CsrFile);
Reg #(Data) rg_dscratch1 <- mkConfigRegU;
`endif
`ifdef PERFORMANCE_MONITORING
PerfCountersVec perf_counters <- mkPerfCountersToooba;
//Reg #(Bit #(2)) rg_ctr_inhib_lsb <- mkReg (0);
//Wire #(Bit #(2)) w_ctr_inhib_lsb <- mkWire;
//Bit #(3) ctr_inhibit_lsb = { rg_ctr_inhib_lsb [1], 0, rg_ctr_inhib_lsb [0] };
//Word ctr_inhibit = zeroExtend ({ perf_counters.read_ctr_inhibit, ctr_inhibit_lsb });
//CSR_Addr no_of_ctrs = fromInteger (valueOf (No_Of_Ctrs));
`endif
`ifdef SECURITY
// sanctum machine CSRs
@@ -756,6 +806,14 @@ module mkCsrFile #(Data hartid)(CsrFile);
// Function for getting a csr given an index
function Reg#(Data) get_csr(CSR csr);
Reg#(Data) ret = readOnlyReg(64'b0);
`ifdef PERFORMANCE_MONITORING
let c = csr.addr;
if ((csrAddrMHPMCOUNTER3.addr <= c) && (c <= csrAddrMHPMCOUNTER31.addr))
ret = perf_counters.counter_vec[c-csrAddrMHPMCOUNTER3.addr];
if ((csrAddrMHPMEVENT3.addr <= c) && (c <= csrAddrMHPMEVENT31.addr))
ret = perf_counters.event_vec[c - csrAddrMHPMEVENT3.addr];
`endif
return (case (csr)
// User CSRs
csrAddrFFLAGS: fflags_csr;
@@ -797,6 +855,9 @@ module mkCsrFile #(Data hartid)(CsrFile);
csrAddrMIMPID: mimpid_csr;
csrAddrMHARTID: mhartid_csr;
csrAddrMCCSR: csr_capcause(mccsr_reg);
`ifdef PERFORMANCE_MONITORING
csrAddrMCOUNTERINHIBIT: perf_counters.inhibit;
`endif
`ifdef SECURITY
csrAddrMEVBASE: mevbase_csr;
csrAddrMEVMASK: mevmask_csr;
@@ -810,20 +871,19 @@ module mkCsrFile #(Data hartid)(CsrFile);
csrAddrMSPEC: mspec_csr;
csrAddrTRNG: trng_csr;
`endif
csrAddrTSELECT: rg_tselect;
csrAddrTDATA1: rg_tdata1;
csrAddrTDATA2: rg_tdata2;
csrAddrTDATA3: rg_tdata3;
csrAddrTSELECT: rg_tselect;
csrAddrTDATA1: rg_tdata1;
csrAddrTDATA2: rg_tdata2;
csrAddrTDATA3: rg_tdata3;
`ifdef INCLUDE_GDB_CONTROL
csrAddrDCSR: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute)
csrAddrDPC: scrToCsr(rg_dpc);
csrAddrDSCRATCH0: rg_dscratch0;
csrAddrDSCRATCH1: rg_dscratch1;
csrAddrDCSR: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute)
csrAddrDPC: scrToCsr(rg_dpc);
csrAddrDSCRATCH0: rg_dscratch0;
csrAddrDSCRATCH1: rg_dscratch1;
`endif
default: readOnlyReg(64'b0);
default: ret;
endcase);
endfunction
@@ -1341,4 +1401,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
`endif
`ifdef PERFORMANCE_MONITORING
method send_performance_events = perf_counters.send_performance_events;
`endif
endmodule

View File

@@ -54,9 +54,9 @@ interface LLC_AXI4_Adapter_IFC;
method Action reset;
// Fabric master interface for memory
interface AXI4_Master_Synth #(Wd_MId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) mem_master;
interface AXI4_Master #(Wd_MId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) mem_master;
endinterface
// ================================================================
@@ -76,7 +76,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
// ================================================================
// Fabric request/response
let master_xactor <- mkAXI4_Master_Xactor;
let masterPortShim <- mkAXI4ShimFF;
// For discarding write-responses
CreditCounter_IFC #(4) ctr_wr_rsps_pending <- mkCreditCounter; // Max 15 writes outstanding
@@ -100,7 +100,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
arregion: fabric_default_region,
aruser: fabric_default_aruser};
master_xactor.slave.ar.put(mem_req_rd_addr);
masterPortShim.slave.ar.put(mem_req_rd_addr);
// Debugging
if (cfg_verbosity > 1) begin
@@ -134,7 +134,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
endrule
rule rl_handle_read_rsps;
let mem_rsp <- get(master_xactor.slave.r);
let mem_rsp <- get(masterPortShim.slave.r);
if (cfg_verbosity > 1) begin
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_rsps: beat %0d ", cur_cycle, rg_rd_rsp_beat);
@@ -189,7 +189,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
// ================
if (rg_wr_req_beat == 0) begin
// send AXI4 AW flit
master_xactor.slave.aw.put (AXI4_AWFlit {
masterPortShim.slave.aw.put (AXI4_AWFlit {
awid: fabric_default_mid,
awaddr: { wb.addr [63:6], 6'h0 },
awlen: 7, // burst len = awlen+1
@@ -218,7 +218,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
Vector #(8, Bit #(8)) line_strb = unpack(pack(wb.byteEn));
Vector #(4, MemTaggedData) line_data = clineToMemTaggedDataVector(wb.data);
// send AXI4 W flit
master_xactor.slave.w.put(AXI4_WFlit {
masterPortShim.slave.w.put(AXI4_WFlit {
wdata: line_data[rg_wr_req_beat[2:1]].data[rg_wr_req_beat[0]],
wstrb: line_strb[rg_wr_req_beat],
wlast: rg_wr_req_beat == 7,
@@ -229,7 +229,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
// Discard write-responses from the fabric
rule rl_discard_write_rsp;
let wr_resp <- get(master_xactor.slave.b);
let wr_resp <- get(masterPortShim.slave.b);
if (ctr_wr_rsps_pending.value == 0) begin
$display ("%0d: ERROR: LLC_AXI4_Adapter.rl_discard_write_rsp: unexpected Wr response (ctr_wr_rsps_pending.value == 0)",
@@ -256,7 +256,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
endmethod
// Fabric interface for memory
interface mem_master = master_xactor.masterSynth;
interface mem_master = masterPortShim.master;
endmodule
// ================================================================

View File

@@ -50,6 +50,7 @@ import GetPut :: *;
import ClientServer :: *;
import Connectable :: *;
import FIFOF :: *;
import FIFO :: *;
import ConfigReg :: *;
// ----------------
@@ -170,16 +171,33 @@ module mkProc (Proc_IFC);
// ================================================================
// Connect stats
FIFO#(Bool) statReqs <- mkFIFO;
for(Integer i = 0; i < valueof(CoreNum); i = i+1) begin
rule broadcastStats;
Bool doStats <- core[i].sendDoStats;
for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin
core[j].recvDoStats(doStats);
end
llc.perf.setStatus(doStats);
endrule
rule recvStatReq;
Bool doStats <- core[i].sendDoStats;
statReqs.enq(doStats);
endrule
end
rule broadcastStats;
for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin
core[j].recvDoStats(statReqs.first);
end
llc.perf.setStatus(statReqs.first);
statReqs.deq;
endrule
`ifdef PERFORMANCE_MONITORING
Reg#(EventsCache) events_tgc_reg <- mkRegU;
rule broadcastPerfEvents;
for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin
core[j].events_llc(llc.events);
core[j].events_tgc(events_tgc_reg);
end
endrule
`endif
// ================================================================
// Stub out deadlock and renameDebug interfaces
@@ -340,6 +358,10 @@ module mkProc (Proc_IFC);
method Bit #(32) hart0_debug_rename = core [0].debugRename;
`endif
`ifdef PERFORMANCE_MONITORING
method events_tgc = events_tgc_reg._write;
`endif
endmodule: mkProc
// ================================================================

View File

@@ -32,6 +32,7 @@ import ISA_Decls :: *;
import AXI4 :: *;
import Fabric_Defs :: *;
import SoC_Map :: *;
import CCTypes :: *;
`ifdef INCLUDE_GDB_CONTROL
import DM_CPU_Req_Rsp :: *;
@@ -69,9 +70,9 @@ interface Proc_IFC;
// SoC fabric connections
// Fabric master interface for memory (from LLC)
interface AXI4_Master_Synth #(Wd_MId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master0;
interface AXI4_Master #(Wd_MId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master0;
// Fabric master interface for IO (from MMIOPlatform)
interface AXI4_Master #(Wd_MId_2x3, Wd_Addr, Wd_Data,
@@ -101,9 +102,9 @@ interface Proc_IFC;
// ----------------
// Coherent port into LLC (used by Debug Module, DMA engines, ... to read/write memory)
interface AXI4_Slave_Synth #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) debug_module_mem_server;
interface AXI4_Slave #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) debug_module_mem_server;
`ifdef RVFI_DII
interface Toooba_RVFI_DII_Server rvfi_dii_server;
@@ -144,6 +145,10 @@ interface Proc_IFC;
method Bit #(32) hart0_debug_rename;
`endif
`ifdef PERFORMANCE_MONITORING
method Action events_tgc(EventsCache events);
`endif
endinterface
// ================================================================

View File

@@ -74,6 +74,7 @@ import ProcTypes :: *;
// Main fabric
import Fabric_Defs :: *; // for Wd_Id, Wd_Addr, Wd_Data...
import SoC_Map :: *;
import CCTypes :: *; // for EventsCache.
`ifdef INCLUDE_GDB_CONTROL
import Debug_Module :: *;
@@ -164,17 +165,27 @@ module mkCoreW #(Reset dm_power_on_reset)
Proc_IFC proc <- mkProc (reset_by hart0_reset);
// handle uncached interface
let proc_uncached <- toAXI4_Master_Synth(extendIDFields(zeroMasterUserFields(proc.master1), 0));
let proc_uncached = extendIDFields (zeroMasterUserFields (proc.master1), 0);
// Bridge for uncached expernal bus transactions.
let uncached_mem_shim <- mkAXI4ShimFF(reset_by hart0_reset);
let uncached_mem_master <- toAXI4_Master_Synth(extendIDFields(zeroMasterUserFields(uncached_mem_shim.master), 0), reset_by hart0_reset);
// handle cached interface
// AXI4 tagController
TagControllerAXI#(Wd_MId, Wd_Addr, Wd_Data) tagController <- mkTagControllerAXI(reset_by hart0_reset); // TODO double check if reseting like this is good enough
AXI4_Master#(Wd_MId, Wd_Addr, Wd_Data, Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User)
tmp2 <- fromAXI4_Master_Synth(proc.master0, reset_by hart0_reset);
mkConnection(tmp2, tagController.slave, reset_by hart0_reset);
mkConnection(proc.master0, tagController.slave, reset_by hart0_reset);
`ifdef PERFORMANCE_MONITORING
rule report_tagController_events;
Vector#(7, Bit#(1)) evts = tagController.events;
EventsCache ce = unpack(0);
ce.evt_ST = zeroExtend(evts[0]); // Unsure of mapping from EventsCacheCore to 7-bit vector.
ce.evt_ST_MISS = zeroExtend(evts[1]);
ce.evt_LD = zeroExtend(evts[2]);
ce.evt_LD_MISS = zeroExtend(evts[3]);
ce.evt_EVICT = zeroExtend(evts[4]);
// SET_TAG_WRITE/READ aren't used in TagCache; tag table data is not tagged.
proc.events_tgc(ce);
endrule
`endif
// PLIC (Platform-Level Interrupt Controller)
PLIC_IFC_16_2_7 plic <- mkPLIC_16_2_7;
@@ -355,26 +366,24 @@ module mkCoreW #(Reset dm_power_on_reset)
// Connect the local 2x3 fabric
// Masters on the local 2x3 fabric
Vector#(Num_Masters_2x3,
AXI4_Master_Synth #(Wd_MId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User))
master_vector = newVector;
Vector#(Num_Masters_2x3, AXI4_Master #(Wd_MId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User))
master_vector = newVector;
//let master_vector = newVector;
master_vector[cpu_uncached_master_num] = proc_uncached;
master_vector[debug_module_sba_master_num] = dm_master_local;
// Slaves on the local 2x3 fabric
// default slave is forwarded out directly to the Core interface
Vector#(Num_Slaves_2x3,
AXI4_Slave_Synth #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User))
slave_vector = newVector;
Vector#(Num_Slaves_2x3, AXI4_Slave #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User))
slave_vector = newVector;
//let slave_vector = newVector;
slave_vector[default_slave_num] <- toAXI4_Slave_Synth(uncached_mem_shim.slave);
slave_vector[default_slave_num] = uncached_mem_shim.slave;
slave_vector[llc_slave_num] = proc.debug_module_mem_server;
slave_vector[plic_slave_num] = plic.axi4_slave;
slave_vector[plic_slave_num] = zeroSlaveUserFields (plic.axi4_slave);
function Vector#(Num_Slaves_2x3, Bool) route_2x3 (Bit#(Wd_Addr) addr);
Vector#(Num_Slaves_2x3, Bool) res = replicate(False);
@@ -389,9 +398,7 @@ module mkCoreW #(Reset dm_power_on_reset)
return res;
endfunction
mkAXI4Bus_Synth (route_2x3, master_vector, slave_vector);
let cached_mem_master <- toAXI4_Master_Synth(tagController.master);
mkAXI4Bus (route_2x3, master_vector, slave_vector);
// ================================================================
// Connect external interrupt lines from PLIC to CPU
@@ -441,10 +448,10 @@ module mkCoreW #(Reset dm_power_on_reset)
// AXI4 Fabric interfaces
// Cached master to Fabric master interface
interface cpu_imem_master = cached_mem_master;
interface cpu_imem_master = tagController.master;
// Uncached master to Fabric master interface
interface cpu_dmem_master = uncached_mem_master;
interface cpu_dmem_master = extendIDFields(zeroMasterUserFields(uncached_mem_shim.master), 0);
// ----------------------------------------------------------------
// External interrupt sources
@@ -493,6 +500,31 @@ module mkCoreW #(Reset dm_power_on_reset)
endmodule: mkCoreW
(* synthesize *)
module mkCoreW_Synth #(Reset dm_power_on_reset)
(CoreW_IFC_Synth #(N_External_Interrupt_Sources));
let core <- mkCoreW (dm_power_on_reset);
let cpu_imem_master_synth <- toAXI4_Master_Synth (core.cpu_imem_master);
let cpu_dmem_master_synth <- toAXI4_Master_Synth (core.cpu_dmem_master);
method set_verbosity = core.set_verbosity;
method start = core.start;
interface cpu_imem_master = cpu_imem_master_synth;
interface cpu_dmem_master = cpu_dmem_master_synth;
interface core_external_interrupt_sources = core.core_external_interrupt_sources;
method nmi_req = core.nmi_req;
`ifdef RVFI_DII
interface rvfi_dii_server = core.rvfi_dii_server;
`endif
`ifdef INCLUDE_GDB_CONTROL
interface dmi = core.dmi;
interface ndm_reset_client = core.ndm_reset_client;
`endif
`ifdef INCLUDE_TANDEM_VERIF
interface tv_verifier_info_get = core.tv_verifier_info_get;
`endif
endmodule
// ================================================================
// 2x3 Fabric for this Core
// Masters: CPU DMem, Debug Module System Bus Access, External access

View File

@@ -81,6 +81,74 @@ interface CoreW_IFC #(numeric type t_n_interrupt_sources);
// ----------------------------------------------------------------
// AXI4 Fabric interfaces
// CPU IMem to Fabric master interface
interface AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
0, 0, 0, 0, 0) cpu_imem_master;
// CPU DMem to Fabric master interface
interface AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
0, 0, 0, 0, 0) cpu_dmem_master;
// ----------------------------------------------------------------
// External interrupt sources
interface Vector #(t_n_interrupt_sources, PLIC_Source_IFC) core_external_interrupt_sources;
// ----------------------------------------------------------------
// Non-maskable interrupt request
(* always_ready, always_enabled *)
method Action nmi_req (Bool set_not_clear);
`ifdef RVFI_DII
interface Toooba_RVFI_DII_Server rvfi_dii_server;
`endif
`ifdef INCLUDE_GDB_CONTROL
// ----------------------------------------------------------------
// Optional Debug Module interfaces
// ----------------
// DMI (Debug Module Interface) facing remote debugger
interface DMI dmi;
// ----------------
// Facing Platform
// Non-Debug-Module Reset (reset all except DM)
interface Client #(Bool, Bool) ndm_reset_client;
`endif
`ifdef INCLUDE_TANDEM_VERIF
// ----------------------------------------------------------------
// Optional Tandem Verifier interface output tuples (n,vb),
// where 'vb' is a vector of bytes
// with relevant bytes in locations [0]..[n-1]
interface Get #(Info_CPU_to_Verifier) tv_verifier_info_get;
`endif
endinterface
// ================================================================
// The Synthesizable CoreW interface (same with Synth AXI)
interface CoreW_IFC_Synth #(numeric type t_n_interrupt_sources);
// ----------------------------------------------------------------
// Debugging: set core's verbosity
method Action set_verbosity (Bit #(4) verbosity, Bit #(64) logdelay);
// ----------------------------------------------------------------
// Start
method Action start (Bool is_running, Bit #(64) tohost_addr, Bit #(64) fromhost_addr);
// ----------------------------------------------------------------
// AXI4 Fabric interfaces
// CPU IMem to Fabric master interface
interface AXI4_Master_Synth #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
0, 0, 0, 0, 0) cpu_imem_master;

View File

@@ -54,9 +54,9 @@ interface DM_System_Bus_IFC;
// ----------------
// Facing System
interface AXI4_Master_Synth #(Wd_MId_2x3, Wd_Addr, Wd_Data_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master;
interface AXI4_Master #(Wd_MId_2x3, Wd_Addr, Wd_Data_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master;
endinterface
// ================================================================
@@ -197,10 +197,8 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
// ----------------------------------------------------------------
// Interface to memory fabric
AXI4_Master_Xactor#(Wd_MId_2x3, Wd_Addr, Wd_Data_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User)
master_xactor <- mkAXI4_Master_Xactor;
let master_xactor <- mkAXI4ShimFF;
// ----------------------------------------------------------------
// System Bus state
@@ -680,7 +678,7 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
// ----------------
// Facing System
interface AXI4_Master_IFC master = master_xactor.masterSynth;
interface master = master_xactor.master;
endmodule
// ================================================================

View File

@@ -155,9 +155,9 @@ interface Debug_Module_IFC;
interface Client #(Bool, Bool) ndm_reset_client;
// Read/Write RISC-V memory
interface AXI4_Master_Synth #(Wd_MId_2x3, Wd_Addr, Wd_Data_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master;
interface AXI4_Master #(Wd_MId_2x3, Wd_Addr, Wd_Data_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) master;
endinterface
// ================================================================
@@ -481,7 +481,7 @@ module mkDebug_Module (Debug_Module_IFC);
interface Client ndm_reset_client = dm_run_control.ndm_reset_client;
// Read/Write RISC-V memory
interface AXI4_Master_IFC master = dm_system_bus.master;
interface master = dm_system_bus.master;
endmodule
// ================================================================

View File

@@ -85,8 +85,8 @@ endinterface
// PLIC interface
interface PLIC_IFC #(numeric type t_n_external_sources,
numeric type t_n_targets,
numeric type t_max_priority);
numeric type t_n_targets,
numeric type t_max_priority);
// Debugging
method Action set_verbosity (Bit #(4) verbosity);
method Action show_PLIC_state;
@@ -98,9 +98,8 @@ interface PLIC_IFC #(numeric type t_n_external_sources,
method Action set_addr_map (Bit #(64) addr_base, Bit #(64) addr_lim);
// Memory-mapped access
interface AXI4_Slave_Synth #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) axi4_slave;
interface AXI4_Slave #( Wd_SId_2x3, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
axi4_slave;
// sources
interface Vector #(t_n_external_sources, PLIC_Source_IFC) v_sources;
@@ -114,9 +113,9 @@ endinterface
module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
provisos (Add #(1, t_n_external_sources, t_n_sources), // source 0 is reserved for 'no source'
Add #(_any_0, TLog #(t_n_sources), T_wd_source_id),
Add #(_any_1, TLog #(t_n_targets), T_wd_target_id),
Log #(TAdd #(t_max_priority, 1), t_wd_priority));
Add #(_any_0, TLog #(t_n_sources), T_wd_source_id),
Add #(_any_1, TLog #(t_n_targets), T_wd_target_id),
Log #(TAdd #(t_max_priority, 1), t_wd_priority));
// 0 = quiet; 1 = show PLIC transactions; 2 = also show AXI4 transactions
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0);
@@ -142,9 +141,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
Reg #(Bit #(64)) rg_addr_lim <- mkRegU;
// Connector to AXI4 fabric
AXI4_Slave_Width_Xactor#(Wd_SId_2x3, Wd_Addr, Wd_Data_Periph, Wd_Data,
Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph, Wd_AR_User_Periph, Wd_R_User_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User) slave_xactor <- mkAXI4_Slave_Zeroing_Xactor;
let slavePortShim <- mkAXI4ShimFF;
// ----------------
// Per-interrupt source state
@@ -161,15 +158,13 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
// Threshold: interrupts at or below threshold should be masked out for target
Vector #(t_n_targets, Reg #(Bit #(t_wd_priority))) vrg_target_threshold <- replicateM (mkReg ('1));
// Target has claimed interrupt for source and is servicing it
Vector #(t_n_targets, Reg #(Bit #(TLog #(t_n_sources)))) vrg_servicing_source <- replicateM (mkReg (0));
// ----------------
// Per-target, per-source state
// Interrupt enables from source to target
Vector #(t_n_targets,
Vector #(t_n_sources, Reg #(Bool))) vvrg_ie <- replicateM (replicateM (mkReg (False)));
Vector #(t_n_sources, Reg #(Bool))) vvrg_ie <- replicateM (replicateM (mkReg (False)));
// ================================================================
// Compute outputs for each target (combinational)
@@ -182,42 +177,42 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
// Note: source_ids begin at 1, not 0.
for (Integer source_id = 1; source_id < n_sources; source_id = source_id + 1)
if ( vrg_source_ip [source_id]
&& (vrg_source_prio [source_id] > max_prio)
&& (vvrg_ie [target_id][source_id])) begin
max_id = fromInteger (source_id);
max_prio = vrg_source_prio [source_id];
end
if ( vrg_source_ip [source_id]
&& (vrg_source_prio [source_id] > max_prio)
&& (vvrg_ie [target_id][source_id])) begin
max_id = fromInteger (source_id);
max_prio = vrg_source_prio [source_id];
end
// Assert: if any interrupt is pending (max_id > 0), then prio > 0
return tuple2 (max_prio, max_id);
endfunction
function Action fa_show_PLIC_state;
action
$display ("----------------");
$write ("Src IPs :");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", pack (vrg_source_ip [source_id]));
$display ("");
$display ("----------------");
$write ("Src IPs :");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", pack (vrg_source_ip [source_id]));
$display ("");
$write ("Src Prios:");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", vrg_source_prio [source_id]);
$display ("");
$write ("Src Prios:");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", vrg_source_prio [source_id]);
$display ("");
$write ("Src busy :");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", pack (vrg_source_busy [source_id]));
$display ("");
$write ("Src busy :");
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", pack (vrg_source_busy [source_id]));
$display ("");
for (Integer target_id = 0; target_id < n_targets; target_id = target_id + 1) begin
$write ("T %0d IEs :", target_id);
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", vvrg_ie [target_id][source_id]);
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (fromInteger (target_id));
$display (" MaxPri %0d, Thresh %0d, MaxId %0d, Svcing %0d",
max_prio, vrg_target_threshold [target_id], max_id, vrg_servicing_source [target_id]);
end
for (Integer target_id = 0; target_id < n_targets; target_id = target_id + 1) begin
$write ("T %0d IEs :", target_id);
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
$write (" %0d", vvrg_ie [target_id][source_id]);
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (fromInteger (target_id));
$display (" MaxPri %0d, Thresh %0d, MaxId %0d",
max_prio, vrg_target_threshold [target_id], max_id);
end
endaction
endfunction
@@ -226,27 +221,26 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
rule rl_reset;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_reset", cur_cycle);
$display ("%0d: PLIC.rl_reset", cur_cycle);
let x <- pop (f_reset_reqs);
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1) begin
vrg_source_ip [source_id] <= False;
vrg_source_busy [source_id] <= False;
vrg_source_prio [source_id] <= 0;
vrg_source_ip [source_id] <= False;
vrg_source_busy [source_id] <= False;
vrg_source_prio [source_id] <= 0;
end
for (Integer target_id = 0; target_id < n_targets; target_id = target_id + 1) begin
// Mask all interrupts with highest threshold
vrg_target_threshold [target_id] <= '1;
vrg_servicing_source [target_id] <= 0;
// Mask all interrupts with highest threshold
vrg_target_threshold [target_id] <= '1;
end
for (Integer target_id = 0; target_id < n_targets; target_id = target_id + 1)
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
vvrg_ie [target_id][source_id] <= False;
for (Integer source_id = 0; source_id < n_sources; source_id = source_id + 1)
vvrg_ie [target_id][source_id] <= False;
slave_xactor.clear;
slavePortShim.clear;
f_reset_rsps.enq (?);
endrule
@@ -261,10 +255,10 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
rule rl_process_rd_req (! f_reset_reqs.notEmpty);
let rda <- get(slave_xactor.master.ar);
let rda <- get(slavePortShim.master.ar);
if (cfg_verbosity > 1) begin
$display ("%0d: PLIC.rl_process_rd_req:", cur_cycle);
$display (" ", fshow (rda));
$display ("%0d: PLIC.rl_process_rd_req:", cur_cycle);
$display (" ", fshow (rda));
end
let addr_offset = rda.araddr - rg_addr_base;
@@ -272,148 +266,137 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
AXI4_Resp rresp = OKAY;
if (rda.araddr < rg_addr_base) begin
// Technically this should not happen: the fabric should
// never have delivered such an addr to this IP.
$display ("%0d: ERROR: PLIC.rl_process_rd_req: unrecognized addr", cur_cycle);
$display (" ", fshow (rda));
rresp = DECERR;
// Technically this should not happen: the fabric should
// never have delivered such an addr to this IP.
$display ("%0d: ERROR: PLIC.rl_process_rd_req: unrecognized addr", cur_cycle);
$display (" ", fshow (rda));
rresp = DECERR;
end
// Source Priority
else if (addr_offset < 'h1000) begin
Bit #(T_wd_source_id) source_id = truncate (addr_offset [11:2]);
if ((0 < source_id) && (source_id <= fromInteger (n_sources - 1))) begin
rdata = changeWidth (vrg_source_prio [source_id]);
Bit #(T_wd_source_id) source_id = truncate (addr_offset [11:2]);
if ((0 < source_id) && (source_id <= fromInteger (n_sources - 1))) begin
rdata = changeWidth (vrg_source_prio [source_id]);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Source Priority: source %0d = 0x%0h",
cur_cycle, source_id, rdata);
end
else
rresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Source Priority: source %0d = 0x%0h",
cur_cycle, source_id, rdata);
end
else
rresp = SLVERR;
end
// Source IPs (interrupt pending).
// Return 32 consecutive IP bits starting with addr.
else if (('h1000 <= addr_offset) && (addr_offset < 'h2000)) begin
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [11:0], 5'h0 });
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [11:0], 5'h0 });
function Bool fn_ip_source_id (Integer source_id_offset);
let source_id = source_id_base + fromInteger (source_id_offset);
Bool ip_source_id = ( (source_id <= fromInteger (n_sources - 1))
? vrg_source_ip [source_id]
: False);
return ip_source_id;
endfunction
function Bool fn_ip_source_id (Integer source_id_offset);
let source_id = source_id_base + fromInteger (source_id_offset);
Bool ip_source_id = ( (source_id <= fromInteger (n_sources - 1))
? vrg_source_ip [source_id]
: False);
return ip_source_id;
endfunction
if (source_id_base <= fromInteger (n_sources - 1)) begin
Bit #(32) v_ip = pack (genWith (fn_ip_source_id));
rdata = changeWidth (v_ip);
if (source_id_base <= fromInteger (n_sources - 1)) begin
Bit #(32) v_ip = pack (genWith (fn_ip_source_id));
rdata = changeWidth (v_ip);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Intr Pending 32 bits from source %0d = 0x%0h",
cur_cycle, source_id_base, rdata);
end
else
rresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Intr Pending 32 bits from source %0d = 0x%0h",
cur_cycle, source_id_base, rdata);
end
else
rresp = SLVERR;
end
// Source IEs (interrupt enables) for a target
// Return 32 consecutive IE bits starting with addr.
// Target 0 addrs: 2000-207F, Target 1 addrs: 2080-20FF, ...
else if (('h2000 <= addr_offset) && (addr_offset < 'h3000)) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [11:7]);
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [6:0], 5'h0 });
Bit #(T_wd_target_id) target_id = truncate (addr_offset [11:7]);
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [6:0], 5'h0 });
function Bool fn_ie_source_id (Integer source_id_offset);
let source_id = fromInteger (source_id_offset) + source_id_base;
return ( (source_id <= fromInteger (n_sources - 1))
? vvrg_ie [target_id][source_id]
: False);
endfunction
function Bool fn_ie_source_id (Integer source_id_offset);
let source_id = fromInteger (source_id_offset) + source_id_base;
return ( (source_id <= fromInteger (n_sources - 1))
? vvrg_ie [target_id][source_id]
: False);
endfunction
if ( (source_id_base <= fromInteger (n_sources - 1))
&& (target_id <= fromInteger (n_targets - 1))) begin
Bit #(32) v_ie = pack (genWith (fn_ie_source_id));
rdata = changeWidth (v_ie);
if ( (source_id_base <= fromInteger (n_sources - 1))
&& (target_id <= fromInteger (n_targets - 1))) begin
Bit #(32) v_ie = pack (genWith (fn_ie_source_id));
rdata = changeWidth (v_ie);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Intr Enable 32 bits from source %0d = 0x%0h",
cur_cycle, source_id_base, rdata);
end
else
rresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Intr Enable 32 bits from source %0d = 0x%0h",
cur_cycle, source_id_base, rdata);
end
else
rresp = SLVERR;
end
// Target threshold
else if ((addr_offset [31:0] & 32'hFFFF_0FFF) == 32'h0020_0000) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
if (target_id <= fromInteger (n_targets - 1)) begin
rdata = changeWidth (vrg_target_threshold [target_id]);
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
if (target_id <= fromInteger (n_targets - 1)) begin
rdata = changeWidth (vrg_target_threshold [target_id]);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Threshold for target %0d = 0x%0h",
cur_cycle, target_id, rdata);
end
else
rresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Threshold for target %0d = 0x%0h",
cur_cycle, target_id, rdata);
end
else
rresp = SLVERR;
end
// Interrupt service claim by target
else if ((addr_offset [31:0] & 32'hFFFF_0FFF) == 32'h0020_0004) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (target_id);
Bool eip = (max_prio > vrg_target_threshold [target_id]);
if (target_id <= fromInteger (n_targets - 1)) begin
if (vrg_servicing_source [target_id] != 0) begin
$display ("%0d: ERROR: PLIC: target %0d claiming without prior completion",
cur_cycle, target_id);
$display (" Still servicing interrupt from source %0d", vrg_servicing_source [target_id]);
$display (" Trying to claim service for source %0d", max_id);
$display (" Ignoring.");
rresp = SLVERR;
end
else begin
if (max_id != 0) begin
vrg_source_ip [max_id] <= False;
vrg_source_busy [max_id] <= True;
vrg_servicing_source [target_id] <= truncate (max_id);
rdata = changeWidth (max_id);
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (target_id);
Bool eip = (max_prio > vrg_target_threshold [target_id]);
if (target_id <= fromInteger (n_targets - 1)) begin
if (max_id != 0) begin
vrg_source_ip [max_id] <= False;
vrg_source_busy [max_id] <= True;
rdata = changeWidth (max_id);
end
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Claim for target %0d = 0x%0h",
cur_cycle, target_id, rdata);
end
end
end
else
rresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_rd_req: reading Claim for target %0d = 0x%0h",
cur_cycle, target_id, rdata);
end
else
rresp = SLVERR;
end
else
rresp = SLVERR;
rresp = SLVERR;
if (rresp != OKAY) begin
$display ("%0d: ERROR: PLIC.rl_process_rd_req: unrecognized addr", cur_cycle);
$display (" ", fshow (rda));
$display ("%0d: ERROR: PLIC.rl_process_rd_req: unrecognized addr", cur_cycle);
$display (" ", fshow (rda));
end
if ((valueOf (Wd_Data) == 64) && ((addr_offset & 'h7) == 'h4))
rdata = { rdata [31:0], 32'h0 };
rdata = { rdata [31:0], 32'h0 };
// Send read-response to bus
Fabric_Data x = truncate (rdata);
let rdr = AXI4_RFlit {rid: rda.arid,
rdata: x,
rresp: rresp,
rlast: True,
ruser: rda.aruser}; // XXX This requires that Wd_AR_User == Wd_R_User
slave_xactor.master.r.put(rdr);
rdata: x,
rresp: rresp,
rlast: True,
ruser: rda.aruser}; // XXX This requires that Wd_AR_User == Wd_R_User
slavePortShim.master.r.put(rdr);
if (cfg_verbosity > 1) begin
$display ("%0d: PLIC.rl_process_rd_req", cur_cycle);
$display (" ", fshow (rda));
$display (" ", fshow (rdr));
$display ("%0d: PLIC.rl_process_rd_req", cur_cycle);
$display (" ", fshow (rda));
$display (" ", fshow (rdr));
end
endrule: rl_process_rd_req
@@ -424,142 +407,140 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
rule rl_process_wr_req (! f_reset_reqs.notEmpty);
let wra <- get(slave_xactor.master.aw);
let wrd <- get(slave_xactor.master.w);
let wra <- get(slavePortShim.master.aw);
let wrd <- get(slavePortShim.master.w);
if (cfg_verbosity > 1) begin
$display ("%0d: PLIC.rl_process_wr_req", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
$display ("%0d: PLIC.rl_process_wr_req", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
end
let addr_offset = wra.awaddr - rg_addr_base;
let wdata32 = (((valueOf (Wd_Data) == 64) && ((addr_offset & 'h7) == 'h4))
? wrd.wdata [63:32]
: wrd.wdata [31:0]);
? wrd.wdata [63:32]
: wrd.wdata [31:0]);
let bresp = OKAY;
if (wra.awaddr < rg_addr_base) begin
// Technically this should not happen: the fabric should
// never have delivered such an addr to this IP.
$display ("%0d: ERROR: PLIC.rl_process_wr_req: unrecognized addr", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
bresp = DECERR;
// Technically this should not happen: the fabric should
// never have delivered such an addr to this IP.
$display ("%0d: ERROR: PLIC.rl_process_wr_req: unrecognized addr", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
bresp = DECERR;
end
// Source priority
else if (addr_offset < 'h1000) begin
Bit #(T_wd_source_id) source_id = truncate (addr_offset [11:2]);
if ((0 < source_id) && (source_id <= fromInteger (n_sources - 1))) begin
vrg_source_prio [source_id] <= changeWidth (wdata32);
Bit #(T_wd_source_id) source_id = truncate (addr_offset [11:2]);
if ((0 < source_id) && (source_id <= fromInteger (n_sources - 1))) begin
vrg_source_prio [source_id] <= changeWidth (wdata32);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing Source Priority: source %0d = 0x%0h",
cur_cycle, source_id, wdata32);
end
else begin
// Note: write to source_id 0 is error; should it just be ignored?
bresp = SLVERR;
end
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing Source Priority: source %0d = 0x%0h",
cur_cycle, source_id, wdata32);
end
else begin
// Note: write to source_id 0 is error; should it just be ignored?
bresp = SLVERR;
end
end
// Source IPs (interrupt pending).
// Read-only, so ignore write; just check that addr ok.
else if (('h1000 <= addr_offset) && (addr_offset < 'h2000)) begin
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [11:0], 5'h0 });
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [11:0], 5'h0 });
if (source_id_base <= fromInteger (n_sources - 1)) begin
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: Ignoring write to Read-only Intr Pending 32 bits from source %0d",
cur_cycle, source_id_base);
end
else
bresp = SLVERR;
if (source_id_base <= fromInteger (n_sources - 1)) begin
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: Ignoring write to Read-only Intr Pending 32 bits from source %0d",
cur_cycle, source_id_base);
end
else
bresp = SLVERR;
end
// Source IEs (interrupt enables) for a target
// Write 32 consecutive IE bits starting with addr.
// Target 0 addrs: 2000-207F, Target 1 addrs: 2080-20FF, ...
else if (('h2000 <= addr_offset) && (addr_offset < 'h3000)) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [11:7]);
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [6:0], 5'h0 });
Bit #(T_wd_target_id) target_id = truncate (addr_offset [11:7]);
Bit #(T_wd_source_id) source_id_base = truncate ({ addr_offset [6:0], 5'h0 });
if ( (source_id_base <= fromInteger (n_sources - 1))
&& (target_id <= fromInteger (n_targets - 1))) begin
for (Bit #(T_wd_source_id) k = 0; k < 32; k = k + 1) begin
Bit #(T_wd_source_id) source_id = source_id_base + k;
if (source_id <= fromInteger (n_sources - 1))
vvrg_ie [target_id][source_id] <= unpack (wdata32 [k]);
end
if ( (source_id_base <= fromInteger (n_sources - 1))
&& (target_id <= fromInteger (n_targets - 1))) begin
for (Bit #(T_wd_source_id) k = 0; k < 32; k = k + 1) begin
Bit #(T_wd_source_id) source_id = source_id_base + k;
if (source_id <= fromInteger (n_sources - 1))
vvrg_ie [target_id][source_id] <= unpack (wdata32 [k]);
end
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing Intr Enable 32 bits for target %0d from source %0d = 0x%0h",
cur_cycle, target_id, source_id_base, wdata32);
end
else
bresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing Intr Enable 32 bits for target %0d from source %0d = 0x%0h",
cur_cycle, target_id, source_id_base, wdata32);
end
else
bresp = SLVERR;
end
// Target threshold
else if ((addr_offset [31:0] & 32'hFFFF_0FFF) == 32'h0020_0000) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
if (target_id <= fromInteger (n_targets - 1)) begin
vrg_target_threshold [target_id] <= changeWidth (wdata32);
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
if (target_id <= fromInteger (n_targets - 1)) begin
vrg_target_threshold [target_id] <= changeWidth (wdata32);
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing threshold for target %0d = 0x%0h",
cur_cycle, target_id, wdata32);
end
else
bresp = SLVERR;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing threshold for target %0d = 0x%0h",
cur_cycle, target_id, wdata32);
end
else
bresp = SLVERR;
end
// Interrupt service completion by target
// Actual memory-write-data is irrelevant.
// Write data is the source ID to complete. Disabled sources are ignored.
else if ((addr_offset [31:0] & 32'hFFFF_0FFF) == 32'h0020_0004) begin
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
Bit #(T_wd_source_id) source_id = zeroExtend (vrg_servicing_source [target_id]);
Bit #(T_wd_target_id) target_id = truncate (addr_offset [20:12]);
Bit #(T_wd_source_id) source_id = truncate (wdata32);
if (target_id <= fromInteger (n_targets - 1)) begin
if (vrg_source_busy [source_id]) begin
vrg_source_busy [source_id] <= False;
vrg_servicing_source [target_id] <= 0;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing completion for target %0d for source 0x%0h",
cur_cycle, target_id, source_id);
end
else begin
$display ("%0d: ERROR: PLIC: interrupt completion to source that is not being serviced",
cur_cycle);
$display (" Completion message from target %0d to source %0d", target_id, source_id);
$display (" Ignoring");
bresp = SLVERR;
end
end
else
bresp = SLVERR;
if (target_id <= fromInteger (n_targets - 1)) begin
if ( (source_id <= fromInteger (n_sources))
&& vvrg_ie [target_id][source_id]) begin
vrg_source_busy [source_id] <= False;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: writing completion for target %0d for source 0x%0h",
cur_cycle, target_id, source_id);
end
else begin
if (cfg_verbosity > 0)
$display ("%0d: PLIC.rl_process_wr_req: ignoring completion for target %0d for source 0x%0h",
cur_cycle, target_id, source_id);
end
end
else
bresp = SLVERR;
end
else
bresp = SLVERR;
bresp = SLVERR;
if (bresp != OKAY) begin
$display ("%0d: ERROR: PLIC.rl_process_wr_req: unrecognized addr", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
$display ("%0d: ERROR: PLIC.rl_process_wr_req: unrecognized addr", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
end
// Send write-response to bus
let wrr = AXI4_BFlit {bid: wra.awid,
bresp: bresp,
buser: wra.awuser}; // XXX This requires that Wd_AW_User == Wd_B_User
slave_xactor.master.b.put(wrr);
bresp: bresp,
buser: wra.awuser}; // XXX This requires that Wd_AW_User == Wd_B_User
slavePortShim.master.b.put(wrr);
if (cfg_verbosity > 1) begin
$display ("%0d: PLIC.AXI4.rl_process_wr_req", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
$display (" ", fshow (wrr));
$display ("%0d: PLIC.AXI4.rl_process_wr_req", cur_cycle);
$display (" ", fshow (wra));
$display (" ", fshow (wrd));
$display (" ", fshow (wrr));
end
endrule: rl_process_wr_req
@@ -568,18 +549,18 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
function PLIC_Source_IFC fn_mk_PLIC_Source_IFC (Integer source_id);
return interface PLIC_Source_IFC;
method Action m_interrupt_req (Bool set_not_clear);
action
if (! vrg_source_busy [source_id + 1]) begin
vrg_source_ip [source_id + 1] <= set_not_clear;
method Action m_interrupt_req (Bool set_not_clear);
action
if (! vrg_source_busy [source_id + 1]) begin
vrg_source_ip [source_id + 1] <= set_not_clear;
if ((cfg_verbosity > 0) && (vrg_source_ip [source_id + 1] != set_not_clear))
$display ("%0d: %m.m_interrupt_req: changing vrg_source_ip [%0d] to %0d",
cur_cycle, source_id + 1, pack (set_not_clear));
end
endaction
endmethod
endinterface;
if ((cfg_verbosity > 0) && (vrg_source_ip [source_id + 1] != set_not_clear))
$display ("%0d: %m.m_interrupt_req: changing vrg_source_ip [%0d] to %0d",
cur_cycle, source_id + 1, pack (set_not_clear));
end
endaction
endmethod
endinterface;
endfunction
// ================================================================
@@ -587,12 +568,12 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
function PLIC_Target_IFC fn_mk_PLIC_Target_IFC (Integer target_id);
return interface PLIC_Target_IFC;
method Bool m_eip; // external interrupt pending
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (fromInteger (target_id));
Bool eip = (max_prio > vrg_target_threshold [target_id]);
return eip;
endmethod
endinterface;
method Bool m_eip; // external interrupt pending
match { .max_prio, .max_id } = fn_target_max_prio_and_max_id (fromInteger (target_id));
Bool eip = (max_prio > vrg_target_threshold [target_id]);
return eip;
endmethod
endinterface;
endfunction
// ================================================================
@@ -613,22 +594,22 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
// set_addr_map should be called after this module's reset
method Action set_addr_map (Bit #(64) addr_base, Bit #(64) addr_lim);
if (addr_base [1:0] != 0)
$display ("%0d: WARNING: PLIC.set_addr_map: addr_base 0x%0h is not 4-Byte-aligned",
cur_cycle, addr_base);
$display ("%0d: WARNING: PLIC.set_addr_map: addr_base 0x%0h is not 4-Byte-aligned",
cur_cycle, addr_base);
if (addr_lim [1:0] != 0)
$display ("%0d: WARNING: PLIC.set_addr_map: addr_lim 0x%0h is not 4-Byte-aligned",
cur_cycle, addr_lim);
$display ("%0d: WARNING: PLIC.set_addr_map: addr_lim 0x%0h is not 4-Byte-aligned",
cur_cycle, addr_lim);
rg_addr_base <= addr_base;
rg_addr_lim <= addr_lim;
if (cfg_verbosity > 0)
$display ("%0d: PLIC.set_addr_map: base 0x%0h limit 0x%0h", cur_cycle, addr_base, addr_lim);
$display ("%0d: PLIC.set_addr_map: base 0x%0h limit 0x%0h", cur_cycle, addr_base, addr_lim);
endmethod
// Memory-mapped access
interface axi4_slave = slave_xactor.slaveSynth;
interface axi4_slave = slavePortShim.slave;
// sources
interface v_sources = genWith (fn_mk_PLIC_Source_IFC);

View File

@@ -45,6 +45,26 @@ import Connectable::*;
import GetPut::*;
import ClientServer::*;
`ifdef PERFORMANCE_MONITORING
typedef struct {
Bit#(8) evt_LD;
Bit#(8) evt_LD_MISS;
Bit#(8) evt_LD_MISS_LAT;
Bit#(8) evt_ST;
Bit#(8) evt_ST_MISS; // Unimplemented
Bit#(8) evt_ST_MISS_LAT; // Unimplemented
Bit#(8) evt_AMO;
Bit#(8) evt_AMO_MISS;
Bit#(8) evt_AMO_MISS_LAT;
Bit#(8) evt_TLB;
Bit#(8) evt_TLB_MISS; // Only leaf is stored in TLB thus a full
Bit#(8) evt_TLB_MISS_LAT; // walk must happen every miss
Bit#(8) evt_TLB_FLUSH;
Bit#(8) evt_EVICT;
} EventsCache deriving (Bits, FShow);
typedef TDiv#(SizeOf#(EventsCache),8) EventsCacheElements;
`endif
typedef enum {
I = 2'd0,
S = 2'd1,

View File

@@ -57,6 +57,10 @@ import CacheUtils::*;
import Performance::*;
import LatencyTimer::*;
import RandomReplace::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import BlueUtils::*;
`endif
export ICRqStuck(..);
export IPRqStuck(..);
@@ -97,6 +101,9 @@ interface IBank#(
// performance
method Action setPerfStatus(Bool stats);
method Data getPerfData(L1IPerfType t);
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
module mkIBank#(
@@ -178,32 +185,50 @@ module mkIBank#(
Bool flushDone = True;
`endif
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer;
`ifdef PERF_COUNT
Reg#(Bool) doStats <- mkConfigReg(False);
Count#(Data) ldCnt <- mkCount(0);
Count#(Data) ldMissCnt <- mkCount(0);
Count#(Data) ldMissLat <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer;
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (2, unpack (0));
`endif
function Action incrReqCnt;
action
`ifdef PERF_COUNT
if(doStats) begin
ldCnt.incr(1);
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache events = unpack (0);
events.evt_LD = 1;
perf_events[0] <= events;
`endif
noAction;
endaction
endfunction
function Action incrMissCnt(cRqIdxT idx);
action
let lat <- latTimer.done(idx);
`ifdef PERF_COUNT
if(doStats) begin
ldMissLat.incr(zeroExtend(lat));
ldMissCnt.incr(1);
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache events = unpack (0);
events.evt_LD_MISS_LAT = saturating_truncate(lat);
events.evt_LD_MISS = 1;
perf_events[1] <= events;
`endif
noAction;
endaction
endfunction
`endif
function tagT getTag(Addr a) = truncateLSB(a);
@@ -227,10 +252,8 @@ module mkIBank#(
}));
// enq to indexQ for in order resp
cRqIndexQ.enq(n);
`ifdef PERF_COUNT
// performance counter: cRq type
incrReqCnt;
`endif
if (verbose)
$display("%t I %m cRqTransfer: ", $time,
fshow(n), " ; ",
@@ -377,10 +400,8 @@ module mkIBank#(
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
// performance counter: start miss timer
latTimer.start(n);
`endif
endrule
// last stage of pipeline: process req
@@ -617,10 +638,8 @@ module mkIBank#(
"pRs must be a hit"
);
cRqHit(cOwner, procRq);
`ifdef PERF_COUNT
// performance counter: miss cRq
incrMissCnt(cOwner);
`endif
end
else begin
doAssert(False, ("pRs owner must match some cRq"));
@@ -818,6 +837,9 @@ module mkIBank#(
default: 0;
endcase);
endmethod
`ifdef PERFORMANCE_MONITORING
method EventsCache events = perf_events[0];
`endif
endmodule

View File

@@ -60,6 +60,10 @@ import CrossBar::*;
import Performance::*;
import LatencyTimer::*;
import RandomReplace::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import BlueUtils::*;
`endif
export L1CRqStuck(..);
export L1PRqStuck(..);
@@ -103,6 +107,9 @@ interface L1Bank#(
// performance
method Action setPerfStatus(Bool stats);
method Data getPerfData(L1DPerfType t);
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
typedef struct {
@@ -191,6 +198,7 @@ module mkL1Bank#(
`endif
// performance
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
`ifdef PERF_COUNT
Reg#(Bool) doStats <- mkConfigReg(False);
Count#(Data) ldCnt <- mkCount(0);
@@ -202,43 +210,77 @@ module mkL1Bank#(
Count#(Data) ldMissLat <- mkCount(0);
Count#(Data) stMissLat <- mkCount(0);
Count#(Data) amoMissLat <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrReqCnt(MemOp op);
action
if(doStats) begin
case(op)
Ld: ldCnt.incr(1);
St: stCnt.incr(1);
Lr, Sc, Amo: amoCnt.incr(1);
endcase
end
endaction
endfunction
function Action incrMissCnt(MemOp op, cRqIdxT idx);
action
let lat <- latTimer.done(idx);
if(doStats) begin
case(op)
Ld: begin
ldMissLat.incr(zeroExtend(lat));
ldMissCnt.incr(1);
end
St: begin
stMissLat.incr(zeroExtend(lat));
stMissCnt.incr(1);
end
Lr, Sc, Amo: begin
amoMissLat.incr(zeroExtend(lat));
amoMissCnt.incr(1);
end
endcase
end
endaction
endfunction
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (2, unpack (0));
`endif
function Action incrReqCnt(MemOp op);
action
`ifdef PERF_COUNT
if(doStats) begin
case(op)
Ld: ldCnt.incr(1);
St: stCnt.incr(1);
Lr, Sc, Amo: amoCnt.incr(1);
endcase
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache events = unpack (0);
case(op)
Ld: events.evt_LD = 1;
St: events.evt_ST = 1;
Lr, Sc, Amo: events.evt_AMO = 1;
endcase
perf_events[0] <= events;
`endif
noAction;
endaction
endfunction
function Action incrMissCnt(MemOp op, cRqIdxT idx);
action
let lat <- latTimer.done(idx);
`ifdef PERF_COUNT
if(doStats) begin
case(op)
Ld: begin
ldMissLat.incr(zeroExtend(lat));
ldMissCnt.incr(1);
end
St: begin
stMissLat.incr(zeroExtend(lat));
stMissCnt.incr(1);
end
Lr, Sc, Amo: begin
amoMissLat.incr(zeroExtend(lat));
amoMissCnt.incr(1);
end
endcase
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache events = unpack (0);
case(op)
Ld: begin
events.evt_LD_MISS_LAT = saturating_truncate(lat);
events.evt_LD_MISS = 1;
end
St: begin
events.evt_ST_MISS_LAT = saturating_truncate(lat);
events.evt_ST_MISS = 1;
end
Lr, Sc, Amo: begin
events.evt_AMO_MISS_LAT = saturating_truncate(lat);
events.evt_AMO_MISS = 1;
end
endcase
perf_events[1] <= events;
`endif
noAction;
endaction
endfunction
function tagT getTag(Addr a) = truncateLSB(a);
@@ -274,10 +316,8 @@ module mkL1Bank#(
addr: r.addr,
mshrIdx: n
}));
`ifdef PERF_COUNT
// performance counter: cRq type
incrReqCnt(r.op);
`endif
if (verbose)
$display("%t L1 %m cRqTransfer_new: ", $time,
fshow(n), " ; ",
@@ -434,10 +474,8 @@ module mkL1Bank#(
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
// performance counter: start miss timer
latTimer.start(n);
`endif
endrule
// last stage of pipeline: process req
@@ -849,10 +887,8 @@ module mkL1Bank#(
("pRs must be a hit")
);
cRqHit(cOwner, procRq);
`ifdef PERF_COUNT
// performance counter: miss cRq
incrMissCnt(procRq.op, cOwner);
`endif
end
else begin
doAssert(False, ("pRs owner must match some cRq"));
@@ -1089,6 +1125,9 @@ module mkL1Bank#(
default: 0;
endcase);
endmethod
`ifdef PERFORMANCE_MONITORING
method EventsCache events = perf_events[0];
`endif
endmodule
@@ -1320,4 +1359,13 @@ module mkL1Cache#(
end
return fold(\+ , d);
endmethod
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
EventsCache ret = unpack(0);
for(Integer i = 0; i < valueof(bankNum); i = i+1) begin
ret = unpack(pack(ret) | pack(banks[i].events));
end
return ret;
endmethod
`endif
endmodule

View File

@@ -51,6 +51,10 @@ import LatencyTimer::*;
import Cntrs::*;
import ConfigReg::*;
import RandomReplace::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import BlueUtils::*;
`endif
export LLCRqStuck(..);
export LLBank(..);
@@ -102,6 +106,9 @@ interface LLBank#(
// performance
method Action setPerfStatus(Bool stats);
method Data getPerfData(LLCPerfType t);
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
typedef struct {
@@ -219,6 +226,7 @@ module mkLLBank#(
`endif
// performance
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
`ifdef PERF_COUNT
Reg#(Bool) doStats <- mkConfigReg(False);
Count#(Data) dmaMemLdCnt <- mkCount(0);
@@ -233,25 +241,34 @@ module mkLLBank#(
Count#(Data) upRespDataCnt <- mkCount(0);
Count#(Data) dmaLdReqCnt <- mkCount(0);
Count#(Data) dmaStReqCnt <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
action
let lat <- latTimer.done(idx);
if(doStats) begin
if(isDma) begin
dmaMemLdCnt.incr(1);
dmaMemLdLat.incr(zeroExtend(lat));
end
else begin
normalMemLdCnt.incr(1);
normalMemLdLat.incr(zeroExtend(lat));
end
end
endaction
endfunction
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (2, unpack (0));
`endif
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
action
let lat <- latTimer.done(idx);
`ifdef PERF_COUNT
if(doStats) begin
if(isDma) begin
dmaMemLdCnt.incr(1);
dmaMemLdLat.incr(zeroExtend(lat));
end
else begin
normalMemLdCnt.incr(1);
normalMemLdLat.incr(zeroExtend(lat));
end
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache events = unpack (0);
events.evt_LD_MISS_LAT = saturating_truncate(lat); // Don't support seperate DMA counts.
events.evt_LD_MISS = 1;
perf_events[1] <= events;
`endif
endaction
endfunction
function tagT getTag(Addr a) = truncateLSB(a);
@@ -515,10 +532,8 @@ module mkLLBank#(
fshow(cRq), " ; ",
fshow(cSlot), " ; "
);
`ifdef PERF_COUNT
// performance counter: normal miss lat and cnt
incrMissCnt(n, False);
`endif
endrule
// this mem resp is just for a DMA req, won't go into pipeline to refill cache
@@ -530,10 +545,8 @@ module mkLLBank#(
// save data into cRq mshr & send to DMA resp IndexQ
cRqMshr.mRsDeq.setData(mRs.id.mshrIdx, Valid (mRs.data));
rsLdToDmaIndexQ_mRsDeq.enq(mRs.id.mshrIdx);
`ifdef PERF_COUNT
// performance counter: dma miss lat and cnt
incrMissCnt(mRs.id.mshrIdx, True);
`endif
endrule
// send rd/wr to mem
@@ -572,10 +585,8 @@ module mkLLBank#(
$display("%t LL %m sendToM: load only: ", $time, fshow(msg));
doAssert(!isValid(data), "cannot have data");
doAssert(!doLdAfterReplace, "doLdAfterReplace should be false");
`ifdef PERF_COUNT
// performance counter: start miss timer
latTimer.start(n);
`endif
`ifdef DEBUG_DMA
if(cRq.id matches tagged Dma .dmaId) begin
dmaRdMissQ.enq(dmaId); // DMA read takes effect
@@ -619,10 +630,8 @@ module mkLLBank#(
doLdAfterReplace <= False;
if (verbose)
$display("%t LL %m sendToM: rep then ld: ld: ", $time, fshow(msg));
`ifdef PERF_COUNT
// performance counter: start miss timer
latTimer.start(n);
`endif
end
else begin // do write back part
toMemT msg = Wb (WbMemRs {
@@ -1531,6 +1540,9 @@ module mkLLBank#(
default: 0;
endcase);
endmethod
`ifdef PERFORMANCE_MONITORING
method EventsCache events = perf_events[0];
`endif
endmodule
// Scheduling notes
@@ -1593,4 +1605,3 @@ endmodule
// -- this cRq is different from that in mRsDeq
// -- this cRq is different from that in sendRsToC/sendRsToDma
// -- XXX this cRq may be the same as that in sendRqToC!!!

View File

@@ -43,6 +43,7 @@ import Vector::*;
import GetPut::*;
import Cntrs::*;
import ConfigReg::*;
import DReg::*;
import FIFO::*;
import FIFOF::*;
import Types::*;
@@ -161,6 +162,9 @@ interface CommitStage;
method Bool is_debug_halted;
method Action debug_resume;
`endif
`ifdef PERFORMANCE_MONITORING
method EventsCore events;
`endif
`ifdef DEBUG_WEDGE
(* always_enabled *)
method Tuple2#(CapMem, Bit#(32)) debugLastInst;
@@ -410,6 +414,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
Count#(Data) flushCacheCnt <- mkCount(0);
`endif
`ifdef PERFORMANCE_MONITORING
Reg#(EventsCore) events_reg <- mkDReg(unpack(0));
`endif
`ifdef RVFI
// RVFI trace report. Not an input?
FIFO#(Rvfi_Traces) rvfiQ <- mkFIFO;
@@ -695,7 +703,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
end
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCore events = unpack(0);
events.evt_TRAP = 1;
events_reg <= events;
`endif
// checks
doAssert(x.rob_inst_state == Executed, "must be executed");
doAssert(x.spec_bits == 0, "cannot have spec bits");
@@ -988,6 +1000,13 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
end
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCore events = unpack(0);
case(x.iType)
Fence, FenceI, SFence: events.evt_FENCE = 1;
endcase
events_reg <= events;
`endif
`ifdef CHECK_DEADLOCK
commitInst.send;
if(csrf.decodeInfo.prv == 0) begin
@@ -1060,7 +1079,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// incr committed inst cnt at the end of rule
SupCnt comInstCnt = 0;
SupCnt comUserInstCnt = 0;
`ifdef PERF_COUNT
// incr some performance counter at the end of rule
SupCnt brCnt = 0;
SupCnt jmpCnt = 0;
@@ -1070,7 +1088,14 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
SupCnt lrCnt = 0;
SupCnt scCnt = 0;
SupCnt amoCnt = 0;
`endif
SupCnt shiftCnt = 0;
SupCnt muldivCnt = 0;
SupCnt auipcCnt = 0;
SupCnt fenceCnt = 0;
SupCnt fpuCnt = 0;
// CHERI-specific counters
SupCnt ldCapCnt = 0;
SupCnt stCapCnt = 0;
`ifdef RVFI
Rvfi_Traces rvfis = replicate(tagged Invalid);
@@ -1170,19 +1195,45 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
comUserInstCnt = comUserInstCnt + 1; // user space inst
end
`ifdef PERF_COUNT
// performance counter
// performance counters
// Some fields of the original instruction to help with classification.
let inst = x.orig_inst;
Opcode opcode = unpackOpcode(inst[ 6 : 0 ]);
let funct3 = inst[ 14 : 12 ];
let funct7 = inst[ 31 : 25 ];
// For "F" and "D" ISA extensions
let funct5 = inst[ 31 : 27 ];
let fmt = inst[ 26 : 25 ];
let rs3 = inst[ 31 : 27 ];
let funct2 = inst[ 26 : 25 ];
// For "A" ISA extension
Bool aq = unpack(inst[ 26 ]);
Bool rl = unpack(inst[ 25 ]);
// For "xCHERI" ISA extension
let funct5rs2 = inst[ 24 : 20 ];
case(x.iType)
Auipc, Auipcc: auipcCnt = auipcCnt + 1;
Br: brCnt = brCnt + 1;
J : jmpCnt = jmpCnt + 1;
Jr: jrCnt = jrCnt + 1;
Ld: ldCnt = ldCnt + 1;
St: stCnt = stCnt + 1;
Ld: begin
ldCnt = ldCnt + 1;
end
St: begin
stCnt = stCnt + 1;
end
Lr: lrCnt = lrCnt + 1;
Sc: scCnt = scCnt + 1;
Amo: amoCnt = amoCnt + 1;
Fpu: fpuCnt = fpuCnt + 1;
Alu: begin
if (((opcode == opcOpImm) || (opcode == opcOpImm32) || (opcode == opcOp)) && ((funct3 == fnSLL) || (funct3 == fnSR)))
shiftCnt = shiftCnt + 1;
if ((opcode == opcOp || opcode == opcOp32) && funct7 == opMULDIV)
muldivCnt = muldivCnt + 1;
end
endcase
`endif
if (opcode == opcMiscMem && funct3 == fnFENCE) fenceCnt = fenceCnt + 1;
end
end
end
@@ -1235,6 +1286,23 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
end
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCore events = unpack(0);
events.evt_BRANCH = brCnt;
events.evt_JAL = jmpCnt;
events.evt_JALR = jrCnt;
events.evt_AUIPC = auipcCnt; // XXX
events.evt_LOAD = ldCnt;
events.evt_STORE = stCnt;
events.evt_LR = lrCnt;
events.evt_SC = scCnt;
events.evt_AMO = amoCnt;
events.evt_SERIAL_SHIFT = shiftCnt;
events.evt_INT_MUL_DIV_REM = muldivCnt;
events.evt_FP = fpuCnt;
events.evt_FENCE = fenceCnt;
events_reg <= events;
`endif
`ifdef RVFI
rvfiQ.enq(rvfis);
traceCnt <= traceCnt + zeroExtend(whichTrace);
@@ -1309,6 +1377,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
endmethod
`endif
`ifdef PERFORMANCE_MONITORING
method events = events_reg;
`endif
`ifdef DEBUG_WEDGE
method Tuple2#(CapMem, Bit#(32)) debugLastInst;
return tuple2(rg_last_pcc, rg_last_inst);

View File

@@ -68,6 +68,11 @@ import LatencyTimer::*;
import CHERICap::*;
import CHERICC_Fat::*;
import ISA_Decls_CHERI::*;
import CacheUtils::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import BlueUtils::*;
`endif
import Cur_Cycle :: *;
@@ -228,6 +233,9 @@ interface MemExePipeline;
interface Server#(void, void) reconcile;
`endif
method Data getPerf(ExeStagePerfType t);
`ifdef PERFORMANCE_MONITORING
method EventsCoreMem events;
`endif
endinterface
module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
@@ -237,6 +245,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// is not good with single core
Bool multicore = valueof(CoreNum) > 1;
// load/store memory total latency (max 1K cycle latency for 1 Ld/St)
// These are always included as they are used by both stat counter systems.
LatencyTimer#(LdQSize, 10) ldMemLatTimer <- mkLatencyTimer;
LatencyTimer#(SBSize, 10) stMemLatTimer <- mkLatencyTimer;
`ifdef PERF_COUNT
// load issue stall
Count#(Data) exeLdStallByLdCnt <- mkCount(0);
@@ -245,8 +257,6 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// load forward count
Count#(Data) exeLdForwardCnt <- mkCount(0);
// load/store memory total latency (max 1K cycle latency for 1 Ld/St)
LatencyTimer#(LdQSize, 10) ldMemLatTimer <- mkLatencyTimer;
LatencyTimer#(SBSize, 10) stMemLatTimer <- mkLatencyTimer;
Count#(Data) exeLdMemLat <- mkCount(0);
Count#(Data) exeStMemLat <- mkCount(0);
// load to use latency: dispatch to resp
@@ -265,6 +275,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
Count#(Data) exeFenceRelCnt <- mkCount(0);
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCoreMem)) events_reg <- mkDRegOR (5, unpack (0));
`endif
// reservation station
ReservationStationMem rsMem <- mkReservationStationMem;
@@ -324,12 +338,18 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
if(verbose) begin
$display("%t : [Ld resp] ", $time, fshow(id), "; ", fshow(d), "; ", fshow(info));
end
`ifdef PERF_COUNT
// perf: load mem latency
let lat <- ldMemLatTimer.done(tag);
`ifdef PERF_COUNT
if(inIfc.doStats) begin
exeLdMemLat.incr(zeroExtend(lat));
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
events.evt_LOAD_WAIT = saturating_truncate(lat);
events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1 : 0;
events_reg[1] <= events;
`endif
endmethod
method Action respLrScAmo(DProcReqId id, MemTaggedData d);
@@ -346,18 +366,24 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
$display("[Store resp] idx ", fshow(id),
", ", fshow(waitSt));
end
`ifdef PERF_COUNT
// perf: store mem latency
let lat <- stMemLatTimer.done(0);
`ifdef PERF_COUNT
if(inIfc.doStats) begin
exeStMemLat.incr(zeroExtend(lat));
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1;
events.evt_STORE_WAIT = saturating_truncate(lat);
events_reg[2] <= events;
`endif
// now figure out the data to be written
Vector#(LineSzData, ByteEn) be = replicate(replicate(False));
Line data = replicate(0);
be[waitSt.offset] = waitSt.shiftedBE;
data[waitSt.offset] = waitSt.shiftedData;
data[waitSt.offset] = waitSt.shiftedData; //XXX I guess this doesn't work with capabilities? Maybe we don't build TSO?
return tuple2(unpack(pack(be)), data);
endmethod
`else
@@ -366,12 +392,18 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
let e <- stb.deq(idx); // deq SB
lsq.wakeupLdStalledBySB(idx); // wake up loads
if(verbose) $display("[Store resp] idx = %x, ", idx, fshow(e));
`ifdef PERF_COUNT
// perf: store mem latency
let lat <- stMemLatTimer.done(idx);
`ifdef PERF_COUNT
if(inIfc.doStats) begin
exeStMemLat.incr(zeroExtend(lat));
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1;
events.evt_STORE_WAIT = saturating_truncate(lat);
events_reg[2] <= events;
`endif
return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry
endmethod
@@ -510,6 +542,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
if(x.ldstq_tag matches tagged St .stTag) begin
MemTaggedData d = x.mem_func == Amo ? toMemData : shiftData; // XXX don't shift for AMO
lsq.updateData(stTag, d);
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
events.evt_MEM_CAP_STORE_TAG_SET = (d.tag) ? 1 : 0;
events_reg[4] <= events;
`endif
end
CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC));
@@ -672,6 +709,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
};
`else
SBSearchRes sbRes = stb.search(info.paddr, info.shiftedBE);
`endif
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
if (pack(info.shiftedBE) == -1) events.evt_MEM_CAP_LOAD = 1;
`endif
// search LSQ
LSQIssueLdResult issRes <- lsq.issueLd(info.tag, info.paddr, info.shiftedBE, sbRes);
@@ -695,10 +736,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
end
else if(issRes == ToCache) begin
reqLdQ.enq(tuple2(zeroExtend(info.tag), info.paddr));
`ifdef PERF_COUNT
// perf: load mem latency
ldMemLatTimer.start(info.tag);
`endif
end
else if(issRes matches tagged Stall .stallBy) begin
`ifdef PERF_COUNT
@@ -716,6 +755,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
else begin
doAssert(False, "load is stalled");
end
`ifdef PERFORMANCE_MONITORING
events_reg[0] <= events;
`endif
endaction
endfunction
@@ -1096,10 +1138,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// we leave deq to resp time
// ROB should have already been set to executed
if(verbose) $display("[doDeqStQ_St] ", fshow(lsqDeqSt));
`ifdef PERF_COUNT
// perf: store mem latency
stMemLatTimer.start(0);
`endif
endrule
`else
@@ -1123,10 +1163,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
rule doIssueSB;
let {sbIdx, en} <- stb.issue;
reqStQ.enq(tuple2(sbIdx, {en.addr, 0}));
`ifdef PERF_COUNT
// perf: store mem latency
stMemLatTimer.start(sbIdx);
`endif
endrule
`endif
@@ -1286,6 +1324,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
if(inIfc.doStats && lsqDeqSt.memFunc == Sc && resp == fromInteger(valueof(ScSuccVal))) begin
exeScSuccessCnt.incr(1);
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCoreMem events = unpack(0);
events.evt_SC_SUCCESS = 1;
events_reg[3] <= events;
`endif
endrule
@@ -1518,4 +1561,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
default: 0;
endcase);
endmethod
`ifdef PERFORMANCE_MONITORING
method events = events_reg[0];
`endif
endmodule

View File

@@ -37,6 +37,101 @@
`CSR(MIP, 12'h344)
`CSR(MCYCLE, 12'hb00)
`CSR(MINSTRET, 12'hb02)
`ifdef PERFORMANCE_MONITORING
`CSR(HPMCOUNTER3, 12'hc03)
`CSR(HPMCOUNTER4, 12'hc04)
`CSR(HPMCOUNTER5, 12'hc05)
`CSR(HPMCOUNTER6, 12'hc06)
`CSR(HPMCOUNTER7, 12'hc07)
`CSR(HPMCOUNTER8, 12'hc08)
`CSR(HPMCOUNTER9, 12'hc09)
`CSR(HPMCOUNTER10, 12'hc0a)
`CSR(HPMCOUNTER11, 12'hc0b)
`CSR(HPMCOUNTER12, 12'hc0c)
`CSR(HPMCOUNTER13, 12'hc0d)
`CSR(HPMCOUNTER14, 12'hc0e)
`CSR(HPMCOUNTER15, 12'hc0f)
`CSR(HPMCOUNTER16, 12'hc10)
`CSR(HPMCOUNTER17, 12'hc11)
`CSR(HPMCOUNTER18, 12'hc12)
`CSR(HPMCOUNTER19, 12'hc13)
`CSR(HPMCOUNTER20, 12'hc14)
`CSR(HPMCOUNTER21, 12'hc15)
`CSR(HPMCOUNTER22, 12'hc16)
`CSR(HPMCOUNTER23, 12'hc17)
`CSR(HPMCOUNTER24, 12'hc18)
`CSR(HPMCOUNTER25, 12'hc19)
`CSR(HPMCOUNTER26, 12'hc1a)
`CSR(HPMCOUNTER27, 12'hc1b)
`CSR(HPMCOUNTER28, 12'hc1c)
`CSR(HPMCOUNTER29, 12'hc1d)
`CSR(HPMCOUNTER30, 12'hc1e)
`CSR(HPMCOUNTER31, 12'hc1f)
`CSR(MHPMCOUNTER3, 12'hb03)
`CSR(MHPMCOUNTER4, 12'hb04)
`CSR(MHPMCOUNTER5, 12'hb05)
`CSR(MHPMCOUNTER6, 12'hb06)
`CSR(MHPMCOUNTER7, 12'hb07)
`CSR(MHPMCOUNTER8, 12'hb08)
`CSR(MHPMCOUNTER9, 12'hb09)
`CSR(MHPMCOUNTER10, 12'hb0a)
`CSR(MHPMCOUNTER11, 12'hb0b)
`CSR(MHPMCOUNTER12, 12'hb0c)
`CSR(MHPMCOUNTER13, 12'hb0d)
`CSR(MHPMCOUNTER14, 12'hb0e)
`CSR(MHPMCOUNTER15, 12'hb0f)
`CSR(MHPMCOUNTER16, 12'hb10)
`CSR(MHPMCOUNTER17, 12'hb11)
`CSR(MHPMCOUNTER18, 12'hb12)
`CSR(MHPMCOUNTER19, 12'hb13)
`CSR(MHPMCOUNTER20, 12'hb14)
`CSR(MHPMCOUNTER21, 12'hb15)
`CSR(MHPMCOUNTER22, 12'hb16)
`CSR(MHPMCOUNTER23, 12'hb17)
`CSR(MHPMCOUNTER24, 12'hb18)
`CSR(MHPMCOUNTER25, 12'hb19)
`CSR(MHPMCOUNTER26, 12'hb1a)
`CSR(MHPMCOUNTER27, 12'hb1b)
`CSR(MHPMCOUNTER28, 12'hb1c)
`CSR(MHPMCOUNTER29, 12'hb1d)
`CSR(MHPMCOUNTER30, 12'hb1e)
`CSR(MHPMCOUNTER31, 12'hb1f)
`CSR(MCOUNTERINHIBIT, 12'h320) // Machine Counter-Inhibit
`CSR(MHPMEVENT3, 12'h323)
`CSR(MHPMEVENT4, 12'h324)
`CSR(MHPMEVENT5, 12'h325)
`CSR(MHPMEVENT6, 12'h326)
`CSR(MHPMEVENT7, 12'h327)
`CSR(MHPMEVENT8, 12'h328)
`CSR(MHPMEVENT9, 12'h329)
`CSR(MHPMEVENT10, 12'h32a)
`CSR(MHPMEVENT11, 12'h32b)
`CSR(MHPMEVENT12, 12'h32c)
`CSR(MHPMEVENT13, 12'h32d)
`CSR(MHPMEVENT14, 12'h32e)
`CSR(MHPMEVENT15, 12'h32f)
`CSR(MHPMEVENT16, 12'h330)
`CSR(MHPMEVENT17, 12'h331)
`CSR(MHPMEVENT18, 12'h332)
`CSR(MHPMEVENT19, 12'h333)
`CSR(MHPMEVENT20, 12'h334)
`CSR(MHPMEVENT21, 12'h335)
`CSR(MHPMEVENT22, 12'h336)
`CSR(MHPMEVENT23, 12'h337)
`CSR(MHPMEVENT24, 12'h338)
`CSR(MHPMEVENT25, 12'h339)
`CSR(MHPMEVENT26, 12'h33a)
`CSR(MHPMEVENT27, 12'h33b)
`CSR(MHPMEVENT28, 12'h33c)
`CSR(MHPMEVENT29, 12'h33d)
`CSR(MHPMEVENT30, 12'h33e)
`CSR(MHPMEVENT31, 12'h33f)
`endif // PERFORMANCE_MONITORING
`CSR(MVENDORID, 12'hf11)
`CSR(MARCHID, 12'hf12)
`CSR(MIMPID, 12'hf13)

View File

@@ -13,7 +13,7 @@
//
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
//-
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -21,10 +21,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -52,6 +52,11 @@ import LatencyTimer::*;
import HasSpecBits::*;
import Vector::*;
import Ehr::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import CCTypes::*;
import BlueUtils::*;
`endif
export DTlbReq(..);
export DTlbResp(..);
@@ -86,7 +91,7 @@ typedef struct {
typedef struct {
// may get page fault: i.e. hit invalid page or
// get non-leaf page at last-level page table
Maybe#(TlbEntry) entry;
Maybe#(TlbEntry) entry;
DTlbReqIdx id;
} DTlbTransRsFromP deriving(Bits, Eq, FShow);
@@ -117,6 +122,9 @@ interface DTlb#(type instT);
// performance
interface Perf#(L1TlbPerfType) perf;
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
typedef FullAssocTlb#(DTlbSize) DTlbArray;
@@ -199,6 +207,7 @@ module mkDTlb#(
Fifo#(1, void) flushRsFromPQ <- mkCFFifo;
// perf counters
LatencyTimer#(DTlbReqNum, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
`ifdef PERF_COUNT
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
@@ -211,8 +220,6 @@ module mkDTlb#(
Count#(Data) hitUnderMissCnt <- mkCount(0);
Count#(Data) allMissCycles <- mkCount(0);
LatencyTimer#(DTlbReqNum, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
rule doPerf;
let t <- toGet(perfReqQ).get;
Data d = (case(t)
@@ -236,6 +243,9 @@ module mkDTlb#(
when(all(isMiss, readVReg(pendWait)), allMissCycles.incr(1));
endrule
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (3, unpack (0));
`endif
// do flush: start when all misses resolve
Bool noMiss = all(\== (False) , readVReg(pendValid_noMiss));
@@ -246,6 +256,11 @@ module mkDTlb#(
flushRqToPQ.enq(?);
waitFlushP <= True;
if(verbose) $display("[DTLB] flush begin");
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB_FLUSH = 1;
perf_events[2] <= ev;
`endif
endrule
rule doFinishFlush(needFlush && waitFlushP);
@@ -333,9 +348,9 @@ module mkDTlb#(
ldTransRsFromPQ.deq;
end
`ifdef PERF_COUNT
// perf: miss
let lat <- latTimer.done(idx);
`ifdef PERF_COUNT
if(doStats) begin
if(isValid(respForOtherReq)) begin
missPeerLat.incr(zeroExtend(lat));
@@ -347,7 +362,12 @@ module mkDTlb#(
end
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
ev.evt_TLB_MISS = 1;
perf_events[0] <= ev;
`endif
// conflict with wrong spec
wrongSpec_doPRs_conflict.wset(?);
endrule
@@ -516,10 +536,8 @@ module mkDTlb#(
idx, fshow(r));
end
end
`ifdef PERF_COUNT
// perf: miss
latTimer.start(idx);
`endif
end
end
else begin
@@ -534,6 +552,11 @@ module mkDTlb#(
if(doStats) begin
accessCnt.incr(1);
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB = 1;
perf_events[1] <= ev;
`endif
// conflict with wrong spec
wrongSpec_procReq_conflict.wset(?);
@@ -623,4 +646,7 @@ module mkDTlb#(
`endif
endmethod
endinterface
`ifdef PERFORMANCE_MONITORING
method EventsCache events = perf_events[0];
`endif
endmodule

View File

@@ -515,17 +515,17 @@ function Maybe#(Trap) checkForException(
Bool writes_csr = ((dInst.execFunc == tagged Alu Csrw) || (rs1 != 0) || (imm != 0));
Bool read_only = (csr [11:10] == 2'b11);
Bool write_deny = (writes_csr && read_only);
Bool asr_deny = !getHardPerms(pcc).accessSysRegs && !(
//((csr_addr_hpmcounter3 <= csr) && (csr <= csr_addr_hpmcounter31) && writes_csr) // TODO seems these aren't implemented?
(csr == pack(csrAddrFFLAGS))
|| (csr == pack(csrAddrFRM))
|| (csr == pack(csrAddrFCSR))
|| (csr == pack(csrAddrCYCLE) && writes_csr)
|| (csr == pack(csrAddrINSTRET) && writes_csr));
Bool asr_allow = getHardPerms(pcc).accessSysRegs
//|| ((csr_addr_hpmcounter3 <= csr) && (csr <= csr_addr_hpmcounter31) && !writes_csr) // TODO seems these aren't implemented?
|| (csr == pack(csrAddrFFLAGS))
|| (csr == pack(csrAddrFRM))
|| (csr == pack(csrAddrFCSR))
|| (csr == pack(csrAddrCYCLE) && !writes_csr)
|| (csr == pack(csrAddrINSTRET) && !writes_csr);
Bool unimplemented = (csr == pack(csrAddrNone)); // Added by Bluespec
if (write_deny || !csr_has_priv || unimplemented) begin
exception = Valid (Exception (excIllegalInst));
end else if (asr_deny) begin
end else if (!asr_allow) begin
exception = Valid (CapException (CSR_XCapCause {cheri_exc_reg: {1'b1, pack(scrAddrPCC)}, cheri_exc_code: cheriExcPermitASRViolation}));
end
end
@@ -535,11 +535,11 @@ function Maybe#(Trap) checkForException(
Bool writes_scr = regs.src1 == Valid (tagged Gpr 0) ? False : True;
Bool read_only = (scr == scrAddrPCC);
Bool write_deny = (writes_scr && read_only);
Bool asr_deny = !getHardPerms(pcc).accessSysRegs && !(
scr == scrAddrDDC || scr == scrAddrPCC);
Bool asr_allow = getHardPerms(pcc).accessSysRegs ||
scr == scrAddrDDC || scr == scrAddrPCC;
if(!scr_has_priv || unimplemented || write_deny) begin
exception = Valid (Exception (excIllegalInst));
end else if (asr_deny) begin
end else if (!asr_allow) begin
exception = Valid (CapException (CSR_XCapCause {cheri_exc_reg: {1'b1, pack(scrAddrPCC)}, cheri_exc_code: cheriExcPermitASRViolation}));
end
end

View File

@@ -13,7 +13,7 @@
//
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
//-
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -21,10 +21,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -49,6 +49,11 @@ import Cntrs::*;
import SafeCounter::*;
import CacheUtils::*;
import LatencyTimer::*;
`ifdef PERFORMANCE_MONITORING
import PerformanceMonitor::*;
import CCTypes::*;
import BlueUtils::*;
`endif
// currently blocking
typedef `L1_TLB_SIZE ITlbSize;
@@ -60,7 +65,7 @@ typedef struct {
typedef struct {
// may get page fault: i.e. hit invalid page or
// get non-leaf page at last-level page table
Maybe#(TlbEntry) entry;
Maybe#(TlbEntry) entry;
} ITlbRsFromP deriving(Bits, Eq, FShow);
interface ITlbToParent;
@@ -85,6 +90,9 @@ interface ITlb;
// performance
interface Perf#(L1TlbPerfType) perf;
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
typedef FullAssocTlb#(ITlbSize) ITlbArray;
@@ -122,6 +130,7 @@ module mkITlb(ITlb::ITlb);
Fifo#(1, void) flushRsFromPQ <- mkCFFifo;
// perf counters
LatencyTimer#(2, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
`ifdef PERF_COUNT
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
@@ -130,8 +139,6 @@ module mkITlb(ITlb::ITlb);
Count#(Data) missCnt <- mkCount(0);
Count#(Data) missLat <- mkCount(0);
LatencyTimer#(2, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
rule doPerf;
let t <- toGet(perfReqQ).get;
Data d = (case(t)
@@ -146,6 +153,9 @@ module mkITlb(ITlb::ITlb);
});
endrule
`endif
`ifdef PERFORMANCE_MONITORING
Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (3, unpack (0));
`endif
// do flush: only start when all misses resolve
rule doStartFlush(needFlush && !waitFlushP && !isValid(miss));
@@ -154,6 +164,11 @@ module mkITlb(ITlb::ITlb);
flushRqToPQ.enq(?);
waitFlushP <= True;
if(verbose) $display("ITLB %m: flush begin");
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB_FLUSH = 1;
perf_events[2] <= ev;
`endif
endrule
rule doFinishFlush(needFlush && waitFlushP && !isValid(miss));
@@ -172,7 +187,7 @@ module mkITlb(ITlb::ITlb);
// search TLB to check whether the PTE is already in TLB; this may
// happen for mega/giga pages. We don't want same PTE to occupy >1
// TLB entires.
// check permission
if(hasVMPermission(vm_info,
en.pteType,
@@ -206,11 +221,17 @@ module mkITlb(ITlb::ITlb);
// miss resolved
miss <= Invalid;
`ifdef PERF_COUNT
let lat <- latTimer.done(0);
`ifdef PERF_COUNT
if(doStats) begin
missLat.incr(zeroExtend(lat));
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
ev.evt_TLB_MISS = 1;
perf_events[0] <= ev;
`endif
endrule
@@ -320,8 +341,8 @@ module mkITlb(ITlb::ITlb);
if(verbose) begin
$display("ITLB %m req (miss): ", fshow(vaddr));
end
`ifdef PERF_COUNT
latTimer.start(0);
`ifdef PERF_COUNT
if(doStats) begin
missCnt.incr(1);
end
@@ -338,6 +359,11 @@ module mkITlb(ITlb::ITlb);
if(doStats) begin
accessCnt.incr(1);
end
`endif
`ifdef PERFORMANCE_MONITORING
EventsCache ev = unpack(0);
ev.evt_TLB = 1;
perf_events[1] <= ev;
`endif
endmethod
endinterface
@@ -387,4 +413,7 @@ module mkITlb(ITlb::ITlb);
`endif
endmethod
endinterface
`ifdef PERFORMANCE_MONITORING
method EventsCache events = perf_events[0];
`endif
endmodule

View File

@@ -178,6 +178,9 @@ interface DCoCache;
method Bool flush_done;
method Action resetLinkAddr;
interface Perf#(L1DPerfType) perf;
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
interface ChildCacheToParent#(L1Way, void) to_parent;
@@ -267,6 +270,9 @@ module mkDCoCache#(L1ProcResp#(DProcReqId) procResp)(DCoCache);
`endif
endmethod
endinterface
`ifdef PERFORMANCE_MONITORING
method EventsCache events = cache.events;
`endif
interface to_parent = cache.to_parent;
@@ -366,6 +372,9 @@ interface ICoCache;
method Action flush;
method Bool flush_done;
interface Perf#(L1IPerfType) perf;
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
interface ChildCacheToParent#(L1Way, void) to_parent;
@@ -436,6 +445,9 @@ module mkICoCache(ICoCache);
`endif
endmethod
endinterface
`ifdef PERFORMANCE_MONITORING
method EventsCache events = cache.events;
`endif
interface to_parent = cache.to_parent;

View File

@@ -131,9 +131,9 @@ module mkLLCDmaConnect #(
DmaServer#(LLCDmaReqId) llc,
// MemLoaderMemClient memLoader, // REPLACED BY AXI4_Slave_interface
Vector#(CoreNum, TlbMemClient) tlb
)(AXI4_Slave_Synth #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User)) provisos (
)(AXI4_Slave #(Wd_SId_2x3, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User)) provisos (
Alias#(dmaRqT, DmaRq#(LLCDmaReqId))
);
Bool verbose = False;
@@ -143,8 +143,8 @@ module mkLLCDmaConnect #(
// When debugger reads a word, request a line from LLC, and remember dword-in-line here
FIFOF #(Bit #(3)) f_dword_in_line <- mkFIFOF;
// Slave transactor for requests from Debug Module
let axi4_slave_xactor <- mkAXI4_Slave_Xactor;
// Connector to AXI4 fabric
let slavePortShim <- mkAXI4ShimFF;
// ================================================================
// These regs are a 1-location local cache for an LLC Cache Line,
@@ -163,10 +163,10 @@ module mkLLCDmaConnect #(
// Respond to store-requests from the external client on store-hit
rule rl_handle_MemLoader_st_req ( ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
|| (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY))
&& (fn_addr_is_in_line (axi4_slave_xactor.master.aw.peek.awaddr,
&& (fn_addr_is_in_line (slavePortShim.master.aw.peek.awaddr,
rg_cacheline_cache_addr)));
let wr_addr <- get (axi4_slave_xactor.master.aw);
let wr_data <- get (axi4_slave_xactor.master.w);
let wr_addr <- get (slavePortShim.master.aw);
let wr_data <- get (slavePortShim.master.w);
// Modify relevant bytes of relevant dword
let newLine = setDataAtBE( rg_cacheline_cache_data
@@ -178,7 +178,7 @@ module mkLLCDmaConnect #(
rg_cacheline_cache_dirty_delay <= '1; // start write-back delay countdown
// Send response to external client
axi4_slave_xactor.master.b.put(AXI4_BFlit{
slavePortShim.master.b.put(AXI4_BFlit{
bid: wr_addr.awid, // TODO: change uniformly to Fabric_id
bresp: OKAY,
buser: ?
@@ -198,14 +198,14 @@ module mkLLCDmaConnect #(
// Responds to load-requests from the external client on load-hit
rule rl_handle_MemLoader_ld_req ( ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
|| (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY))
&& (fn_addr_is_in_line (axi4_slave_xactor.master.ar.peek.araddr,
&& (fn_addr_is_in_line (slavePortShim.master.ar.peek.araddr,
rg_cacheline_cache_addr)));
let rd_addr <- get (axi4_slave_xactor.master.ar);
let rd_addr <- get (slavePortShim.master.ar);
let dword = getDataAt( rg_cacheline_cache_data
, getCLineDataSel(rd_addr.araddr));
// Send response to external client
axi4_slave_xactor.master.r.put(AXI4_RFlit{
slavePortShim.master.r.put(AXI4_RFlit{
rid: rd_addr.arid,
rdata: dword,
rresp: OKAY,
@@ -255,12 +255,12 @@ module mkLLCDmaConnect #(
// Initiate writeback if dirty and next request is store-miss
rule rl_cacheline_cache_writeback_st_miss ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (! fn_addr_is_in_line (axi4_slave_xactor.master.aw.peek.awaddr,
&& (! fn_addr_is_in_line (slavePortShim.master.aw.peek.awaddr,
rg_cacheline_cache_addr)));
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_st_miss.", cur_cycle);
$display (" Old line addr %0h", rg_cacheline_cache_addr);
$display (" New addr %0h", axi4_slave_xactor.master.aw.peek.awaddr);
$display (" New addr %0h", slavePortShim.master.aw.peek.awaddr);
end
fa_writeback;
@@ -269,12 +269,12 @@ module mkLLCDmaConnect #(
// Initiate writeback if dirty and next request is load-miss
rule rl_cacheline_cache_writeback_ld_miss ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (! fn_addr_is_in_line (axi4_slave_xactor.master.ar.peek.araddr,
&& (! fn_addr_is_in_line (slavePortShim.master.ar.peek.araddr,
rg_cacheline_cache_addr)));
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_ld_miss.", cur_cycle);
$display (" Old line addr %0h", rg_cacheline_cache_addr);
$display (" New addr %0h", axi4_slave_xactor.master.aw.peek.awaddr);
$display (" New addr %0h", slavePortShim.master.aw.peek.awaddr);
end
fa_writeback;
@@ -313,9 +313,9 @@ module mkLLCDmaConnect #(
// Initiate reload when cacheline_cache is clean on store-miss
rule rl_cacheline_cache_reload_req_st ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
&& (! fn_addr_is_in_line (axi4_slave_xactor.master.aw.peek.awaddr,
&& (! fn_addr_is_in_line (slavePortShim.master.aw.peek.awaddr,
rg_cacheline_cache_addr)));
let addr = axi4_slave_xactor.master.aw.peek.awaddr;
let addr = slavePortShim.master.aw.peek.awaddr;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_reload_req_st for addr %0h", cur_cycle, addr);
@@ -327,9 +327,9 @@ module mkLLCDmaConnect #(
// Initiate reload when cacheline_cache is clean on load-miss
rule rl_cacheline_cache_reload_req_ld ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
&& (! fn_addr_is_in_line (axi4_slave_xactor.master.ar.peek.araddr,
&& (! fn_addr_is_in_line (slavePortShim.master.ar.peek.araddr,
rg_cacheline_cache_addr)));
let addr = axi4_slave_xactor.master.ar.peek.araddr;
let addr = slavePortShim.master.ar.peek.araddr;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_reload_req_ld for addr %0h", cur_cycle, addr);
@@ -424,5 +424,5 @@ module mkLLCDmaConnect #(
// ================================================================
// INTERFACE
return axi4_slave_xactor.slaveSynth;
return slavePortShim.slave;
endmodule

View File

@@ -13,7 +13,7 @@
//
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
//-
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -21,10 +21,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -254,6 +254,9 @@ interface LLCache;
interface Get#(LLCStuck) cRqStuck;
// performance
interface Perf#(LLCPerfType) perf;
`ifdef PERFORMANCE_MONITORING
method EventsCache events;
`endif
endinterface
`ifdef SECURITY
@@ -462,4 +465,7 @@ module mkLLCache(LLCache);
`endif
endmethod
endinterface
`ifdef PERFORMANCE_MONITORING
method EventsCache events = cache.events;
`endif
endmodule

View File

@@ -50,7 +50,6 @@ import ISA_Decls_CHERI::*;
import GetPut::*;
import RVFI_DII_Types::*;
`endif
import ISA_Decls_CHERI::*;
typedef `NUM_CORES CoreNum;
typedef Bit#(TLog#(CoreNum)) CoreId;
@@ -1040,3 +1039,77 @@ function Fmt showInst(Instruction inst);
endfunction
function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERICap#(x, a, b, c, d, e)) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
`ifdef PERFORMANCE_MONITORING
typedef 128 No_Of_Evts;
typedef 8 Report_Width;
typedef 64 Counter_Width;
typedef 29 No_Of_Ctrs;
typedef struct {
SupCnt evt_REDIRECT;
SupCnt evt_TRAP;
SupCnt evt_BRANCH;
SupCnt evt_JAL;
SupCnt evt_JALR;
SupCnt evt_AUIPC;
SupCnt evt_LOAD;
SupCnt evt_STORE;
SupCnt evt_LR;
SupCnt evt_SC;
SupCnt evt_AMO;
SupCnt evt_SERIAL_SHIFT;
SupCnt evt_INT_MUL_DIV_REM;
SupCnt evt_FP;
SupCnt evt_SC_SUCCESS;
SupCnt evt_LOAD_WAIT;
SupCnt evt_STORE_WAIT;
SupCnt evt_FENCE;
SupCnt evt_F_BUSY_NO_CONSUME; // XXX
SupCnt evt_D_BUSY_NO_CONSUME; // XXX
SupCnt evt_1_BUSY_NO_CONSUME; // XXX
SupCnt evt_2_BUSY_NO_CONSUME; // XXX
SupCnt evt_3_BUSY_NO_CONSUME; // XXX
SupCnt evt_IMPRECISE_SETBOUND; // XXX
SupCnt evt_UNREPRESENTABLE_CAP; // XXX
SupCnt evt_MEM_CAP_LOAD;
SupCnt evt_MEM_CAP_STORE;
SupCnt evt_MEM_CAP_LOAD_TAG_SET;
SupCnt evt_MEM_CAP_STORE_TAG_SET;
} EventsCore deriving (Bits, FShow);
typedef TDiv#(SizeOf#(EventsCore),SizeOf#(SupCnt)) EventsCoreElements;
typedef Bit#(Report_Width) HpmRpt;
typedef struct {
HpmRpt evt_REDIRECT;
HpmRpt evt_TRAP;
HpmRpt evt_BRANCH;
HpmRpt evt_JAL;
HpmRpt evt_JALR;
HpmRpt evt_AUIPC;
HpmRpt evt_LOAD;
HpmRpt evt_STORE;
HpmRpt evt_LR;
HpmRpt evt_SC;
HpmRpt evt_AMO;
HpmRpt evt_SERIAL_SHIFT;
HpmRpt evt_INT_MUL_DIV_REM;
HpmRpt evt_FP;
HpmRpt evt_SC_SUCCESS;
HpmRpt evt_LOAD_WAIT;
HpmRpt evt_STORE_WAIT;
HpmRpt evt_FENCE;
HpmRpt evt_F_BUSY_NO_CONSUME; // XXX
HpmRpt evt_D_BUSY_NO_CONSUME; // XXX
HpmRpt evt_1_BUSY_NO_CONSUME; // XXX
HpmRpt evt_2_BUSY_NO_CONSUME; // XXX
HpmRpt evt_3_BUSY_NO_CONSUME; // XXX
HpmRpt evt_IMPRECISE_SETBOUND; // XXX
HpmRpt evt_UNREPRESENTABLE_CAP; // XXX
HpmRpt evt_MEM_CAP_LOAD;
HpmRpt evt_MEM_CAP_STORE;
HpmRpt evt_MEM_CAP_LOAD_TAG_SET;
HpmRpt evt_MEM_CAP_STORE_TAG_SET;
} EventsCoreMem deriving (Bits, FShow); // Memory needs more space for reporting delays
typedef TDiv#(SizeOf#(EventsCoreMem),Report_Width) EventsCoreMemElements;
`endif

View File

@@ -69,11 +69,12 @@ typedef struct {
typedef struct {
Bool cap_writable;
Bool cap_readable;
Bool cap_dirty;
} PTEUpperType deriving (Bits, Eq, FShow);
typedef struct {
PTEUpperType pteUpperType;
Bit#(8) reserved;
Bit#(7) reserved;
Ppn ppn;
Bit#(2) reserved_sw; // reserved for supervisor software
PTEType pteType;
@@ -222,12 +223,15 @@ function TlbPermissionCheck hasVMPermission(
end
end
Exception excCode = excLoadPageFault; // Unused default. Just choose one valid option.
// check execute/read/write permission
case(access)
InstFetch: begin
if(!pte_type.executable) begin
fault = True;
end
excCode = excLoadPageFault;
end
DataLoad: begin
// need to consider mstatus.mxr bit
@@ -235,34 +239,39 @@ function TlbPermissionCheck hasVMPermission(
!(pte_type.executable && vm_info.exeReadable)) begin
fault = True;
end
excCode = excLoadPageFault;
end
DataStore: begin
// store requires page to be both readable and writable
if(!(pte_type.readable && pte_type.writable)) begin
fault = True;
excCode = excStorePageFault;
end
else if(cap && !pte_upper_type.cap_writable) begin
fault = True;
excCode = excStoreCapPageFault;
end
end
endcase
TlbPermissionCheck ret = TlbPermissionCheck {
allowed: !fault,
excCode: access == DataStore ? excStorePageFault : excLoadPageFault,
excCode: excCode,
allowCap: pte_upper_type.cap_readable};
if (!fault) begin
if (cap && access == DataStore && !pte_upper_type.cap_writable) begin
// check if accessed or dirty bit needs to be set
if(cap && access == DataStore && !pte_upper_type.cap_dirty) begin
ret.allowed = False;
ret.excCode = excStoreCapPageFault;
end else begin
// check if accessed or dirty bit needs to be set
if(!pte_type.accessed) begin
ret.allowed = False;
ret.excCode = access == DataStore ? excStorePageFault : excLoadPageFault;
end
if(access == DataStore && !pte_type.dirty) begin
ret.allowed = False;
ret.excCode = access == DataStore ? excStorePageFault : excLoadPageFault;
end
end
if(access == DataStore && !pte_type.dirty) begin
ret.allowed = False;
ret.excCode = excStorePageFault;
end
if(!pte_type.accessed) begin
ret.allowed = False;
ret.excCode = access == DataStore ? excStorePageFault : excLoadPageFault;
end
end

View File

@@ -293,15 +293,16 @@ module mkP3_Core (P3_Core_IFC);
// ================================================================
// INTERFACE
let master0_synth <- toAXI4_Master_Synth(corew.cpu_imem_master);
let master1_synth <- toAXI4_Master_Synth(corew.cpu_dmem_master);
// ----------------------------------------------------------------
// Core CPU interfaces
// CPU IMem to Fabric master interface
interface AXI4_Master_Synth master0 = corew.cpu_imem_master;
interface AXI4_Master_Synth master0 = master0_synth;
// CPU DMem to Fabric master interface
interface AXI4_Master_Synth master1 = corew.cpu_dmem_master;
interface AXI4_Master_Synth master1 = master1_synth;
// External interrupts
method Action interrupt_reqs (Bit #(N_External_Interrupt_Sources) reqs);

View File

@@ -2696,6 +2696,26 @@
<spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>IMPORTED_FILE</spirit:userFileType>
</spirit:file>
<spirit:file>
<spirit:name>hdl/module_capChecksExec.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>IMPORTED_FILE</spirit:userFileType>
</spirit:file>
<spirit:file>
<spirit:name>hdl/module_capChecksMem.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>IMPORTED_FILE</spirit:userFileType>
</spirit:file>
<spirit:file>
<spirit:name>hdl/mkAxiLowPower.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>IMPORTED_FILE</spirit:userFileType>
</spirit:file>
<spirit:file>
<spirit:name>hdl/mkPLIC_16_CoreNumX2_7.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>IMPORTED_FILE</spirit:userFileType>
</spirit:file>
<spirit:file>
<spirit:name>hdl/module_decode.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType>

View File

@@ -64,11 +64,30 @@ interface Boot_ROM_IFC;
method Action set_addr_map (Fabric_Addr addr_base, Fabric_Addr addr_lim);
// Main Fabric Reqs/Rsps
interface AXI4_Slave_Synth #(Wd_SId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User,
Wd_AR_User, Wd_R_User) slave;
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0)
slave;
endinterface
// ================================================================
// Some local help-functions
function Bool fn_addr_is_aligned (Fabric_Addr addr, AXI4_Size arsize);
if (arsize == 1) return True;
else if (arsize == 2) return (addr [0] == 1'b_0);
else if (arsize == 4) return (addr [1:0] == 2'b_00);
else if (arsize == 8) return (addr [2:0] == 3'b_000);
else return False;
endfunction
function Bool fn_addr_is_in_range (Fabric_Addr base, Fabric_Addr addr, Fabric_Addr lim);
return ((base <= addr) && (addr < lim));
endfunction
function Bool fn_addr_is_ok (Fabric_Addr base, Fabric_Addr addr, Fabric_Addr lim, AXI4_Size arsize);
return ( fn_addr_is_aligned (addr, arsize)
&& fn_addr_is_in_range (base, addr, lim));
endfunction
// ================================================================
(* synthesize *)
@@ -85,30 +104,10 @@ module mkBoot_ROM (Boot_ROM_IFC);
// ----------------
// Connector to fabric
AXI4_Slave_Width_Xactor#(Wd_SId, Wd_Addr, Wd_Data_Periph, Wd_Data,
Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph, Wd_AR_User_Periph, Wd_R_User_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User) slave_xactor <- mkAXI4_Slave_Zeroing_Xactor;
let slavePortShim <- mkAXI4ShimFF;
// ----------------
function Bool fn_addr_is_aligned (Fabric_Addr addr);
if (valueOf (Wd_Data) == 32)
return (addr [1:0] == 2'b_00);
else if (valueOf (Wd_Data) == 64)
return (addr [2:0] == 3'b_000);
else
return False;
endfunction
function Bool fn_addr_is_in_range (Fabric_Addr base, Fabric_Addr addr, Fabric_Addr lim);
return ((base <= addr) && (addr < lim));
endfunction
function Bool fn_addr_is_ok (Fabric_Addr base, Fabric_Addr addr, Fabric_Addr lim);
return ( fn_addr_is_aligned (addr)
&& fn_addr_is_in_range (base, addr, lim));
endfunction
// ================================================================
// BEHAVIOR
@@ -116,34 +115,37 @@ module mkBoot_ROM (Boot_ROM_IFC);
// Handle fabric read requests
rule rl_process_rd_req (rg_module_ready);
let rda <- get(slave_xactor.master.ar);
let byte_addr = rda.araddr - rg_addr_base;
let rda <- get(slavePortShim.master.ar);
AXI4_Resp rresp = OKAY;
Bit #(64) data64 = 0;
if (! fn_addr_is_ok (rg_addr_base, rda.araddr, rg_addr_lim)) begin
if (! fn_addr_is_ok (rg_addr_base, rda.araddr, rg_addr_lim, rda.arsize)) begin
rresp = SLVERR;
$display ("%0d: ERROR: Boot_ROM.rl_process_rd_req: unrecognized addr", cur_cycle);
$display ("%0d: ERROR: Boot_ROM.rl_process_rd_req: unrecognized or misaligned addr",
cur_cycle);
$display (" ", fshow (rda));
end
else if (rda.araddr [2:0] == 3'b0) begin
Bit #(32) d0 = fn_read_ROM_0 (byte_addr);
Bit #(32) d1 = fn_read_ROM_4 (byte_addr + 4);
data64 = { d1, d0 };
end
else begin // ((valueOf (Wd_Data) == 32) && (rda.addr [1:0] == 2'b_00))
Bit #(32) d1 = fn_read_ROM_4 (byte_addr);
data64 = { 0, d1 };
else begin
// Byte offset
let byte_offset = rda.araddr - rg_addr_base;
let rom_addr_0 = (byte_offset & (~ 'b_111));
Bit #(32) d0 = fn_read_ROM_0 (rom_addr_0);
let rom_addr_4 = (rom_addr_0 | 'b_100);
Bit #(32) d4 = fn_read_ROM_4 (rom_addr_4);
if ((valueOf (Wd_Data) == 32) && (byte_offset [2] == 1'b_1))
data64 = { 0, d4 };
else
data64 = { d4, d0 };
end
Bit #(Wd_Data) rdata = truncate (data64);
let rdr = AXI4_RFlit {rid: rda.arid,
rdata: rdata,
rresp: rresp,
rlast: True,
ruser: rda.aruser}; // XXX This requires that Wd_AR_User == Wd_R_User
slave_xactor.master.r.put(rdr);
Bit #(Wd_Data_Periph) rdata = truncate (data64);
AXI4_RFlit#(Wd_SId, Wd_Data_Periph, 0) rdr = AXI4_RFlit {rid: rda.arid,
rdata: rdata,
rresp: rresp,
rlast: True,
ruser: 0};
slavePortShim.master.r.put(rdr);
if (verbosity > 0) begin
$display ("%0d: Boot_ROM.rl_process_rd_req: ", cur_cycle);
@@ -156,20 +158,21 @@ module mkBoot_ROM (Boot_ROM_IFC);
// Handle fabric write requests: ignore all of them (this is a ROM)
rule rl_process_wr_req (rg_module_ready);
let wra <- get(slave_xactor.master.aw);
let wrd <- get(slave_xactor.master.w);
let wra <- get(slavePortShim.master.aw);
let wrd <- get(slavePortShim.master.w);
AXI4_Resp bresp = OKAY;
if (! fn_addr_is_ok (rg_addr_base, wra.awaddr, rg_addr_lim)) begin
if (! fn_addr_is_ok (rg_addr_base, wra.awaddr, rg_addr_lim, wra.awsize)) begin
bresp = SLVERR;
$display ("%0d: ERROR: Boot_ROM.rl_process_wr_req: unrecognized addr", cur_cycle);
$display ("%0d: ERROR: Boot_ROM.rl_process_wr_req: unrecognized or misaligned addr",
cur_cycle);
$display (" ", fshow (wra));
end
let wrr = AXI4_BFlit {bid: wra.awid,
bresp: bresp,
buser: wra.awuser}; // XXX This requires that Wd_AW_User == Wd_B_User
slave_xactor.master.b.put(wrr);
AXI4_BFlit#(Wd_SId, 0) wrr = AXI4_BFlit {bid: wra.awid,
bresp: bresp,
buser: 0};
slavePortShim.master.b.put(wrr);
if (verbosity > 0) begin
$display ("%0d: Boot_ROM.rl_process_wr_req; ignoring all writes", cur_cycle);
@@ -206,14 +209,13 @@ module mkBoot_ROM (Boot_ROM_IFC);
rg_addr_base <= addr_base;
rg_addr_lim <= addr_lim;
rg_module_ready <= True;
slave_xactor.clear;
if (verbosity > 0) begin
$display ("%0d: Boot_ROM.set_addr_map: base 0x%0h lim 0x%0h", cur_cycle, addr_base, addr_lim);
end
endmethod
// Main Fabric Reqs/Rsps
interface slave = slave_xactor.slaveSynth;
interface slave = slavePortShim.slave;
endmodule
// ================================================================

View File

@@ -207,8 +207,8 @@ interface Mem_Controller_IFC;
method Action set_addr_map (Fabric_Addr addr_base, Fabric_Addr addr_lim);
// Main Fabric Reqs/Rsps
interface AXI4_Slave_Synth #(Wd_SId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User) slave;
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
slave;
// To raw memory (outside the SoC)
interface MemoryClient #(Bits_per_Raw_Mem_Addr, Bits_per_Raw_Mem_Word) to_raw_mem;
@@ -269,9 +269,7 @@ module mkMem_Controller (Mem_Controller_IFC);
FIFOF #(Bit #(0)) f_reset_rsps <- mkFIFOF;
// Communication with fabric
AXI4_Slave_Width_Xactor#(Wd_SId, Wd_Addr, Wd_Data_Periph, Wd_Data,
Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph, Wd_AR_User_Periph, Wd_R_User_Periph,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User) slave_xactor <- mkAXI4_Slave_Zeroing_Xactor;
let slavePortShim <- mkAXI4ShimFF;
// Requests merged from the (WrA, WrD) and RdA channels
FIFOF #(Req) f_reqs <- mkPipelineFIFOF;
@@ -304,7 +302,7 @@ module mkMem_Controller (Mem_Controller_IFC);
function Action fa_reset_actions;
action
slave_xactor.clear;
slavePortShim.clear;
f_raw_mem_reqs.clear;
f_raw_mem_rsps.clear;
rg_status <= 0;
@@ -345,7 +343,7 @@ module mkMem_Controller (Mem_Controller_IFC);
// Merge requests into a single queue, prioritizing reads over writes
rule rl_merge_rd_req;
let rda <- get(slave_xactor.master.ar);
let rda <- get(slavePortShim.master.ar);
let req = Req {req_op: REQ_OP_RD,
id: rda.arid,
addr: rda.araddr,
@@ -370,8 +368,8 @@ module mkMem_Controller (Mem_Controller_IFC);
(* descending_urgency = "rl_merge_rd_req, rl_merge_wr_req" *)
rule rl_merge_wr_req;
let wra <- get(slave_xactor.master.aw);
let wrd <- get(slave_xactor.master.w);
let wra <- get(slavePortShim.master.aw);
let wrd <- get(slavePortShim.master.w);
let req = Req {req_op: REQ_OP_WR,
id: wra.awid,
addr: wra.awaddr,
@@ -504,8 +502,8 @@ module mkMem_Controller (Mem_Controller_IFC);
rdata: rdata,
rresp: OKAY,
rlast: True,
ruser: f_reqs.first.user}; // XXX This requires that Wd_AR_User == Wd_R_User
slave_xactor.master.r.put(rdr);
ruser: 0'b0};
slavePortShim.master.r.put(rdr);
f_reqs.deq;
if (cfg_verbosity > 1) begin
@@ -546,8 +544,8 @@ module mkMem_Controller (Mem_Controller_IFC);
let wrr = AXI4_BFlit {bid: f_reqs.first.id,
bresp: OKAY,
buser: f_reqs.first.user}; // XXX This requires that Wd_AW_User == Wd_B_User
slave_xactor.master.b.put(wrr);
buser: 0'b0};
slavePortShim.master.b.put(wrr);
f_reqs.deq;
if (cfg_verbosity > 1) begin
@@ -616,8 +614,8 @@ module mkMem_Controller (Mem_Controller_IFC);
rdata: rdata, // for debugging only
rresp: SLVERR,
rlast: True,
ruser: f_reqs.first.user}; // XXX This requires that Wd_AR_User == Wd_R_User
slave_xactor.master.r.put(rdr);
ruser: 0'b0};
slavePortShim.master.r.put(rdr);
f_reqs.deq;
$write ("%0d: ERROR: Mem_Controller:", cur_cycle);
@@ -635,8 +633,8 @@ module mkMem_Controller (Mem_Controller_IFC);
&& (f_reqs.first.req_op == REQ_OP_WR));
let wrr = AXI4_BFlit {bid: f_reqs.first.id,
bresp: SLVERR,
buser: f_reqs.first.user}; // XXX This requires that Wd_AW_User == Wd_B_User
slave_xactor.master.b.put(wrr);
buser: 0'b0};
slavePortShim.master.b.put(wrr);
f_reqs.deq;
$write ("%0d: ERROR: Mem_Controller:", cur_cycle);
@@ -671,7 +669,7 @@ module mkMem_Controller (Mem_Controller_IFC);
endmethod
// Main Fabric Reqs/Rsps
interface slave = slave_xactor.slaveSynth;
interface slave = slavePortShim.slave;
// To raw memory (outside the SoC)
interface to_raw_mem = toGPClient (f_raw_mem_reqs, f_raw_mem_rsps);

View File

@@ -153,16 +153,14 @@ module mkSoC_Top #(Reset dm_power_on_reset)
// SoC Boot ROM
Boot_ROM_IFC boot_rom <- mkBoot_ROM;
// AXI4 Deburster in front of Boot_ROM
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User)
boot_rom_axi4_deburster <- mkBurstToNoBurst;
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
boot_rom_axi4_deburster <- mkBurstToNoBurst;
// SoC Memory
Mem_Controller_IFC mem0_controller <- mkMem_Controller;
// AXI4 Deburster in front of SoC Memory
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data,
Wd_AW_User, Wd_W_User, Wd_B_User, Wd_AR_User, Wd_R_User)
mem0_controller_axi4_deburster <- mkBurstToNoBurst;
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
mem0_controller_axi4_deburster <- mkBurstToNoBurst;
// SoC IPs
UART_IFC uart0 <- mkUART;
@@ -176,9 +174,9 @@ module mkSoC_Top #(Reset dm_power_on_reset)
// SoC fabric master connections
// Note: see 'SoC_Map' for 'master_num' definitions
Vector#(Num_Masters, AXI4_Master_Synth #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
0, 0, 0, 0, 0))
master_vector = newVector;
Vector#(Num_Masters, AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
0, 0, 0, 0, 0))
master_vector = newVector;
// CPU IMem master to fabric
master_vector[imem_master_num] = corew.cpu_imem_master;
@@ -190,30 +188,28 @@ module mkSoC_Top #(Reset dm_power_on_reset)
// SoC fabric slave connections
// Note: see 'SoC_Map' for 'slave_num' definitions
Vector#(Num_Slaves, AXI4_Slave_Synth #(Wd_SId, Wd_Addr, Wd_Data,
0, 0, 0, 0, 0))
slave_vector = newVector;
Vector#(Num_Slaves, Range#(Wd_Addr)) route_vector = newVector;
Vector#(Num_Slaves, AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data,
0, 0, 0, 0, 0))
slave_vector = newVector;
Vector#(Num_Slaves, Range#(Wd_Addr)) route_vector = newVector;
// Fabric to Boot ROM
let br <- fromAXI4_Slave_Synth(boot_rom.slave);
mkConnection(boot_rom_axi4_deburster.master, br);
slave_vector[boot_rom_slave_num] <- toAXI4_Slave_Synth(zeroSlaveUserFields(boot_rom_axi4_deburster.slave));
mkConnection(boot_rom_axi4_deburster.master, boot_rom.slave);
slave_vector[boot_rom_slave_num] = boot_rom_axi4_deburster.slave;
route_vector[boot_rom_slave_num] = soc_map.m_boot_rom_addr_range;
// Fabric to Mem Controller
let mem <- fromAXI4_Slave_Synth(mem0_controller.slave);
mkConnection(mem0_controller_axi4_deburster.master, mem);
slave_vector[mem0_controller_slave_num] <- toAXI4_Slave_Synth(zeroSlaveUserFields(mem0_controller_axi4_deburster.slave));
mkConnection(mem0_controller_axi4_deburster.master, mem0_controller.slave);
slave_vector[mem0_controller_slave_num] = mem0_controller_axi4_deburster.slave;
route_vector[mem0_controller_slave_num] = soc_map.m_mem0_controller_addr_range;
// Fabric to UART0
slave_vector[uart0_slave_num] <- toAXI4_Slave_Synth(zeroSlaveUserFields(uart0.slave));
slave_vector[uart0_slave_num] = zeroSlaveUserFields(uart0.slave);
route_vector[uart0_slave_num] = soc_map.m_uart0_addr_range;
`ifdef INCLUDE_ACCEL0
// Fabric to accel0
slave_vector[accel0_slave_num] <- liftAXI4_Slave_Synth(zeroSlaveUserFields, accel0.slave);
slave_vector[accel0_slave_num] = zeroSlaveUserFields (accel0.slave);
route_vector[accel0_slave_num] = soc_map.m_accel0_addr_range;
`endif
@@ -225,8 +221,8 @@ module mkSoC_Top #(Reset dm_power_on_reset)
`endif
// SoC Fabric
let bus <- mkAXI4Bus_Synth (routeFromMappingTable(route_vector),
master_vector, slave_vector);
let bus <- mkAXI4Bus (routeFromMappingTable(route_vector),
master_vector, slave_vector);
// ----------------
// Connect interrupt sources for CPU external interrupt request inputs.