diff --git a/README.md b/README.md index 836e269..fcc0026 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/Tests/elf_to_hex/elf_to_hex.c b/Tests/elf_to_hex/elf_to_hex.c index e148c37..a146c46 100644 --- a/Tests/elf_to_hex/elf_to_hex.c +++ b/Tests/elf_to_hex/elf_to_hex.c @@ -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 \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); } diff --git a/builds/RV64ACDFIMSUxCHERI_Toooba_RVFI_DII_bluesim/Makefile b/builds/RV64ACDFIMSUxCHERI_Toooba_RVFI_DII_bluesim/Makefile index 6316758..11baa09 100644 --- a/builds/RV64ACDFIMSUxCHERI_Toooba_RVFI_DII_bluesim/Makefile +++ b/builds/RV64ACDFIMSUxCHERI_Toooba_RVFI_DII_bluesim/Makefile @@ -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 \ diff --git a/libs/BlueStuff b/libs/BlueStuff index baf31fb..c483104 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit baf31fb28835f3176163f1c160e0177cb85a3f11 +Subproject commit c483104aa7f8bd2a1585e747dd6f5dab7d82e17f diff --git a/libs/TagController b/libs/TagController index aaa23bc..f4c5348 160000 --- a/libs/TagController +++ b/libs/TagController @@ -1 +1 @@ -Subproject commit aaa23bc2469bcde6c6b6e315f94f8ae83c0c14f3 +Subproject commit f4c53481887564f6e8fcb9b8f2bf94f56b7afb07 diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 1c16a97..eee9b05 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -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 diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 9519ac2..49055a6 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -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 diff --git a/src_Core/CPU/LLC_AXI4_Adapter.bsv b/src_Core/CPU/LLC_AXI4_Adapter.bsv index 9fa964b..3a03154 100644 --- a/src_Core/CPU/LLC_AXI4_Adapter.bsv +++ b/src_Core/CPU/LLC_AXI4_Adapter.bsv @@ -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 // ================================================================ diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 54f6852..e8464b6 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -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 // ================================================================ diff --git a/src_Core/CPU/Proc_IFC.bsv b/src_Core/CPU/Proc_IFC.bsv index 26123f5..61369f5 100644 --- a/src_Core/CPU/Proc_IFC.bsv +++ b/src_Core/CPU/Proc_IFC.bsv @@ -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 // ================================================================ diff --git a/src_Core/Core/CoreW.bsv b/src_Core/Core/CoreW.bsv index ea14bc6..0a9e5e4 100644 --- a/src_Core/Core/CoreW.bsv +++ b/src_Core/Core/CoreW.bsv @@ -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 diff --git a/src_Core/Core/CoreW_IFC.bsv b/src_Core/Core/CoreW_IFC.bsv index 6853767..731fedf 100644 --- a/src_Core/Core/CoreW_IFC.bsv +++ b/src_Core/Core/CoreW_IFC.bsv @@ -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; diff --git a/src_Core/Debug_Module/DM_System_Bus.bsv b/src_Core/Debug_Module/DM_System_Bus.bsv index a6f9abc..08417d2 100644 --- a/src_Core/Debug_Module/DM_System_Bus.bsv +++ b/src_Core/Debug_Module/DM_System_Bus.bsv @@ -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 // ================================================================ diff --git a/src_Core/Debug_Module/Debug_Module.bsv b/src_Core/Debug_Module/Debug_Module.bsv index cb96e8c..1178891 100644 --- a/src_Core/Debug_Module/Debug_Module.bsv +++ b/src_Core/Debug_Module/Debug_Module.bsv @@ -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 // ================================================================ diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index dbd05ab..6dc3da9 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -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); diff --git a/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv b/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv index b583769..27b21ab 100644 --- a/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv @@ -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, diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index 1fcf4fb..a1aed8b 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv index 3e4adec..9e918f3 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv index 06be57a..28dd961 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv @@ -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!!! - diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index f7b529e..a283d0b 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -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); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index a9206e7..39ceb05 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi index a7b029b..96970e3 100644 --- a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi @@ -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) diff --git a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv index 2c699ac..ed7618b 100644 --- a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index 0d914a9..352cc75 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv index 5af744c..d26d0ab 100644 --- a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv index 26e652a..8f87367 100644 --- a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv +++ b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv index b008ebb..916c602 100644 --- a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv +++ b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/LLCache.bsv b/src_Core/RISCY_OOO/procs/lib/LLCache.bsv index 401aa2c..70a5cf7 100644 --- a/src_Core/RISCY_OOO/procs/lib/LLCache.bsv +++ b/src_Core/RISCY_OOO/procs/lib/LLCache.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 85c6235..4f69c89 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index 9d15af0..084990e 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -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 diff --git a/src_SSITH_P3/src_BSV/P3_Core.bsv b/src_SSITH_P3/src_BSV/P3_Core.bsv index 6fb6d87..5c4b81a 100644 --- a/src_SSITH_P3/src_BSV/P3_Core.bsv +++ b/src_SSITH_P3/src_BSV/P3_Core.bsv @@ -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); diff --git a/src_SSITH_P3/xilinx_ip/component.xml b/src_SSITH_P3/xilinx_ip/component.xml index 8a4b2e2..7f94e25 100644 --- a/src_SSITH_P3/xilinx_ip/component.xml +++ b/src_SSITH_P3/xilinx_ip/component.xml @@ -2696,6 +2696,26 @@ verilogSource IMPORTED_FILE + + hdl/module_capChecksExec.v + verilogSource + IMPORTED_FILE + + + hdl/module_capChecksMem.v + verilogSource + IMPORTED_FILE + + + hdl/mkAxiLowPower.v + verilogSource + IMPORTED_FILE + + + hdl/mkPLIC_16_CoreNumX2_7.v + verilogSource + IMPORTED_FILE + hdl/module_decode.v verilogSource diff --git a/src_Testbench/SoC/Boot_ROM.bsv b/src_Testbench/SoC/Boot_ROM.bsv index 5a8daf8..bfd7262 100644 --- a/src_Testbench/SoC/Boot_ROM.bsv +++ b/src_Testbench/SoC/Boot_ROM.bsv @@ -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 // ================================================================ diff --git a/src_Testbench/SoC/Mem_Controller.bsv b/src_Testbench/SoC/Mem_Controller.bsv index e37b5b6..09433c4 100644 --- a/src_Testbench/SoC/Mem_Controller.bsv +++ b/src_Testbench/SoC/Mem_Controller.bsv @@ -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); diff --git a/src_Testbench/SoC/SoC_Top.bsv b/src_Testbench/SoC/SoC_Top.bsv index 5ce90eb..3fbd43f 100644 --- a/src_Testbench/SoC/SoC_Top.bsv +++ b/src_Testbench/SoC/SoC_Top.bsv @@ -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.