From 60f12a6f6034035b94ba00dd9abef72f149cd56f Mon Sep 17 00:00:00 2001 From: Matthew <106996253+Matthew-Otto@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:27:06 -0500 Subject: [PATCH] Fix DPC write and DCSR Cause --- config/shared/debug.vh | 8 +++++++ src/debug/dmc.sv | 42 ++++++++++++++++++++------------- src/ifu/ifu.sv | 12 +++++----- src/privileged/csr.sv | 5 ++-- src/privileged/csrd.sv | 40 +++++++++++++++++-------------- src/privileged/privileged.sv | 5 ++-- src/wally/wallypipelinedcore.sv | 13 +++++----- 7 files changed, 74 insertions(+), 51 deletions(-) diff --git a/config/shared/debug.vh b/config/shared/debug.vh index d392665ce..0e53b6296 100755 --- a/config/shared/debug.vh +++ b/config/shared/debug.vh @@ -143,6 +143,14 @@ `define AAR64 3 `define AAR128 4 +// debug mode cause +`define CAUSE_EBREAK 3'h1 +`define CAUSE_TRIGGER 3'h2 +`define CAUSE_HALTREQ 3'h3 +`define CAUSE_STEP 3'h4 +`define CAUSE_RESETHALTREQ 3'h5 +`define CAUSE_GROUP 3'h6 + // Register Numbers (regno) // (Table 3.3) // 0x0000 – 0x0fff | CSRs. The “PC” can be accessed here through dpc. diff --git a/src/debug/dmc.sv b/src/debug/dmc.sv index 1a7d8404d..f944afe71 100644 --- a/src/debug/dmc.sv +++ b/src/debug/dmc.sv @@ -31,23 +31,26 @@ // In a multihart system, this module should be instantiated under wallypipelinedcore module dmc ( - input logic clk, reset, - input logic Step, - input logic HaltReq, // Initiates core halt - input logic ResumeReq, // Initiates core resume - input logic HaltOnReset, // Halts core immediately on hart reset - input logic AckHaveReset, // Clears HaveReset status + input logic clk, reset, + input logic Step, + input logic HaltReq, // Initiates core halt + input logic ResumeReq, // Initiates core resume + input logic HaltOnReset, // Halts core immediately on hart reset + input logic AckHaveReset, // Clears HaveReset status - output logic DebugMode, - output logic ResumeAck, // Signals Hart has been resumed - output logic HaveReset, // Signals Hart has been reset - output logic DebugStall, // Stall signal goes to hazard unit + output logic DebugMode, + output logic [2:0] DebugCause, // Reason Hart entered debug mode + output logic ResumeAck, // Signals Hart has been resumed + output logic HaveReset, // Signals Hart has been reset + output logic DebugStall, // Stall signal goes to hazard unit - output logic CapturePCNextF, // Store PCNextF in DPC when entering Debug Mode - output logic ForceDPCNextF, // Updates PCNextF with the current value of DPC - output logic ForceNOP // Fills the pipeline with NOP + output logic EnterDebugMode, // Store PCNextF in DPC when entering Debug Mode + output logic ExitDebugMode, // Updates PCNextF with the current value of DPC + output logic ForceNOP // Fills the pipeline with NOP ); - enum logic [1:0] {RUNNING, FLUSH, HALTED, RESUME} State; + `include "debug.vh" + +enum logic [1:0] {RUNNING, FLUSH, HALTED, RESUME} State; localparam NOP_CYCLE_DURATION = 0; logic [$clog2(NOP_CYCLE_DURATION+1)-1:0] Counter; @@ -62,20 +65,24 @@ module dmc ( assign DebugMode = (State != RUNNING); assign DebugStall = (State == HALTED); - assign CapturePCNextF = (State == FLUSH) & (Counter == 0); - assign ForceDPCNextF = (State == HALTED) & ResumeReq; + assign EnterDebugMode = (State == FLUSH) & (Counter == 0); + assign ExitDebugMode = (State == HALTED) & ResumeReq; assign ForceNOP = (State == FLUSH); always_ff @(posedge clk) begin if (reset) begin State <= HaltOnReset ? HALTED : RUNNING; + DebugCause <= HaltOnReset ? `CAUSE_RESETHALTREQ : 0; end else begin case (State) RUNNING : begin if (HaltReq) begin Counter <= 0; State <= FLUSH; - end + DebugCause <= `CAUSE_HALTREQ; + end + //else if (eBreak) TODO: halt on ebreak if DCSR bit is set + // DebugCause <= `CAUSE_EBREAK; end // fill the pipe with NOP before halting @@ -95,6 +102,7 @@ module dmc ( if (Step) begin Counter <= 0; State <= FLUSH; + DebugCause <= `CAUSE_STEP; end else begin State <= RUNNING; ResumeAck <= 1; diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index c7cfe7403..5e3aa8d36 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -98,10 +98,10 @@ module ifu import cvw::*; #(parameter cvw_t P) ( output logic ICacheAccess, // Report I$ read to performance counters output logic ICacheMiss, // Report I$ miss to performance counters // Debug Mode logic - (* mark_debug = "true" *)input logic ForceDPCNextF, - (* mark_debug = "true" *)input logic [P.XLEN-1:0] DPC, - (* mark_debug = "true" *)output logic [P.XLEN-1:0] PCNextF, // Next PCF, selected from Branch predictor, Privilege, or PC+2/4 - (* mark_debug = "true" *)input logic ForceNOP, + input logic ExitDebugMode, + input logic [P.XLEN-1:0] DPC, + output logic [P.XLEN-1:0] PCNextF, // Next PCF, selected from Branch predictor, Privilege, or PC+2/4 + input logic ForceNOP, // Debug scan chain input logic DebugScanEn, input logic DebugScanIn, @@ -327,8 +327,8 @@ module ifu import cvw::*; #(parameter cvw_t P) ( mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF); if (P.DEBUG_SUPPORTED) begin mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextFM); - assign PCNextF = ForceDPCNextF ? DPC : PCNextFM; - flopen #(P.XLEN) pcreg(clk, ~StallF | reset | ForceDPCNextF, PCNextF, PCF); + assign PCNextF = ExitDebugMode ? DPC : PCNextFM; + flopen #(P.XLEN) pcreg(clk, ~StallF | reset | ExitDebugMode, PCNextF, PCF); end else begin mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF); flopen #(P.XLEN) pcreg(clk, ~StallF | reset, PCNextF, PCF); diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 9f64c4dc4..5cea11a7b 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -94,10 +94,11 @@ module csr import cvw::*; #(parameter cvw_t P) ( output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level output logic BigEndianM, // memory access is big-endian based on privilege mode and STATUS register endian fields // Debug Mode output + input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, input logic [P.XLEN-1:0] PCNextF, - input logic CapturePCNextF, + input logic EnterDebugMode, // Debug scan chain input logic DebugSel, input logic [11:0] DebugRegAddr, @@ -304,7 +305,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( if (P.DEBUG_SUPPORTED) begin:csrd csrd #(P) csrd(.clk, .reset, .CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM, - .Step, .DPC, .PCNextF, .CapturePCNextF); + .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode); end else begin assign CSRDReadValM = '0; assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported diff --git a/src/privileged/csrd.sv b/src/privileged/csrd.sv index 1263b7fdc..38fefde5b 100644 --- a/src/privileged/csrd.sv +++ b/src/privileged/csrd.sv @@ -34,10 +34,11 @@ module csrd import cvw::*; #(parameter cvw_t P) ( output logic [P.XLEN-1:0] CSRDReadValM, output logic IllegalCSRDAccessM, + input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, input logic [P.XLEN-1:0] PCNextF, - input logic CapturePCNextF + input logic EnterDebugMode ); `include "debug.vh" @@ -45,8 +46,8 @@ module csrd import cvw::*; #(parameter cvw_t P) ( localparam DPC_ADDR = 12'h7B1; // Debug PC // TODO: these registers are only accessible from Debug Mode. - logic [31:0] DCSR_REGW; - logic [P.XLEN-1:0] DPC_REGW, DPCWriteVal; + logic [31:0] DCSR; + logic [P.XLEN-1:0] DPCWriteVal; logic WriteDCSRM; logic WriteDPCM; @@ -60,7 +61,7 @@ module csrd import cvw::*; #(parameter cvw_t P) ( const logic StepIE = 0; const logic StopCount = 0; const logic StopTime = 0; - logic [2:0] Cause; // TODO: give reason for entering debug mode + logic [2:0] Cause; const logic V = 0; const logic MPrvEn = 0; logic NMIP; // pending non-maskable interrupt @@ -68,34 +69,37 @@ module csrd import cvw::*; #(parameter cvw_t P) ( + always_ff @(posedge clk) begin + if (reset) begin + Prv <= 3; + Cause <= 0; + end else if (EnterDebugMode) begin + // Prv <= // hart priv mode + Cause <= DebugCause; + end else if (WriteDCSRM) begin + Prv <= CSRWriteValM[`PRV]; // TODO: overwrite hart privilege mode + end + end + assign WriteDCSRM = CSRWriteDM & (CSRAdrM == DCSR_ADDR); assign WriteDPCM = CSRWriteDM & (CSRAdrM == DPC_ADDR); - always_ff @(posedge clk) begin - if (reset) - Prv <= 3; - //else if (Halt) // TODO: trigger when hart enters debug mode - // Prv <= // hart priv mode - else if (WriteDCSRM) - Prv <= CSRWriteValM[`PRV]; // TODO: overwrite hart privilege mode - end - flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, {CSRWriteValM[`EBREAKM], CSRWriteValM[`EBREAKS], CSRWriteValM[`EBREAKU], CSRWriteValM[`STEP]}, {ebreakM, ebreakS, ebreakU, Step}); - assign DCSR_REGW = {4'b0100, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, + assign DCSR = {4'b0100, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv}; - assign DPCWriteVal = CapturePCNextF ? PCNextF : CSRWriteValM; - flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | CapturePCNextF, DPCWriteVal, DPC_REGW); + assign DPCWriteVal = EnterDebugMode ? PCNextF : CSRWriteValM; + flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); always_comb begin CSRDReadValM = 0; IllegalCSRDAccessM = 0; case (CSRAdrM) - DCSR_ADDR : CSRDReadValM = DCSR_REGW; - DPC_ADDR : CSRDReadValM = DPC_REGW; + DCSR_ADDR : CSRDReadValM = DCSR; + DPC_ADDR : CSRDReadValM = DPC; default: IllegalCSRDAccessM = 1'b1; endcase end diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 458f63ab2..75e2d7a47 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -98,10 +98,11 @@ module privileged import cvw::*; #(parameter cvw_t P) ( // Fault outputs output logic wfiM, IntPendingM, // Stall in Memory stage for WFI until interrupt pending or timeout // Debuge Mode + input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, input logic [P.XLEN-1:0] PCNextF, - input logic CapturePCNextF, + input logic EnterDebugMode, // Debug scan chain input logic DebugSel, input logic [11:0] DebugRegAddr, @@ -161,7 +162,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .EPCM, .TrapVectorM, .CSRReadValW, .IllegalCSRAccessM, .BigEndianM, - .Step, .DPC, .PCNextF, .CapturePCNextF, + .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, .DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut); // pipeline early-arriving trap sources diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 473c8f5f6..6c6af0619 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -193,9 +193,10 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( // Debug mode logic logic [P.XLEN-1:0] DPC, PCNextF; - logic ForceDPCNextF; - logic CapturePCNextF; + logic ExitDebugMode; + logic EnterDebugMode; logic ForceNOP; + logic [2:0] DebugCause; // Debug register scan chain interconnects logic [2:0] DebugScanReg; @@ -221,7 +222,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissF, // pmp/pma (inside mmu) signals. .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF, - .ForceDPCNextF, .DPC, .PCNextF, .ForceNOP, + .ExitDebugMode, .DPC, .PCNextF, .ForceNOP, .DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1])); // integer execution unit: integer register file, datapath and controller @@ -320,8 +321,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( dmc debugcontrol( .clk, .reset, .Step, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, - .ResumeAck, .HaveReset, .DebugMode, .DebugStall, - .CapturePCNextF, .ForceDPCNextF, .ForceNOP); + .ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall, + .EnterDebugMode, .ExitDebugMode, .ForceNOP); end else begin assign DebugStall = 1'b0; end @@ -349,7 +350,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, - .Step, .DPC, .PCNextF, .CapturePCNextF, + .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, .DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut)); if (P.DEBUG_SUPPORTED) begin flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));