From d4308f0f03eaf90d8f95929947a5d01e517a6067 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Wed, 30 Sep 2020 15:40:50 +0100 Subject: [PATCH 01/41] Slightly rework CHERI PTE to add CapDirty flag Permissions are consistently checked before dirty flags, now, too. --- src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 37 +++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index 9d15af0..1fbf387 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; @@ -183,6 +184,14 @@ typedef struct { Bool allowCap; // Whether we can load caps } TlbPermissionCheck deriving(Bits, Eq, FShow); +function Exception tlbExcCode(TlbAccessType access, Bool cap); + if (access == DataStore) begin + return cap ? excStoreCapPageFault : excStorePageFault; + end else begin + return excLoadPageFault; + end +endfunction + function TlbPermissionCheck hasVMPermission( VMInfo vm_info, PTEType pte_type, PTEUpperType pte_upper_type, @@ -241,28 +250,30 @@ function TlbPermissionCheck hasVMPermission( if(!(pte_type.readable && pte_type.writable)) begin fault = True; end + if(cap && !pte_upper_type.cap_writable) begin + fault = True; + end end endcase TlbPermissionCheck ret = TlbPermissionCheck { allowed: !fault, - excCode: access == DataStore ? excStorePageFault : excLoadPageFault, + excCode: tlbExcCode(access, cap), 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 From ed9541e8d05156dfc577e85f953a84ad079885f1 Mon Sep 17 00:00:00 2001 From: Marno van der Maas <34654485+marnovandermaas@users.noreply.github.com> Date: Fri, 2 Oct 2020 13:09:51 +0100 Subject: [PATCH 02/41] Put all dirs for source description in code blocks --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 836e269..a14ac44 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 From 328592b068999d35b9f501e86eb38cb5fc097bed Mon Sep 17 00:00:00 2001 From: Marno van der Maas <34654485+marnovandermaas@users.noreply.github.com> Date: Thu, 29 Oct 2020 15:45:17 +0000 Subject: [PATCH 03/41] Added missing slash in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a14ac44..fcc0026 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ 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. + - `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) - `BSV_Additional_Libs/`: generic utilities (not CPU-specific) From 61b88ef987c726f0db7ad7e0c6294e26495c01ac Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Mon, 2 Nov 2020 11:23:07 +0000 Subject: [PATCH 04/41] Generate elf files the correct size --- Tests/elf_to_hex/elf_to_hex.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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); } From bf77ac74babf1cf09c39ca9d225942ad9d615496 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 4 Nov 2020 12:11:31 +0000 Subject: [PATCH 05/41] Fix performance reporting requests for multicore --- src_Core/CPU/Proc.bsv | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 54f6852..d3af7d3 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,23 @@ 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 + // ================================================================ // Stub out deadlock and renameDebug interfaces From 69c697daf7644ee9d120e4eb8fe1d1335be44a15 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Thu, 22 Oct 2020 15:21:47 +0100 Subject: [PATCH 06/41] Changes needed to build for FPGA. --- src_Core/CPU/Core.bsv | 2 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 2 +- src_SSITH_P3/xilinx_ip/component.xml | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 1c16a97..3e91399 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1319,7 +1319,7 @@ module mkCore#(CoreId coreId)(Core); l2Tlb.updateVMInfo(vmI, vmD); let startpc = csrf.dpc_read; - fetchStage.redirect (cast(startpc)); + fetchStage.redirect (PredState{pc: cast(startpc)}); renameStage.debug_resume; commitStage.debug_resume; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index f7b529e..e40eb1a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -747,7 +747,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); ? 4 : 1)); csrf.dcsr_cause_write (dcsr_cause); - csrf.dpc_write (cast(trap.pc)); + csrf.dpc_write (cast(trap.ps.pc)); // Tell fetch stage to wait for redirect // Note: rule doCommitTrap_flush may have done this already; redundant call is ok. 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 From 6e4c378d4dd20d954d66dc462f2c6d0db4dfb854 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Fri, 6 Nov 2020 14:38:07 +0000 Subject: [PATCH 07/41] CHERI ISAv8 CapDirty fault priority fix Raise a store page fault if the PTE is missing R or W, even if the store is a cap store and the PTE is also missing CW, as per the sail spec. Co-authored-by: Jessica Clarke --- src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index 1fbf387..f941ee9 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -184,14 +184,6 @@ typedef struct { Bool allowCap; // Whether we can load caps } TlbPermissionCheck deriving(Bits, Eq, FShow); -function Exception tlbExcCode(TlbAccessType access, Bool cap); - if (access == DataStore) begin - return cap ? excStoreCapPageFault : excStorePageFault; - end else begin - return excLoadPageFault; - end -endfunction - function TlbPermissionCheck hasVMPermission( VMInfo vm_info, PTEType pte_type, PTEUpperType pte_upper_type, @@ -231,12 +223,15 @@ function TlbPermissionCheck hasVMPermission( end end + Exception excCode; + // 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 @@ -244,21 +239,24 @@ 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 - if(cap && !pte_upper_type.cap_writable) begin + else if(cap && !pte_upper_type.cap_writable) begin fault = True; + excCode = excStoreCapPageFault; end end endcase TlbPermissionCheck ret = TlbPermissionCheck { allowed: !fault, - excCode: tlbExcCode(access, cap), + excCode: excCode, allowCap: pte_upper_type.cap_readable}; if (!fault) begin From 0289bfe17d4062986cd0244262da3be085369cd1 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Mon, 9 Nov 2020 11:14:11 +0000 Subject: [PATCH 08/41] Fix a couple errors due to changes somehow merged over from the rich_predicted_state branch. --- src_Core/CPU/Core.bsv | 2 +- src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 3e91399..1c16a97 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1319,7 +1319,7 @@ module mkCore#(CoreId coreId)(Core); l2Tlb.updateVMInfo(vmI, vmD); let startpc = csrf.dpc_read; - fetchStage.redirect (PredState{pc: cast(startpc)}); + fetchStage.redirect (cast(startpc)); renameStage.debug_resume; commitStage.debug_resume; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index e40eb1a..f7b529e 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -747,7 +747,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); ? 4 : 1)); csrf.dcsr_cause_write (dcsr_cause); - csrf.dpc_write (cast(trap.ps.pc)); + csrf.dpc_write (cast(trap.pc)); // Tell fetch stage to wait for redirect // Note: rule doCommitTrap_flush may have done this already; redundant call is ok. From 98a9c076cdee586a8e172cfa36d06a7af858a477 Mon Sep 17 00:00:00 2001 From: Alexandre Joannou Date: Tue, 1 Dec 2020 00:33:48 +0000 Subject: [PATCH 09/41] Update BlueStuff API and Bump BlueStuff and TagController --- libs/BlueStuff | 2 +- libs/TagController | 2 +- src_Core/CPU/LLC_AXI4_Adapter.bsv | 20 ++-- src_Core/CPU/Proc_IFC.bsv | 12 +- src_Core/Core/CoreW.bsv | 62 ++++++---- src_Core/Core/CoreW_IFC.bsv | 68 +++++++++++ src_Core/PLIC/PLIC.bsv | 35 +++--- .../RISCY_OOO/procs/lib/LLCDmaConnect.bsv | 42 +++---- src_Testbench/SoC/Boot_ROM.bsv | 110 +++++++++--------- src_Testbench/SoC/Mem_Controller.bsv | 34 +++--- src_Testbench/SoC/SoC_Top.bsv | 42 +++---- 11 files changed, 254 insertions(+), 175 deletions(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index baf31fb..b9c76d5 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit baf31fb28835f3176163f1c160e0177cb85a3f11 +Subproject commit b9c76d57ed363744f1ba3fc0596931c6dbaa04b0 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/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_IFC.bsv b/src_Core/CPU/Proc_IFC.bsv index 26123f5..d9eaede 100644 --- a/src_Core/CPU/Proc_IFC.bsv +++ b/src_Core/CPU/Proc_IFC.bsv @@ -69,9 +69,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 +101,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; diff --git a/src_Core/Core/CoreW.bsv b/src_Core/Core/CoreW.bsv index ea14bc6..ffd1128 100644 --- a/src_Core/Core/CoreW.bsv +++ b/src_Core/Core/CoreW.bsv @@ -164,17 +164,14 @@ 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); // PLIC (Platform-Level Interrupt Controller) PLIC_IFC_16_2_7 plic <- mkPLIC_16_2_7; @@ -355,26 +352,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 +384,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 +434,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 +486,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.Toooba_RVFI_DII_Server 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/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index dbd05ab..32d9465 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -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; @@ -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 @@ -246,7 +243,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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,7 +258,7 @@ 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)); @@ -404,11 +401,11 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) // 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); @@ -424,8 +421,8 @@ 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)); @@ -551,9 +548,9 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) // 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); @@ -628,7 +625,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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/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_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. From 259d34618c61f030d04ae8b4ea89f338f87642ba Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 1 Dec 2020 18:02:11 +0000 Subject: [PATCH 10/41] A design that actually passes one performance monitor trace from TestRig. The example counted redirections, which happend to match between Flute and Toooba for this example. --- .../Makefile | 1 + src_Core/CPU/Core.bsv | 80 ++++++++++++++++ src_Core/CPU/CsrFile.bsv | 80 ++++++++++++++-- src_Core/RISCY_OOO/procs/lib/CSRs.bsvi | 95 +++++++++++++++++++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 6 ++ 5 files changed, 252 insertions(+), 10 deletions(-) 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/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 1c16a97..238ece2 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 SpecialWires::*; +`endif import HasSpecBits::*; import Exec::*; import FetchStage::*; @@ -157,6 +161,48 @@ interface CoreRenameDebug; interface Get#(RenameErrInfo) renameErr; endinterface +// ================================================================ + +`ifdef PERFORMANCE_MONITORING +typedef struct { + Bool evt_REDIRECT; + Bool evt_TLB_EXC; // TODO: Misleading name + Bool evt_BRANCH; + Bool evt_JAL; + Bool evt_JALR; + Bool evt_AUIPC; + Bool evt_LOAD; + Bool evt_STORE; + Bool evt_LR; + Bool evt_SC; + Bool evt_AMO; + Bool evt_SERIAL_SHIFT; + Bool evt_INT_MUL_DIV_REM; + Bool evt_FP; + Bool evt_SC_SUCCESS; + Bool evt_LOAD_WAIT; + Bool evt_STORE_WAIT; + Bool evt_FENCE; + Bool evt_F_BUSY_NO_CONSUME; + Bool evt_D_BUSY_NO_CONSUME; + Bool evt_1_BUSY_NO_CONSUME; + Bool evt_2_BUSY_NO_CONSUME; + Bool evt_3_BUSY_NO_CONSUME; + Bool evt_IMPRECISE_SETBOUND; + Bool evt_UNREPRESENTABLE_CAP; + Bool evt_MEM_CAP_LOAD; + Bool evt_MEM_CAP_STORE; + Bool evt_MEM_CAP_LOAD_TAG_SET; + Bool evt_MEM_CAP_STORE_TAG_SET; +} EventsCore deriving (Bits, FShow); + +instance BitVectorable #(EventsCore, 1, m) provisos (Bits #(EventsCore, m)); + function to_vector = struct_to_vector; +endinstance +`endif + +// ================================================================ + interface Core; // core request & indication interface CoreReq coreReq; @@ -258,6 +304,14 @@ module mkCore#(CoreId coreId)(Core); Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF); `endif +`ifdef PERFORMANCE_MONITORING + Array #(Wire #(EventsCore)) aw_events <- mkDWireOR (5, unpack (0)); + Reg #(EventsCore) aw_events_reg <- mkConfigReg(unpack(0)); + rule update_aw_events_reg; + aw_events_reg <= aw_events[0]; + endrule +`endif + // ================================================================ // front end @@ -400,6 +454,11 @@ module mkCore#(CoreId coreId)(Core); `endif ); globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag); +`ifdef PERFORMANCE_MONITORING + EventsCore events = unpack (0); + events.evt_REDIRECT = True; + aw_events[1] <= events; +`endif endmethod method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put; method doStats = doStatsReg._read; @@ -1075,6 +1134,27 @@ module mkCore#(CoreId coreId)(Core); endrule `endif +`ifdef PERFORMANCE_MONITORING + // ================================================================ + // Performance counters + + Vector #(1, Bit #(Counter_Width)) null_evt = replicate (0); + Vector #(31, Bit #(Counter_Width)) core_evts_vec = to_large_vector (aw_events_reg); + Vector #(16, Bit #(Counter_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); + Vector #(16, Bit #(Counter_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); + Vector #(32, Bit #(Counter_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); + + 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); + + (* 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 diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 9519ac2..c09ff4d 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 #(Counter_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#(Counter_Width)) evts); +endinterface +(* synthesize *) +module mkPerfCountersToooba (PerfCountersVec); + PerfCounters_IFC #(No_Of_Ctrs, Counter_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 ((csrAddrMHPMCNT3.addr <= c) && (c <= csrAddrMHPMCNT31.addr)) + ret = perf_counters.counter_vec[c-csrAddrMHPMCNT3.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; @@ -810,20 +868,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 +1398,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/RISCY_OOO/procs/lib/CSRs.bsvi b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi index a7b029b..85e93bf 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(HPMCNT3, 12'hc03) +`CSR(HPMCNT4, 12'hc04) +`CSR(HPMCNT5, 12'hc05) +`CSR(HPMCNT6, 12'hc06) +`CSR(HPMCNT7, 12'hc07) +`CSR(HPMCNT8, 12'hc08) +`CSR(HPMCNT9, 12'hc09) +`CSR(HPMCNT10, 12'hc0a) +`CSR(HPMCNT11, 12'hc0b) +`CSR(HPMCNT12, 12'hc0c) +`CSR(HPMCNT13, 12'hc0d) +`CSR(HPMCNT14, 12'hc0e) +`CSR(HPMCNT15, 12'hc0f) +`CSR(HPMCNT16, 12'hc10) +`CSR(HPMCNT17, 12'hc11) +`CSR(HPMCNT18, 12'hc12) +`CSR(HPMCNT19, 12'hc13) +`CSR(HPMCNT20, 12'hc14) +`CSR(HPMCNT21, 12'hc15) +`CSR(HPMCNT22, 12'hc16) +`CSR(HPMCNT23, 12'hc17) +`CSR(HPMCNT24, 12'hc18) +`CSR(HPMCNT25, 12'hc19) +`CSR(HPMCNT26, 12'hc1a) +`CSR(HPMCNT27, 12'hc1b) +`CSR(HPMCNT28, 12'hc1c) +`CSR(HPMCNT29, 12'hc1d) +`CSR(HPMCNT30, 12'hc1e) +`CSR(HPMCNT31, 12'hc1f) + +`CSR(MHPMCNT3, 12'hb03) +`CSR(MHPMCNT4, 12'hb04) +`CSR(MHPMCNT5, 12'hb05) +`CSR(MHPMCNT6, 12'hb06) +`CSR(MHPMCNT7, 12'hb07) +`CSR(MHPMCNT8, 12'hb08) +`CSR(MHPMCNT9, 12'hb09) +`CSR(MHPMCNT10, 12'hb0a) +`CSR(MHPMCNT11, 12'hb0b) +`CSR(MHPMCNT12, 12'hb0c) +`CSR(MHPMCNT13, 12'hb0d) +`CSR(MHPMCNT14, 12'hb0e) +`CSR(MHPMCNT15, 12'hb0f) +`CSR(MHPMCNT16, 12'hb10) +`CSR(MHPMCNT17, 12'hb11) +`CSR(MHPMCNT18, 12'hb12) +`CSR(MHPMCNT19, 12'hb13) +`CSR(MHPMCNT20, 12'hb14) +`CSR(MHPMCNT21, 12'hb15) +`CSR(MHPMCNT22, 12'hb16) +`CSR(MHPMCNT23, 12'hb17) +`CSR(MHPMCNT24, 12'hb18) +`CSR(MHPMCNT25, 12'hb19) +`CSR(MHPMCNT26, 12'hb1a) +`CSR(MHPMCNT27, 12'hb1b) +`CSR(MHPMCNT28, 12'hb1c) +`CSR(MHPMCNT29, 12'hb1d) +`CSR(MHPMCNT30, 12'hb1e) +`CSR(MHPMCNT31, 12'hb1f) + +`CSR(MCNTIHB, 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/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 85c6235..34d5e2a 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1040,3 +1040,9 @@ 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 96 No_Of_Evts; +typedef 64 Counter_Width; +typedef 29 No_Of_Ctrs; +`endif From 742c4c5c92b8b92fe6177dbdbbc6eaf7ba38c0e8 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 1 Dec 2020 18:03:44 +0000 Subject: [PATCH 11/41] Bump Bluestuff. --- libs/BlueStuff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index baf31fb..ebd9403 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit baf31fb28835f3176163f1c160e0177cb85a3f11 +Subproject commit ebd9403e8651011fb722d297dd30c02f9195586e From e99e1e6274b0dfb0994a4b9fea16e6c9a89d8c0c Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 2 Dec 2020 10:18:25 +0000 Subject: [PATCH 12/41] Update CSR names to fullish standard names. --- src_Core/CPU/CsrFile.bsv | 7 +- src_Core/RISCY_OOO/procs/lib/CSRs.bsvi | 118 ++++++++++++------------- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index c09ff4d..58490ec 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -809,8 +809,8 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(Data) ret = readOnlyReg(64'b0); `ifdef PERFORMANCE_MONITORING let c = csr.addr; - if ((csrAddrMHPMCNT3.addr <= c) && (c <= csrAddrMHPMCNT31.addr)) - ret = perf_counters.counter_vec[c-csrAddrMHPMCNT3.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 @@ -855,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; diff --git a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi index 85e93bf..96970e3 100644 --- a/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CSRs.bsvi @@ -39,67 +39,67 @@ `CSR(MINSTRET, 12'hb02) `ifdef PERFORMANCE_MONITORING -`CSR(HPMCNT3, 12'hc03) -`CSR(HPMCNT4, 12'hc04) -`CSR(HPMCNT5, 12'hc05) -`CSR(HPMCNT6, 12'hc06) -`CSR(HPMCNT7, 12'hc07) -`CSR(HPMCNT8, 12'hc08) -`CSR(HPMCNT9, 12'hc09) -`CSR(HPMCNT10, 12'hc0a) -`CSR(HPMCNT11, 12'hc0b) -`CSR(HPMCNT12, 12'hc0c) -`CSR(HPMCNT13, 12'hc0d) -`CSR(HPMCNT14, 12'hc0e) -`CSR(HPMCNT15, 12'hc0f) -`CSR(HPMCNT16, 12'hc10) -`CSR(HPMCNT17, 12'hc11) -`CSR(HPMCNT18, 12'hc12) -`CSR(HPMCNT19, 12'hc13) -`CSR(HPMCNT20, 12'hc14) -`CSR(HPMCNT21, 12'hc15) -`CSR(HPMCNT22, 12'hc16) -`CSR(HPMCNT23, 12'hc17) -`CSR(HPMCNT24, 12'hc18) -`CSR(HPMCNT25, 12'hc19) -`CSR(HPMCNT26, 12'hc1a) -`CSR(HPMCNT27, 12'hc1b) -`CSR(HPMCNT28, 12'hc1c) -`CSR(HPMCNT29, 12'hc1d) -`CSR(HPMCNT30, 12'hc1e) -`CSR(HPMCNT31, 12'hc1f) +`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(MHPMCNT3, 12'hb03) -`CSR(MHPMCNT4, 12'hb04) -`CSR(MHPMCNT5, 12'hb05) -`CSR(MHPMCNT6, 12'hb06) -`CSR(MHPMCNT7, 12'hb07) -`CSR(MHPMCNT8, 12'hb08) -`CSR(MHPMCNT9, 12'hb09) -`CSR(MHPMCNT10, 12'hb0a) -`CSR(MHPMCNT11, 12'hb0b) -`CSR(MHPMCNT12, 12'hb0c) -`CSR(MHPMCNT13, 12'hb0d) -`CSR(MHPMCNT14, 12'hb0e) -`CSR(MHPMCNT15, 12'hb0f) -`CSR(MHPMCNT16, 12'hb10) -`CSR(MHPMCNT17, 12'hb11) -`CSR(MHPMCNT18, 12'hb12) -`CSR(MHPMCNT19, 12'hb13) -`CSR(MHPMCNT20, 12'hb14) -`CSR(MHPMCNT21, 12'hb15) -`CSR(MHPMCNT22, 12'hb16) -`CSR(MHPMCNT23, 12'hb17) -`CSR(MHPMCNT24, 12'hb18) -`CSR(MHPMCNT25, 12'hb19) -`CSR(MHPMCNT26, 12'hb1a) -`CSR(MHPMCNT27, 12'hb1b) -`CSR(MHPMCNT28, 12'hb1c) -`CSR(MHPMCNT29, 12'hb1d) -`CSR(MHPMCNT30, 12'hb1e) -`CSR(MHPMCNT31, 12'hb1f) +`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(MCNTIHB, 12'h320) // Machine Counter-Inhibit +`CSR(MCOUNTERINHIBIT, 12'h320) // Machine Counter-Inhibit `CSR(MHPMEVENT3, 12'h323) `CSR(MHPMEVENT4, 12'h324) From 4fcc18635a62f5ce444139c96ba01e5d1af80602 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 2 Dec 2020 15:28:41 +0000 Subject: [PATCH 13/41] Supporting most architectural counters, wiring them out from CommitStage. Also support multiple events per cycle. --- src_Core/CPU/Core.bsv | 65 +++++-------------- src_Core/CPU/CsrFile.bsv | 6 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 29 +++++++-- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 34 ++++++++++ 4 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 238ece2..32ea1f1 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -161,48 +161,6 @@ interface CoreRenameDebug; interface Get#(RenameErrInfo) renameErr; endinterface -// ================================================================ - -`ifdef PERFORMANCE_MONITORING -typedef struct { - Bool evt_REDIRECT; - Bool evt_TLB_EXC; // TODO: Misleading name - Bool evt_BRANCH; - Bool evt_JAL; - Bool evt_JALR; - Bool evt_AUIPC; - Bool evt_LOAD; - Bool evt_STORE; - Bool evt_LR; - Bool evt_SC; - Bool evt_AMO; - Bool evt_SERIAL_SHIFT; - Bool evt_INT_MUL_DIV_REM; - Bool evt_FP; - Bool evt_SC_SUCCESS; - Bool evt_LOAD_WAIT; - Bool evt_STORE_WAIT; - Bool evt_FENCE; - Bool evt_F_BUSY_NO_CONSUME; - Bool evt_D_BUSY_NO_CONSUME; - Bool evt_1_BUSY_NO_CONSUME; - Bool evt_2_BUSY_NO_CONSUME; - Bool evt_3_BUSY_NO_CONSUME; - Bool evt_IMPRECISE_SETBOUND; - Bool evt_UNREPRESENTABLE_CAP; - Bool evt_MEM_CAP_LOAD; - Bool evt_MEM_CAP_STORE; - Bool evt_MEM_CAP_LOAD_TAG_SET; - Bool evt_MEM_CAP_STORE_TAG_SET; -} EventsCore deriving (Bits, FShow); - -instance BitVectorable #(EventsCore, 1, m) provisos (Bits #(EventsCore, m)); - function to_vector = struct_to_vector; -endinstance -`endif - -// ================================================================ - interface Core; // core request & indication interface CoreReq coreReq; @@ -278,6 +236,13 @@ 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 +`endif + (* synthesize *) module mkCore#(CoreId coreId)(Core); let verbose = False; @@ -456,7 +421,7 @@ module mkCore#(CoreId coreId)(Core); globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag); `ifdef PERFORMANCE_MONITORING EventsCore events = unpack (0); - events.evt_REDIRECT = True; + events.evt_REDIRECT = 1; aw_events[1] <= events; `endif endmethod @@ -1138,11 +1103,15 @@ module mkCore#(CoreId coreId)(Core); // ================================================================ // Performance counters - Vector #(1, Bit #(Counter_Width)) null_evt = replicate (0); - Vector #(31, Bit #(Counter_Width)) core_evts_vec = to_large_vector (aw_events_reg); - Vector #(16, Bit #(Counter_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); - Vector #(16, Bit #(Counter_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); - Vector #(32, Bit #(Counter_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); + rule report_commit_events; + aw_events[2] <= commitStage.events; + endrule + + Vector #(1, Bit #(Report_Width)) null_evt = replicate (0); + Vector #(31, Bit #(Report_Width)) core_evts_vec = to_large_vector (aw_events_reg); + Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); + Vector #(16, Bit #(Report_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); + Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); let events = append (null_evt, core_evts_vec); events = append (events, imem_evts_vec); diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 58490ec..49055a6 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -185,7 +185,7 @@ interface CsrFile; `endif `ifdef PERFORMANCE_MONITORING (* always_ready, always_enabled *) - method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Counter_Width)) evts); + method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Report_Width)) evts); `endif endinterface @@ -246,11 +246,11 @@ 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#(Counter_Width)) evts); + 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, No_Of_Evts) perf_counters <- mkPerfCounters; + 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; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index f7b529e..51ccd48 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; @@ -1060,7 +1068,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 +1077,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); SupCnt lrCnt = 0; SupCnt scCnt = 0; SupCnt amoCnt = 0; -`endif `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); @@ -1170,7 +1176,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); comUserInstCnt = comUserInstCnt + 1; // user space inst end -`ifdef PERF_COUNT // performance counter case(x.iType) Br: brCnt = brCnt + 1; @@ -1182,7 +1187,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Sc: scCnt = scCnt + 1; Amo: amoCnt = amoCnt + 1; endcase -`endif end end end @@ -1235,6 +1239,19 @@ 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 = 0; // XXX + events.evt_LOAD = ldCnt; + events.evt_STORE = stCnt; + events.evt_LR = lrCnt; + events.evt_SC = scCnt; + events.evt_AMO = amoCnt; + events_reg <= events; +`endif `ifdef RVFI rvfiQ.enq(rvfis); traceCnt <= traceCnt + zeroExtend(whichTrace); @@ -1309,6 +1326,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/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 34d5e2a..afca918 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1043,6 +1043,40 @@ function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERIC `ifdef PERFORMANCE_MONITORING typedef 96 No_Of_Evts; +typedef 8 Report_Width; typedef 64 Counter_Width; typedef 29 No_Of_Ctrs; + +typedef struct { + SupCnt evt_REDIRECT; + SupCnt evt_TLB_EXC; // TODO: Misleading name + 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; + SupCnt evt_D_BUSY_NO_CONSUME; + SupCnt evt_1_BUSY_NO_CONSUME; + SupCnt evt_2_BUSY_NO_CONSUME; + SupCnt evt_3_BUSY_NO_CONSUME; + SupCnt evt_IMPRECISE_SETBOUND; + SupCnt evt_UNREPRESENTABLE_CAP; + 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; `endif From 8a13b866d7080f667d4c83fc804dcf4555f40ec3 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 2 Dec 2020 15:31:49 +0000 Subject: [PATCH 14/41] Bump bluestuff to the one with generalised report width. --- libs/BlueStuff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index ebd9403..ad6e8b2 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit ebd9403e8651011fb722d297dd30c02f9195586e +Subproject commit ad6e8b2704bf6330000e2823ea525cb02312e147 From 1fb388fb183d664957521fb873d4a62e55b0e04c Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 3 Dec 2020 17:54:46 +0000 Subject: [PATCH 15/41] Count more things correctly. --- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 51ccd48..690d7e3 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -996,6 +996,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 @@ -1077,6 +1084,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); SupCnt lrCnt = 0; SupCnt scCnt = 0; SupCnt amoCnt = 0; + SupCnt shiftCnt = 0; + SupCnt muldivCnt = 0; + SupCnt auipcCnt = 0; + SupCnt fenceCnt = 0; `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); @@ -1176,8 +1187,24 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); comUserInstCnt = comUserInstCnt + 1; // user space inst end - // 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; @@ -1186,6 +1213,13 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Lr: lrCnt = lrCnt + 1; Sc: scCnt = scCnt + 1; Amo: amoCnt = amoCnt + 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 + Fence, FenceI, SFence: fenceCnt = fenceCnt + 1; // Some of these are "System" instructions. endcase end end @@ -1244,12 +1278,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); events.evt_BRANCH = brCnt; events.evt_JAL = jmpCnt; events.evt_JALR = jrCnt; - events.evt_AUIPC = 0; // XXX + 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_FENCE = fenceCnt; events_reg <= events; `endif `ifdef RVFI From 425c2778c01d2ed4b867036d9c987bd89ee546b7 Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 3 Dec 2020 17:55:03 +0000 Subject: [PATCH 16/41] Bump Bluestuff to get resetting in the Performance Monitor. --- libs/BlueStuff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index ad6e8b2..29332e8 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit ad6e8b2704bf6330000e2823ea525cb02312e147 +Subproject commit 29332e87fc3b2e4badf7edd727d29447d52f20ed From 5665d2e9cd08d41d34a339a9f1f0bb957f82b03c Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 4 Dec 2020 16:28:19 +0000 Subject: [PATCH 17/41] A more effective Fence count (as some fences go through as the Nop iType). --- src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 690d7e3..3d003c3 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -1219,8 +1219,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); if ((opcode == opcOp || opcode == opcOp32) && funct7 == opMULDIV) muldivCnt = muldivCnt + 1; end - Fence, FenceI, SFence: fenceCnt = fenceCnt + 1; // Some of these are "System" instructions. endcase + if (opcode == opcMiscMem && funct3 == fnFENCE) fenceCnt = fenceCnt + 1; end end end From 3f60c046f71e80ee2206cf008be50e0ce6337671 Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 4 Dec 2020 16:51:44 +0000 Subject: [PATCH 18/41] Fix typo. --- src_Core/Core/CoreW.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/Core/CoreW.bsv b/src_Core/Core/CoreW.bsv index ffd1128..06e3d4a 100644 --- a/src_Core/Core/CoreW.bsv +++ b/src_Core/Core/CoreW.bsv @@ -500,7 +500,7 @@ module mkCoreW_Synth #(Reset dm_power_on_reset) interface core_external_interrupt_sources = core.core_external_interrupt_sources; method nmi_req = core.nmi_req; `ifdef RVFI_DII - interface rvfi_dii_server = core.Toooba_RVFI_DII_Server rvfi_dii_server; + interface rvfi_dii_server = core.rvfi_dii_server; `endif `ifdef INCLUDE_GDB_CONTROL interface dmi = core.dmi; From bdc2d494f2a74118f2e2dba440f9ab97f6d2aec3 Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 4 Dec 2020 17:12:26 +0000 Subject: [PATCH 19/41] Change name something that makes sense. --- src_Core/CPU/Core.bsv | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 32ea1f1..406e4a0 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -270,10 +270,10 @@ module mkCore#(CoreId coreId)(Core); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCore)) aw_events <- mkDWireOR (5, unpack (0)); - Reg #(EventsCore) aw_events_reg <- mkConfigReg(unpack(0)); - rule update_aw_events_reg; - aw_events_reg <= aw_events[0]; + Array #(Wire #(EventsCore)) hpm_core_events <- mkDWireOR (5, unpack (0)); + Reg #(EventsCore) hpm_core_events_reg <- mkConfigReg(unpack(0)); + rule update_hpm_core_events_reg; + hpm_core_events_reg <= hpm_core_events[0]; endrule `endif @@ -422,7 +422,7 @@ module mkCore#(CoreId coreId)(Core); `ifdef PERFORMANCE_MONITORING EventsCore events = unpack (0); events.evt_REDIRECT = 1; - aw_events[1] <= events; + hpm_core_events[1] <= events; `endif endmethod method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put; @@ -1104,11 +1104,11 @@ module mkCore#(CoreId coreId)(Core); // Performance counters rule report_commit_events; - aw_events[2] <= commitStage.events; + hpm_core_events[2] <= commitStage.events; endrule Vector #(1, Bit #(Report_Width)) null_evt = replicate (0); - Vector #(31, Bit #(Report_Width)) core_evts_vec = to_large_vector (aw_events_reg); + Vector #(31, Bit #(Report_Width)) core_evts_vec = to_large_vector (hpm_core_events_reg); Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); From d6243be1ddfe30f44733d3eee1b9dcf580267dbb Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 4 Dec 2020 18:34:56 +0000 Subject: [PATCH 20/41] Add a few more core performance counters. --- src_Core/CPU/Core.bsv | 4 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 20 +++++++-- .../procs/RV64G_OOO/MemExePipeline.bsv | 43 +++++++++++++++++++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 22 +++++----- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 406e4a0..46eee13 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1103,8 +1103,8 @@ module mkCore#(CoreId coreId)(Core); // ================================================================ // Performance counters - rule report_commit_events; - hpm_core_events[2] <= commitStage.events; + rule report_events; + hpm_core_events[2] <= unpack(pack(commitStage.events) | pack(coreFix.memExeIfc.events)); endrule Vector #(1, Bit #(Report_Width)) null_evt = replicate (0); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 3d003c3..a283d0b 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -703,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"); @@ -1088,6 +1092,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); 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); @@ -1208,11 +1216,16 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); 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; @@ -1286,6 +1299,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); 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 diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index a9206e7..77b131d 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -68,6 +68,10 @@ import LatencyTimer::*; import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; +`ifdef PERFORMANCE_MONITORING +import PerformanceMonitor::*; +import SpecialWires::*; +`endif import Cur_Cycle :: *; @@ -228,6 +232,9 @@ interface MemExePipeline; interface Server#(void, void) reconcile; `endif method Data getPerf(ExeStagePerfType t); +`ifdef PERFORMANCE_MONITORING + method EventsCore events; +`endif endinterface module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); @@ -265,6 +272,14 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); Count#(Data) exeFenceRelCnt <- mkCount(0); `endif +`ifdef PERFORMANCE_MONITORING + Array #(Wire #(EventsCore)) events_wire <- mkDWireOR (3, unpack (0)); + Reg #(EventsCore) events_reg <- mkReg(unpack(0)); + rule update_events_reg; + events_reg <= events_wire[0]; + endrule +`endif + // reservation station ReservationStationMem rsMem <- mkReservationStationMem; @@ -352,6 +367,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); if(inIfc.doStats) begin exeStMemLat.incr(zeroExtend(lat)); end +`endif +`ifdef PERFORMANCE_MONITORING + EventsCore events = unpack(0); + if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1; + events_wire[1] <= events; `endif // now figure out the data to be written Vector#(LineSzData, ByteEn) be = replicate(replicate(False)); @@ -372,6 +392,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); if(inIfc.doStats) begin exeStMemLat.incr(zeroExtend(lat)); end +`endif +`ifdef PERFORMANCE_MONITORING + EventsCore events = unpack(0); + if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1; + events_wire[1] <= events; `endif return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry endmethod @@ -672,6 +697,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); }; `else SBSearchRes sbRes = stb.search(info.paddr, info.shiftedBE); +`endif +`ifdef PERFORMANCE_MONITORING + EventsCore 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); @@ -711,11 +740,17 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); default: doAssert(False, "unknow stall reason"); endcase end +`endif +`ifdef PERFORMANCE_MONITORING + events.evt_LOAD_WAIT = 1; `endif end else begin doAssert(False, "load is stalled"); end +`ifdef PERFORMANCE_MONITORING + events_wire[0] <= events; +`endif endaction endfunction @@ -1286,6 +1321,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 + EventsCore events = unpack(0); + events.evt_SC_SUCCESS = 1; + events_wire[2] <= events; `endif endrule @@ -1518,4 +1558,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); default: 0; endcase); endmethod +`ifdef PERFORMANCE_MONITORING + method events = events_reg; +`endif endmodule diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index afca918..a76c7fc 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1049,7 +1049,7 @@ typedef 29 No_Of_Ctrs; typedef struct { SupCnt evt_REDIRECT; - SupCnt evt_TLB_EXC; // TODO: Misleading name + SupCnt evt_TRAP; SupCnt evt_BRANCH; SupCnt evt_JAL; SupCnt evt_JALR; @@ -1064,19 +1064,19 @@ typedef struct { SupCnt evt_FP; SupCnt evt_SC_SUCCESS; SupCnt evt_LOAD_WAIT; - SupCnt evt_STORE_WAIT; + SupCnt evt_STORE_WAIT; // XXX SupCnt evt_FENCE; - SupCnt evt_F_BUSY_NO_CONSUME; - SupCnt evt_D_BUSY_NO_CONSUME; - SupCnt evt_1_BUSY_NO_CONSUME; - SupCnt evt_2_BUSY_NO_CONSUME; - SupCnt evt_3_BUSY_NO_CONSUME; - SupCnt evt_IMPRECISE_SETBOUND; - SupCnt evt_UNREPRESENTABLE_CAP; + 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; + SupCnt evt_MEM_CAP_LOAD_TAG_SET; // XXX + SupCnt evt_MEM_CAP_STORE_TAG_SET; // XXX } EventsCore deriving (Bits, FShow); typedef TDiv#(SizeOf#(EventsCore),SizeOf#(SupCnt)) EventsCoreElements; `endif From 1bae03da9c2017a009f3c896bc626c7ceb828d0e Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 11 Dec 2020 15:47:04 +0000 Subject: [PATCH 21/41] Implement all the remaining core (not cache) memory stat counters. --- src_Core/CPU/Core.bsv | 6 ++- .../procs/RV64G_OOO/MemExePipeline.bsv | 54 ++++++++++--------- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 41 ++++++++++++-- 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 46eee13..88edf12 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1104,11 +1104,13 @@ module mkCore#(CoreId coreId)(Core); // Performance counters rule report_events; - hpm_core_events[2] <= unpack(pack(commitStage.events) | pack(coreFix.memExeIfc.events)); + hpm_core_events[2] <= unpack(pack(commitStage.events)); endrule Vector #(1, Bit #(Report_Width)) null_evt = replicate (0); - Vector #(31, Bit #(Report_Width)) core_evts_vec = to_large_vector (hpm_core_events_reg); + Vector #(31, Bit #(Report_Width)) mem_core_evts_vec = reverse(unpack({pack(coreFix.memExeIfc.events),0})); + Vector #(31, Bit #(Report_Width)) other_core_evts_vec = to_large_vector (hpm_core_events_reg); + Vector #(31, Bit #(Report_Width)) core_evts_vec = unpack(pack(mem_core_evts_vec) | pack(other_core_evts_vec)); Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 77b131d..e262e3e 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -68,6 +68,7 @@ import LatencyTimer::*; import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; +import CacheUtils::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; import SpecialWires::*; @@ -233,7 +234,7 @@ interface MemExePipeline; `endif method Data getPerf(ExeStagePerfType t); `ifdef PERFORMANCE_MONITORING - method EventsCore events; + method EventsCoreMem events; `endif endinterface @@ -244,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); @@ -252,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 @@ -273,8 +276,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCore)) events_wire <- mkDWireOR (3, unpack (0)); - Reg #(EventsCore) events_reg <- mkReg(unpack(0)); + Array #(Wire #(EventsCoreMem)) events_wire <- mkDWireOR (4, unpack (0)); + Reg #(EventsCoreMem) events_reg <- mkReg(unpack(0)); rule update_events_reg; events_reg <= events_wire[0]; endrule @@ -339,12 +342,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 = truncate(lat); + events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1:0; + events_wire[1] <= events; `endif endmethod method Action respLrScAmo(DProcReqId id, MemTaggedData d); @@ -361,23 +370,25 @@ 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 - EventsCore events = unpack(0); + EventsCoreMem events = unpack(0); if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1; - events_wire[1] <= events; + events.evt_STORE_WAIT = truncate(lat); + events.evt_MEM_CAP_STORE_TAG_SET = (waitSt.shiftedData.tag) ? 1:0; + events_wire[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 @@ -386,17 +397,19 @@ 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 - EventsCore events = unpack(0); + EventsCoreMem events = unpack(0); if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1; - events_wire[1] <= events; + events.evt_STORE_WAIT = truncate(lat); + events.evt_MEM_CAP_STORE_TAG_SET = pack(zeroExtend(countOnes(pack(e.line.tag)))); + events_wire[2] <= events; `endif return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry endmethod @@ -699,7 +712,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); SBSearchRes sbRes = stb.search(info.paddr, info.shiftedBE); `endif `ifdef PERFORMANCE_MONITORING - EventsCore events = unpack(0); + EventsCoreMem events = unpack(0); if (pack(info.shiftedBE) == -1) events.evt_MEM_CAP_LOAD = 1; `endif // search LSQ @@ -724,10 +737,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 @@ -740,9 +751,6 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); default: doAssert(False, "unknow stall reason"); endcase end -`endif -`ifdef PERFORMANCE_MONITORING - events.evt_LOAD_WAIT = 1; `endif end else begin @@ -1131,10 +1139,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 @@ -1158,10 +1164,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 @@ -1323,9 +1327,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); end `endif `ifdef PERFORMANCE_MONITORING - EventsCore events = unpack(0); + EventsCoreMem events = unpack(0); events.evt_SC_SUCCESS = 1; - events_wire[2] <= events; + events_wire[3] <= events; `endif endrule diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index a76c7fc..e4e691f 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; @@ -1064,7 +1063,7 @@ typedef struct { SupCnt evt_FP; SupCnt evt_SC_SUCCESS; SupCnt evt_LOAD_WAIT; - SupCnt evt_STORE_WAIT; // XXX + SupCnt evt_STORE_WAIT; // XXX Don't think we can make this make sense for Toooba. Store delays overlap so we can't get a single number that tells us the cycles spent waiting for store delays. Toooba seems to measure the delay of each store independently. Maybe we could do this with ~8bits per element? One report per cycle? SupCnt evt_FENCE; SupCnt evt_F_BUSY_NO_CONSUME; // XXX SupCnt evt_D_BUSY_NO_CONSUME; // XXX @@ -1075,8 +1074,42 @@ typedef struct { SupCnt evt_UNREPRESENTABLE_CAP; // XXX SupCnt evt_MEM_CAP_LOAD; SupCnt evt_MEM_CAP_STORE; - SupCnt evt_MEM_CAP_LOAD_TAG_SET; // XXX - SupCnt evt_MEM_CAP_STORE_TAG_SET; // XXX + 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 From 19a07882ab17e71b68fda8d69e46eebdeb0ef2d5 Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 11 Dec 2020 16:44:59 +0000 Subject: [PATCH 22/41] CSome style cleanups from chat with Alexandre. --- src_Core/CPU/Core.bsv | 6 +++++- src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv | 11 +++++------ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 88edf12..0d5e0c1 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -241,6 +241,10 @@ instance BitVectorable #(EventsCore, SizeOf#(SupCnt), EventsCoreElements) provis 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 `endif (* synthesize *) @@ -1108,7 +1112,7 @@ module mkCore#(CoreId coreId)(Core); endrule Vector #(1, Bit #(Report_Width)) null_evt = replicate (0); - Vector #(31, Bit #(Report_Width)) mem_core_evts_vec = reverse(unpack({pack(coreFix.memExeIfc.events),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_reg); Vector #(31, Bit #(Report_Width)) core_evts_vec = unpack(pack(mem_core_evts_vec) | pack(other_core_evts_vec)); Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index e262e3e..819aefd 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -351,8 +351,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif `ifdef PERFORMANCE_MONITORING EventsCoreMem events = unpack(0); - events.evt_LOAD_WAIT = truncate(lat); - events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1:0; + events.evt_LOAD_WAIT = saturating_truncate(lat); + events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1 : 0; events_wire[1] <= events; `endif endmethod @@ -380,8 +380,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `ifdef PERFORMANCE_MONITORING EventsCoreMem events = unpack(0); if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1; - events.evt_STORE_WAIT = truncate(lat); - events.evt_MEM_CAP_STORE_TAG_SET = (waitSt.shiftedData.tag) ? 1:0; + events.evt_STORE_WAIT = saturating_truncate(lat); + events.evt_MEM_CAP_STORE_TAG_SET = (waitSt.shiftedData.tag) ? 1 : 0; events_wire[2] <= events; `endif // now figure out the data to be written @@ -407,8 +407,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `ifdef PERFORMANCE_MONITORING EventsCoreMem events = unpack(0); if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1; - events.evt_STORE_WAIT = truncate(lat); - events.evt_MEM_CAP_STORE_TAG_SET = pack(zeroExtend(countOnes(pack(e.line.tag)))); + events.evt_STORE_WAIT = saturating_truncate(lat); events_wire[2] <= events; `endif return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index e4e691f..83d3f00 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1063,7 +1063,7 @@ typedef struct { SupCnt evt_FP; SupCnt evt_SC_SUCCESS; SupCnt evt_LOAD_WAIT; - SupCnt evt_STORE_WAIT; // XXX Don't think we can make this make sense for Toooba. Store delays overlap so we can't get a single number that tells us the cycles spent waiting for store delays. Toooba seems to measure the delay of each store independently. Maybe we could do this with ~8bits per element? One report per cycle? + SupCnt evt_STORE_WAIT; SupCnt evt_FENCE; SupCnt evt_F_BUSY_NO_CONSUME; // XXX SupCnt evt_D_BUSY_NO_CONSUME; // XXX From 6768bf92c77fe93de6f51fafce95043112807b73 Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 11 Dec 2020 17:16:38 +0000 Subject: [PATCH 23/41] iMove the store count to the pipeline write. It appeared to be counting capabilities in store counter flushes, which, FI think, is not quite what was intended in this counter. --- src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 819aefd..1f34878 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -276,7 +276,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCoreMem)) events_wire <- mkDWireOR (4, unpack (0)); + Array #(Wire #(EventsCoreMem)) events_wire <- mkDWireOR (5, unpack (0)); Reg #(EventsCoreMem) events_reg <- mkReg(unpack(0)); rule update_events_reg; events_reg <= events_wire[0]; @@ -381,7 +381,6 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); EventsCoreMem events = unpack(0); if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1; events.evt_STORE_WAIT = saturating_truncate(lat); - events.evt_MEM_CAP_STORE_TAG_SET = (waitSt.shiftedData.tag) ? 1 : 0; events_wire[2] <= events; `endif // now figure out the data to be written @@ -547,6 +546,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_wire[4] <= events; +`endif end CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC)); From 295b8788365705319ea597a89474549b560b968b Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 14 Dec 2020 10:50:23 +0000 Subject: [PATCH 24/41] Fix negated CYCLE/INSTRET logic for ASR and make less confusing --- libs/BlueStuff | 2 +- libs/TagController | 2 +- src_Core/RISCY_OOO/procs/lib/Exec.bsv | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index 29332e8..baf31fb 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit 29332e87fc3b2e4badf7edd727d29447d52f20ed +Subproject commit baf31fb28835f3176163f1c160e0177cb85a3f11 diff --git a/libs/TagController b/libs/TagController index f4c5348..aaa23bc 160000 --- a/libs/TagController +++ b/libs/TagController @@ -1 +1 @@ -Subproject commit f4c53481887564f6e8fcb9b8f2bf94f56b7afb07 +Subproject commit aaa23bc2469bcde6c6b6e315f94f8ae83c0c14f3 diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index 0d914a9..3218a61 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 From f6569e2d14c623847910b661f0108cf5f3229a90 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 14 Dec 2020 10:51:57 +0000 Subject: [PATCH 25/41] Actually do the intended fix, not just inverting the variable --- src_Core/RISCY_OOO/procs/lib/Exec.bsv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index 3218a61..352cc75 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -516,12 +516,12 @@ function Maybe#(Trap) checkForException( Bool read_only = (csr [11:10] == 2'b11); Bool write_deny = (writes_csr && read_only); Bool asr_allow = getHardPerms(pcc).accessSysRegs - //|| ((csr_addr_hpmcounter3 <= csr) && (csr <= csr_addr_hpmcounter31) && writes_csr) // TODO seems these aren't implemented? + //|| ((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); + || (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)); From 982758cae7124740bf228bb96556e6973ba5b4ef Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 14 Dec 2020 12:13:34 +0000 Subject: [PATCH 26/41] Bump to version of Bluestuff that has the saturating truncate function. --- libs/BlueStuff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index baf31fb..dfd4e64 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit baf31fb28835f3176163f1c160e0177cb85a3f11 +Subproject commit dfd4e647b798a1200fcce3cd265c11935a3a5715 From 73d25bf8f5ed8f6910d3736dd51615f022d4a16b Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 14 Dec 2020 18:10:06 +0000 Subject: [PATCH 27/41] Support performance counters (hopefully) in the caches. The DCache should be fully wired up. --- src_Core/CPU/Core.bsv | 6 +- src_Core/RISCY_OOO/coherence/src/CCTypes.bsv | 20 +++ src_Core/RISCY_OOO/coherence/src/L1Bank.bsv | 134 +++++++++++++------ src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv | 6 + 4 files changed, 125 insertions(+), 41 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 0d5e0c1..25544b6 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -245,6 +245,10 @@ instance BitVectorable #(EventsCoreMem, SizeOf#(HpmRpt), EventsCoreMemElements) 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 *) @@ -1116,7 +1120,7 @@ module mkCore#(CoreId coreId)(Core); Vector #(31, Bit #(Report_Width)) other_core_evts_vec = to_large_vector (hpm_core_events_reg); Vector #(31, Bit #(Report_Width)) core_evts_vec = unpack(pack(mem_core_evts_vec) | pack(other_core_evts_vec)); Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); - Vector #(16, Bit #(Report_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events); + Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); let events = append (null_evt, core_evts_vec); 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/L1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv index 3e4adec..59dd7a9 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 SpecialWires::*; +`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,81 @@ 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 #(Wire #(EventsCache)) perf_events <- mkDWireOR (2, unpack (0)); + Reg #(EventsCache) perf_events_reg <- mkConfigReg(unpack(0)); + rule update_events_reg; + perf_events_reg <= perf_events[0]; + endrule +`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 +320,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), " ; ", @@ -849,10 +893,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 +1131,9 @@ module mkL1Bank#( default: 0; endcase); endmethod +`ifdef PERFORMANCE_MONITORING + method EventsCache events = perf_events_reg; +`endif endmodule @@ -1320,4 +1365,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/procs/lib/L1CoCache.bsv b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv index 26e652a..9edaaaa 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; From b6a397df524ca98fdeb2bd3547b8ed97e14af3be Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 15 Dec 2020 14:49:16 +0000 Subject: [PATCH 28/41] Support for ICache stat counters. --- libs/TagController | 2 +- src_Core/CPU/Core.bsv | 2 +- src_Core/RISCY_OOO/coherence/src/IBank.bsv | 42 ++++++++++++++++++--- src_Core/RISCY_OOO/coherence/src/L1Bank.bsv | 2 - src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv | 6 +++ 5 files changed, 44 insertions(+), 10 deletions(-) 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 25544b6..1066279 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1119,7 +1119,7 @@ module mkCore#(CoreId coreId)(Core); 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_reg); Vector #(31, Bit #(Report_Width)) core_evts_vec = unpack(pack(mem_core_evts_vec) | pack(other_core_evts_vec)); - Vector #(16, Bit #(Report_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events); + Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (iMem.events); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); Vector #(32, Bit #(Report_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts); diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index 1fcf4fb..b65da88 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 SpecialWires::*; +`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,54 @@ 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 #(Wire #(EventsCache)) perf_events <- mkDWireOR (2, unpack (0)); + Reg #(EventsCache) perf_events_reg <- mkConfigReg(unpack(0)); + rule update_events_reg; + perf_events_reg <= perf_events[0]; + endrule +`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); @@ -377,10 +406,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 @@ -818,6 +845,9 @@ module mkIBank#( default: 0; endcase); endmethod +`ifdef PERFORMANCE_MONITORING + method EventsCache events = perf_events_reg; +`endif endmodule diff --git a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv index 59dd7a9..4dc503b 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv @@ -478,10 +478,8 @@ endfunction fshow(slot), " ; ", fshow(cRqToP) ); -`ifdef PERF_COUNT // performance counter: start miss timer latTimer.start(n); -`endif endrule // last stage of pipeline: process req diff --git a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv index 9edaaaa..8f87367 100644 --- a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv +++ b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv @@ -372,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; @@ -442,6 +445,9 @@ module mkICoCache(ICoCache); `endif endmethod endinterface +`ifdef PERFORMANCE_MONITORING + method EventsCache events = cache.events; +`endif interface to_parent = cache.to_parent; From d64df09d82da492ee14d66bac395e726a040cdf7 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 15 Dec 2020 16:18:18 +0000 Subject: [PATCH 29/41] Bump to version with DRegOR. --- libs/BlueStuff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/BlueStuff b/libs/BlueStuff index dfd4e64..c483104 160000 --- a/libs/BlueStuff +++ b/libs/BlueStuff @@ -1 +1 @@ -Subproject commit dfd4e647b798a1200fcce3cd265c11935a3a5715 +Subproject commit c483104aa7f8bd2a1585e747dd6f5dab7d82e17f From 17a7a32092e241d14cdc6f1be8243b775e8aac81 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 15 Dec 2020 16:18:36 +0000 Subject: [PATCH 30/41] Use DRegOR instead of immitating latching behaviour. --- src_Core/CPU/Core.bsv | 10 +++------ src_Core/RISCY_OOO/coherence/src/IBank.bsv | 10 +++------ src_Core/RISCY_OOO/coherence/src/L1Bank.bsv | 10 +++------ .../procs/RV64G_OOO/MemExePipeline.bsv | 22 ++++++++----------- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 1066279..0085c35 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -61,7 +61,7 @@ import VerificationPacket::*; import Performance::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; -import SpecialWires::*; +import BlueUtils::*; `endif import HasSpecBits::*; import Exec::*; @@ -278,11 +278,7 @@ module mkCore#(CoreId coreId)(Core); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCore)) hpm_core_events <- mkDWireOR (5, unpack (0)); - Reg #(EventsCore) hpm_core_events_reg <- mkConfigReg(unpack(0)); - rule update_hpm_core_events_reg; - hpm_core_events_reg <= hpm_core_events[0]; - endrule + Array #(Reg #(EventsCore)) hpm_core_events <- mkDRegOR (5, unpack (0)); `endif // ================================================================ @@ -1117,7 +1113,7 @@ module mkCore#(CoreId coreId)(Core); 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_reg); + 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)); Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (iMem.events); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index b65da88..ef1bf10 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -59,7 +59,7 @@ import LatencyTimer::*; import RandomReplace::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; -import SpecialWires::*; +import BlueUtils::*; `endif export ICRqStuck(..); @@ -193,11 +193,7 @@ module mkIBank#( Count#(Data) ldMissLat <- mkCount(0); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCache)) perf_events <- mkDWireOR (2, unpack (0)); - Reg #(EventsCache) perf_events_reg <- mkConfigReg(unpack(0)); - rule update_events_reg; - perf_events_reg <= perf_events[0]; - endrule + Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (2, unpack (0)); `endif function Action incrReqCnt; action @@ -846,7 +842,7 @@ module mkIBank#( endcase); endmethod `ifdef PERFORMANCE_MONITORING - method EventsCache events = perf_events_reg; + 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 4dc503b..9e918f3 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv @@ -62,7 +62,7 @@ import LatencyTimer::*; import RandomReplace::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; -import SpecialWires::*; +import BlueUtils::*; `endif export L1CRqStuck(..); @@ -212,11 +212,7 @@ module mkL1Bank#( Count#(Data) amoMissLat <- mkCount(0); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCache)) perf_events <- mkDWireOR (2, unpack (0)); - Reg #(EventsCache) perf_events_reg <- mkConfigReg(unpack(0)); - rule update_events_reg; - perf_events_reg <= perf_events[0]; - endrule + Array #(Reg #(EventsCache)) perf_events <- mkDRegOR (2, unpack (0)); `endif function Action incrReqCnt(MemOp op); action @@ -1130,7 +1126,7 @@ endfunction endcase); endmethod `ifdef PERFORMANCE_MONITORING - method EventsCache events = perf_events_reg; + method EventsCache events = perf_events[0]; `endif endmodule diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 1f34878..39ceb05 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -71,7 +71,7 @@ import ISA_Decls_CHERI::*; import CacheUtils::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; -import SpecialWires::*; +import BlueUtils::*; `endif import Cur_Cycle :: *; @@ -276,11 +276,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif `ifdef PERFORMANCE_MONITORING - Array #(Wire #(EventsCoreMem)) events_wire <- mkDWireOR (5, unpack (0)); - Reg #(EventsCoreMem) events_reg <- mkReg(unpack(0)); - rule update_events_reg; - events_reg <= events_wire[0]; - endrule + Array #(Reg #(EventsCoreMem)) events_reg <- mkDRegOR (5, unpack (0)); `endif // reservation station @@ -353,7 +349,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); EventsCoreMem events = unpack(0); events.evt_LOAD_WAIT = saturating_truncate(lat); events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1 : 0; - events_wire[1] <= events; + events_reg[1] <= events; `endif endmethod method Action respLrScAmo(DProcReqId id, MemTaggedData d); @@ -381,7 +377,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); EventsCoreMem events = unpack(0); if (waitSt.shiftedBE == -1) events.evt_MEM_CAP_STORE = 1; events.evt_STORE_WAIT = saturating_truncate(lat); - events_wire[2] <= events; + events_reg[2] <= events; `endif // now figure out the data to be written Vector#(LineSzData, ByteEn) be = replicate(replicate(False)); @@ -407,7 +403,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); EventsCoreMem events = unpack(0); if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1; events.evt_STORE_WAIT = saturating_truncate(lat); - events_wire[2] <= events; + events_reg[2] <= events; `endif return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry endmethod @@ -549,7 +545,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `ifdef PERFORMANCE_MONITORING EventsCoreMem events = unpack(0); events.evt_MEM_CAP_STORE_TAG_SET = (d.tag) ? 1 : 0; - events_wire[4] <= events; + events_reg[4] <= events; `endif end @@ -760,7 +756,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); doAssert(False, "load is stalled"); end `ifdef PERFORMANCE_MONITORING - events_wire[0] <= events; + events_reg[0] <= events; `endif endaction endfunction @@ -1332,7 +1328,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `ifdef PERFORMANCE_MONITORING EventsCoreMem events = unpack(0); events.evt_SC_SUCCESS = 1; - events_wire[3] <= events; + events_reg[3] <= events; `endif endrule @@ -1566,6 +1562,6 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); endcase); endmethod `ifdef PERFORMANCE_MONITORING - method events = events_reg; + method events = events_reg[0]; `endif endmodule From fa9931b64ccd26004848ae1a48fd54b408e6b38a Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 15 Dec 2020 18:16:21 +0000 Subject: [PATCH 31/41] Implement a couple Cache counters in the LLCache. These aren't too useful... We don't seem to have normal counters for loads and stores in the baseline. --- src_Core/CPU/Core.bsv | 10 ++++ src_Core/CPU/Proc.bsv | 8 +++ src_Core/RISCY_OOO/coherence/src/IBank.bsv | 4 -- src_Core/RISCY_OOO/coherence/src/LLBank.bsv | 65 ++++++++++++--------- src_Core/RISCY_OOO/procs/lib/LLCache.bsv | 12 +++- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 8 +-- 6 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 0085c35..8b59ae8 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -216,6 +216,9 @@ interface Core; method Bit#(32) debugRename; `endif +`ifdef PERFORMANCE_MONITORING + method Action events_llc(EventsCache events); +`endif endinterface // fixpoint to instantiate modules @@ -1107,6 +1110,7 @@ module mkCore#(CoreId coreId)(Core); // ================================================================ // Performance counters + Reg#(EventsCache) events_llc_reg <- mkRegU; rule report_events; hpm_core_events[2] <= unpack(pack(commitStage.events)); endrule @@ -1118,11 +1122,13 @@ module mkCore#(CoreId coreId)(Core); Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (iMem.events); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); 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); 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); (* fire_when_enabled, no_implicit_conditions *) rule rl_send_perf_evts; @@ -1522,4 +1528,8 @@ module mkCore#(CoreId coreId)(Core); endmethod `endif +`ifdef PERFORMANCE_MONITORING + method events_llc = events_llc_reg._write; +`endif + endmodule diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index d3af7d3..d65e6e4 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -188,6 +188,14 @@ module mkProc (Proc_IFC); statReqs.deq; endrule +`ifdef PERFORMANCE_MONITORING + rule broadcastPerfEvents; + for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin + core[j].events_llc(llc.events); + end + endrule +`endif + // ================================================================ // Stub out deadlock and renameDebug interfaces diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index ef1bf10..a1aed8b 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -252,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), " ; ", @@ -640,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")); 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/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 83d3f00..8b13ae1 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1041,10 +1041,10 @@ 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 96 No_Of_Evts; -typedef 8 Report_Width; -typedef 64 Counter_Width; -typedef 29 No_Of_Ctrs; +typedef 112 No_Of_Evts; +typedef 8 Report_Width; +typedef 64 Counter_Width; +typedef 29 No_Of_Ctrs; typedef struct { SupCnt evt_REDIRECT; From 4131dcd0734bdf036a98e1c689b3d0912d2f3cd8 Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 17 Dec 2020 12:37:45 +0000 Subject: [PATCH 32/41] Cause two surprising conditions to not throw slave errors as this is not specified and causes kernel panics. Hopefully the details of what should happen in these cases is correct, but we shall see... --- src_Core/PLIC/PLIC.bsv | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index 32d9465..3e7ec60 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -362,18 +362,17 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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) vrg_source_busy [max_id] <= True; // Set vrg_source_busy even if there was an error. 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); @@ -530,7 +529,6 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) cur_cycle); $display (" Completion message from target %0d to source %0d", target_id, source_id); $display (" Ignoring"); - bresp = SLVERR; end end else From bab989d6d25683196e22d8a9e194dbe75df10def Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 17 Dec 2020 12:38:52 +0000 Subject: [PATCH 33/41] Support for stat counters from the tag controller. The order of the events is very not tested; 50% chance of being correct. --- src_Core/CPU/Core.bsv | 5 +++++ src_Core/CPU/Proc.bsv | 6 ++++++ src_Core/CPU/Proc_IFC.bsv | 5 +++++ src_Core/Core/CoreW.bsv | 14 ++++++++++++++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 2 +- 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 8b59ae8..b87a303 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -218,6 +218,7 @@ interface Core; `ifdef PERFORMANCE_MONITORING method Action events_llc(EventsCache events); + method Action events_tgc(EventsCache events); `endif endinterface @@ -1111,6 +1112,7 @@ module mkCore#(CoreId coreId)(Core); // 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 @@ -1123,12 +1125,14 @@ module mkCore#(CoreId coreId)(Core); Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); 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; @@ -1530,6 +1534,7 @@ module mkCore#(CoreId coreId)(Core); `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/Proc.bsv b/src_Core/CPU/Proc.bsv index d65e6e4..e8464b6 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -189,9 +189,11 @@ module mkProc (Proc_IFC); 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 @@ -356,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 d9eaede..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 :: *; @@ -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 06e3d4a..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 :: *; @@ -172,6 +173,19 @@ module mkCoreW #(Reset dm_power_on_reset) // 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 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; diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 8b13ae1..4f69c89 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -1041,7 +1041,7 @@ 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 112 No_Of_Evts; +typedef 128 No_Of_Evts; typedef 8 Report_Width; typedef 64 Counter_Width; typedef 29 No_Of_Ctrs; From 4dd0a73051e183f61d0b670a6335f2321b70030d Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Thu, 17 Dec 2020 15:02:05 +0000 Subject: [PATCH 34/41] Port to internal AXI interfaces for the debug module. --- src_Core/Debug_Module/DM_System_Bus.bsv | 14 ++++++-------- src_Core/Debug_Module/Debug_Module.bsv | 8 ++++---- src_SSITH_P3/src_BSV/P3_Core.bsv | 7 ++++--- 3 files changed, 14 insertions(+), 15 deletions(-) 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_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); From 4ddcaff497f20f12d1cfeca63b01b1f31e23cfff Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 17 Dec 2020 16:52:45 +0000 Subject: [PATCH 35/41] Support for data TLB counters. --- src_Core/CPU/Core.bsv | 3 +- src_Core/RISCY_OOO/procs/lib/DTlb.bsv | 46 +++++++++++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index b87a303..647d5fe 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1122,7 +1122,8 @@ module mkCore#(CoreId coreId)(Core); 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)); Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (iMem.events); - Vector #(16, Bit #(Report_Width)) dmem_evts_vec = to_large_vector (dMem.events); + 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); 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 From f86d4d9dc0394b7e11f637ad53f4a355b11a14e6 Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 17 Dec 2020 17:57:43 +0000 Subject: [PATCH 36/41] Add counter support to ITLB. --- src_Core/CPU/Core.bsv | 3 +- src_Core/RISCY_OOO/procs/lib/ITlb.bsv | 47 ++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 647d5fe..eee9b05 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1121,7 +1121,8 @@ module mkCore#(CoreId coreId)(Core); 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)); - Vector #(16, Bit #(Report_Width)) imem_evts_vec = to_large_vector (iMem.events); + 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); 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 From 92ca72a6e201c7e6408fc28af101dfb6c03c75eb Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Fri, 18 Dec 2020 17:55:18 +0000 Subject: [PATCH 37/41] Fix build error by providing default. --- src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index f941ee9..084990e 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -223,7 +223,7 @@ function TlbPermissionCheck hasVMPermission( end end - Exception excCode; + Exception excCode = excLoadPageFault; // Unused default. Just choose one valid option. // check execute/read/write permission case(access) From e3f94224de798eb142c71aca9efecb0c646bf2cc Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 21 Dec 2020 13:03:13 +0000 Subject: [PATCH 38/41] Revert "Cause two surprising conditions to not throw slave errors as this is not" This reverts commit 4131dcd0734bdf036a98e1c689b3d0912d2f3cd8. --- src_Core/PLIC/PLIC.bsv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index 3e7ec60..32d9465 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -362,17 +362,18 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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) vrg_source_busy [max_id] <= True; // Set vrg_source_busy even if there was an error. 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); @@ -529,6 +530,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) cur_cycle); $display (" Completion message from target %0d to source %0d", target_id, source_id); $display (" Ignoring"); + bresp = SLVERR; end end else From 6b55d30a8e0c7fca7c59ad3e10a6a47369c80d6b Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 21 Dec 2020 13:29:58 +0000 Subject: [PATCH 39/41] PLIC: Restore upstream whitespace --- src_Core/PLIC/PLIC.bsv | 478 ++++++++++++++++++++--------------------- 1 file changed, 239 insertions(+), 239 deletions(-) diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index 32d9465..18e7a5b 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; @@ -113,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); @@ -166,7 +166,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) // 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) @@ -179,42 +179,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, Svcing %0d", + max_prio, vrg_target_threshold [target_id], max_id, vrg_servicing_source [target_id]); + end endaction endfunction @@ -223,25 +223,25 @@ 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; + vrg_servicing_source [target_id] <= 0; 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; slavePortShim.clear; @@ -260,8 +260,8 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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; @@ -269,134 +269,134 @@ 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 (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); - 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 + end + 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); @@ -408,9 +408,9 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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,126 +424,126 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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. 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 = zeroExtend (vrg_servicing_source [target_id]); - 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 (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; 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 @@ -553,10 +553,10 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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 @@ -565,18 +565,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 // ================================================================ @@ -584,12 +584,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 // ================================================================ @@ -610,18 +610,18 @@ 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 From ac6244181a531b86a8f5f54e5b98ac85e97d64f1 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 21 Dec 2020 13:26:46 +0000 Subject: [PATCH 40/41] PLIC: Allow multiple interrupts to be claimed but not completed Whilst the current PLIC spec is hard to decipher, the older v1.9 privileged spec is clearer. The intent is that each interrupt is independent and so claims and completions can be overlapped (e.g. as done by FreeBSD if deferring an interrupt handler). This is approximately expressed in the spec by: The PLIC can perform a claim at any time and the claim operation is not affected by the setting of the priority threshold register. ... The PLIC does not check whether the completion ID is the same as the last claim ID for that target. If the completion ID does not match an interrupt source that is currently enabled for the target, the completion is silently ignored. Thost last two sentences make it sound like the completion ID not matching the last claim ID is a thing to ignore, but in fact they are entirely independent statements. This can be confirmed by reading the source for the Rocket and QEMU PLICs, which have none of the stricter requirements of the Bluespec PLIC implementation. This should fix running FreeBSD after r362977, which started to correctly delay the completion of interrupts until after deferred handlers had completed (as opposed to after they had been queued). --- src_Core/PLIC/PLIC.bsv | 46 ++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index 18e7a5b..9f0e7a2 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -158,8 +158,6 @@ 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 @@ -212,8 +210,8 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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]); + $display (" MaxPri %0d, Thresh %0d, MaxId %0d", + max_prio, vrg_target_threshold [target_id], max_id); end endaction endfunction @@ -236,7 +234,6 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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; end for (Integer target_id = 0; target_id < n_targets; target_id = target_id + 1) @@ -362,26 +359,15 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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; + if (max_id != 0) begin + vrg_source_ip [max_id] <= False; + vrg_source_busy [max_id] <= True; + rdata = changeWidth (max_id); 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); - 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 + 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; @@ -515,22 +501,20 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) // Actual memory-write-data is irrelevant. 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_source_id) source_id = truncate (wdata32); if (target_id <= fromInteger (n_targets - 1)) begin - if (vrg_source_busy [source_id]) begin + if ( (source_id <= fromInteger (n_sources)) + && vvrg_ie [target_id][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; + 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 From 4a0c8fe7d2e020051ca1ca0f5a42b47f60ebd363 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 21 Dec 2020 13:37:01 +0000 Subject: [PATCH 41/41] PLIC: Update comment after previous commit --- src_Core/PLIC/PLIC.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/PLIC/PLIC.bsv b/src_Core/PLIC/PLIC.bsv index 9f0e7a2..6dc3da9 100644 --- a/src_Core/PLIC/PLIC.bsv +++ b/src_Core/PLIC/PLIC.bsv @@ -498,7 +498,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority)) 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 = truncate (wdata32);