diff --git a/bin/hw_debug_test.py b/bin/hw_debug_test.py index 5febadc2a..4a108fdf8 100755 --- a/bin/hw_debug_test.py +++ b/bin/hw_debug_test.py @@ -36,7 +36,20 @@ random_stimulus = True random_order = False -def main(): +def flow_control_test(): + with OpenOCD() as cvw: + cvw.reset_dm() + cvw.reset_hart() + + cvw.halt() + cvw.read_data("DCSR") + for _ in range(50): + cvw.step() + cvw.read_data("PCM") + cvw.resume() + + +def register_rw_test(): with OpenOCD() as cvw: registers = dict.fromkeys(cvw.register_translations.keys(),[]) reg_addrs = list(registers.keys()) @@ -49,7 +62,7 @@ def main(): cvw.reset_dm() cvw.reset_hart() - time.sleep(70) # wait for OpenSBI + #time.sleep(70) # wait for OpenSBI cvw.halt() @@ -140,4 +153,5 @@ def random_hex(reg_name): return "0x" + f"{(data & (2**size-1)):x}".rjust(pad, "0") -main() +#register_rw_test() +flow_control_test() diff --git a/src/debug/dm.sv b/src/debug/dm.sv index 77f142b89..00f38c8b2 100644 --- a/src/debug/dm.sv +++ b/src/debug/dm.sv @@ -141,8 +141,9 @@ module dm import cvw::*; #(parameter cvw_t P) ( logic AckUnavail; logic DmActive; // This bit is used to (de)activate the DM. Toggling off-on acts as reset // DMStatus - logic StickyUnavail; - logic ImpEBreak; + const logic NdmResetPending = 0; + const logic StickyUnavail = 0; + const logic ImpEBreak = 0; // TODO: change this to const 1 if implementing 1x32bit progbuf logic AllHaveReset; logic AnyHaveReset; logic AllResumeAck; @@ -156,9 +157,9 @@ module dm import cvw::*; #(parameter cvw_t P) ( logic AllHalted; logic AnyHalted; const logic Authenticated = 1; - logic AuthBusy; + const logic AuthBusy = 0; const logic HasResetHaltReq = 1; - logic ConfStrPtrValid; + const logic ConfStrPtrValid = 0; // Used with SysBusAccess const logic [3:0] Version = 3; // DM Version // AbstractCS const logic [4:0] ProgBufSize = 0; @@ -179,11 +180,9 @@ module dm import cvw::*; #(parameter cvw_t P) ( assign AllResumeAck = ResumeAck; assign AnyResumeAck = ResumeAck; - // See spec 3.14.2 assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0, 10'b0, 4'b0, NdmReset, DmActive}; - // See spec 3.14.1 - assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0, + assign DMStatus = {7'b0, NdmResetPending, StickyUnavail, ImpEBreak, 2'b0, AllHaveReset, AnyHaveReset, AllResumeAck, AnyResumeAck, AllNonExistent, AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted, AnyHalted, Authenticated, AuthBusy, HasResetHaltReq, ConfStrPtrValid, Version}; @@ -203,17 +202,8 @@ module dm import cvw::*; #(parameter cvw_t P) ( case (State) INACTIVE : begin // Reset Values - // TODO: one-line these + {HaltReq, ResumeReq, AckHaveReset, HaltOnReset, NdmReset} <= 0; RspData <= 0; - HaltReq <= 0; - ResumeReq <= 0; - AckHaveReset <= 0; - HaltOnReset <= 0; - NdmReset <= 0; - StickyUnavail <= 0; - ImpEBreak <= 0; - AuthBusy <= 0; - ConfStrPtrValid <= 0; CmdErr <= 0; if (ReqValid) begin if (ReqAddress == `DMCONTROL & ReqOP == `OP_WRITE & ReqData[`DMACTIVE]) begin diff --git a/src/debug/rad.sv b/src/debug/rad.sv index e09b5f4d5..ede1effcb 100644 --- a/src/debug/rad.sv +++ b/src/debug/rad.sv @@ -76,6 +76,11 @@ module rad import cvw::*; #(parameter cvw_t P) ( GPRegNo = 0; FPRegNo = 0; case (Regno) inside + [`DCSR_REGNO:`DPC_REGNO] : begin + ShiftCount = P.LLEN - 1; + CSRegNo = 1; + end + [`FFLAGS_REGNO:`FCSR_REGNO], [`MSTATUS_REGNO:`MCOUNTEREN_REGNO], // InvalidRegNo = ~P.ZICSR_SUPPORTED; `MENVCFG_REGNO, @@ -85,7 +90,6 @@ module rad import cvw::*; #(parameter cvw_t P) ( [`MSCRATCH_REGNO:`MIP_REGNO], [`PMPCFG0_REGNO:`PMPADDR3F_REGNO], // TODO This is variable len (P.PA_BITS)? [`TSELECT_REGNO:`TDATA3_REGNO], - [`DCSR_REGNO:`DPC_REGNO], `SIP_REGNO, `MIP_REGNO, `MHPMEVENTBASE_REGNO, @@ -106,7 +110,7 @@ module rad import cvw::*; #(parameter cvw_t P) ( `MIP_REGNO : begin ShiftCount = P.LLEN - 1; CSRegNo = 1; - //RegReadOnly = 1; + RegReadOnly = 1; end [`HPMCOUNTERBASE_REGNO:`TIME_REGNO], diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 5cea11a7b..26abfb137 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -94,6 +94,7 @@ 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 DebugMode, input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, @@ -123,7 +124,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW; logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM; logic CSRWriteDM; - logic CSRMWriteM, CSRSWriteM, CSRUWriteM, CSRDWriteM; + logic CSRMWriteM, CSRSWriteM, CSRUWriteM; logic UngatedCSRMWriteM; logic WriteFRMM, WriteFFLAGSM; logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM; @@ -222,7 +223,6 @@ module csr import cvw::*; #(parameter cvw_t P) ( assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM; assign CSRSWriteM = CSRWriteDM & (|PrivilegeModeW) & InstrValidNotFlushedM; assign CSRUWriteM = CSRWriteDM & InstrValidNotFlushedM; - assign CSRDWriteM = CSRWriteDM; assign MTrapM = TrapM & (NextPrivilegeModeM == P.M_MODE); assign STrapM = TrapM & (NextPrivilegeModeM == P.S_MODE) & P.S_SUPPORTED; @@ -303,7 +303,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( end if (P.DEBUG_SUPPORTED) begin:csrd - csrd #(P) csrd(.clk, .reset, + csrd #(P) csrd(.clk, .reset, .DebugMode, .PrivilegeModeW, .CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM, .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode); end else begin diff --git a/src/privileged/csrd.sv b/src/privileged/csrd.sv index 38fefde5b..8382ff804 100644 --- a/src/privileged/csrd.sv +++ b/src/privileged/csrd.sv @@ -28,6 +28,8 @@ module csrd import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, + input logic DebugMode, + input logic [1:0] PrivilegeModeW, input logic CSRWriteDM, input logic [11:0] CSRAdrM, input logic [P.XLEN-1:0] CSRWriteValM, @@ -45,7 +47,7 @@ module csrd import cvw::*; #(parameter cvw_t P) ( localparam DCSR_ADDR = 12'h7B0; // Debug Control and Status Register localparam DPC_ADDR = 12'h7B1; // Debug PC - // TODO: these registers are only accessible from Debug Mode. + logic CSRDWriteM; logic [31:0] DCSR; logic [P.XLEN-1:0] DPCWriteVal; logic WriteDCSRM; @@ -68,40 +70,44 @@ module csrd import cvw::*; #(parameter cvw_t P) ( logic [1:0] Prv; + assign CSRDWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE) & DebugMode; + + assign WriteDCSRM = CSRDWriteM & (CSRAdrM == DCSR_ADDR); + assign WriteDPCM = CSRDWriteM & (CSRAdrM == DPC_ADDR); always_ff @(posedge clk) begin if (reset) begin - Prv <= 3; - Cause <= 0; + Prv <= 2'h3; + Cause <= 3'h0; end else if (EnterDebugMode) begin - // Prv <= // hart priv mode + Prv <= PrivilegeModeW; 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); - flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, {CSRWriteValM[`EBREAKM], CSRWriteValM[`EBREAKS], CSRWriteValM[`EBREAKU], CSRWriteValM[`STEP]}, {ebreakM, ebreakS, ebreakU, Step}); - assign DCSR = {4'b0100, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, + assign DCSR = {DebugVer, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv}; 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; - DPC_ADDR : CSRDReadValM = DPC; - default: IllegalCSRDAccessM = 1'b1; - endcase + CSRDReadValM = '0; + IllegalCSRDAccessM = 1'b0; + if (~((PrivilegeModeW == P.M_MODE) & DebugMode)) + IllegalCSRDAccessM = 1'b1; + else + case (CSRAdrM) + DCSR_ADDR : CSRDReadValM = DCSR; + DPC_ADDR : CSRDReadValM = DPC; + default: IllegalCSRDAccessM = 1'b1; + endcase end endmodule \ No newline at end of file diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 75e2d7a47..fb7d56fc7 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -98,6 +98,7 @@ 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 DebugMode, input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, @@ -162,7 +163,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .EPCM, .TrapVectorM, .CSRReadValW, .IllegalCSRAccessM, .BigEndianM, - .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, + .DebugMode, .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 6c6af0619..60aa51000 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -195,8 +195,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] DPC, PCNextF; logic ExitDebugMode; logic EnterDebugMode; - logic ForceNOP; logic [2:0] DebugCause; + logic ForceNOP; // Debug register scan chain interconnects logic [2:0] DebugScanReg; @@ -350,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, - .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, + .DebugMode, .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]));