From 1cfc58c2cc02946e1ab5dc074b0fd423d0da3e4f Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Mon, 16 Sep 2024 16:10:02 +0100 Subject: [PATCH] Fix debug module reset state machine dmactive should only go low when the debug module has successfully reset. Approximate this by waiting for 1024 cycles, allowing any register access requests and system bus requests to come back. --- src_Core/Debug_Module/DM_Common.bsv | 2 + src_Core/Debug_Module/DM_Run_Control.bsv | 155 ++++++++++++----------- src_Core/Debug_Module/Debug_Module.bsv | 109 +++++++++------- 3 files changed, 143 insertions(+), 123 deletions(-) diff --git a/src_Core/Debug_Module/DM_Common.bsv b/src_Core/Debug_Module/DM_Common.bsv index a111ff1..197d7ca 100644 --- a/src_Core/Debug_Module/DM_Common.bsv +++ b/src_Core/Debug_Module/DM_Common.bsv @@ -26,6 +26,8 @@ DM_Addr max_DM_Addr = 'h5F; typedef Bit #(32) DM_Word; +typedef Bit #(10) DM_Reset_Count; + // ================================================================ // Debug Module address map diff --git a/src_Core/Debug_Module/DM_Run_Control.bsv b/src_Core/Debug_Module/DM_Run_Control.bsv index c8ac9c9..0249185 100644 --- a/src_Core/Debug_Module/DM_Run_Control.bsv +++ b/src_Core/Debug_Module/DM_Run_Control.bsv @@ -47,7 +47,7 @@ import ProcTypes :: *; // Interface interface DM_Run_Control_IFC; - method Bool dmactive; + method Bool dmactive_cleared; method Action reset; // ---------------- @@ -111,6 +111,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC); Reg #(Bool) rg_dmcontrol_ndmreset <- mkRegU; Reg #(Bool) rg_dmcontrol_dmactive <- mkReg (False); Reg #(Bit#(20)) rg_dmcontrol_hartsel <- mkReg (0); + // Whether the user has attempted to clear dmactive since last reset + Reg #(Bool) rg_dmactive_cleared <- mkReg (False); Bit#(20) core_num_sel = fromInteger(valueOf(CoreNum)); @@ -193,7 +195,6 @@ module mkDM_Run_Control (DM_Run_Control_IFC); rg_dmcontrol_haltreq <= haltreq; rg_dmcontrol_hartreset <= hartreset; rg_dmcontrol_ndmreset <= ndmreset; - rg_dmcontrol_dmactive <= dmactive; rg_dmcontrol_hartsel <= hartsel; // Debug Module reset @@ -214,88 +215,90 @@ module mkDM_Run_Control (DM_Run_Control_IFC); $display (" dmactive has priority; ignoring hartreset"); end - // No action here; other rules will fire (see method dmactive, Debug_Module.rl_reset) - noAction; - end + rg_dmactive_cleared <= True; - // Ignore if NDM reset is in progress - else if (rg_ndm_reset_pending) begin - $display ("%0d: %m.dmcontrol_write 0x%0h: ndm reset in progress; ignoring this write", - cur_cycle, dm_word); - end + end else begin + rg_dmcontrol_dmactive <= True; - // Non-Debug-Module reset (platform reset) posedge: ignore - else if ((! rg_dmcontrol_ndmreset) && ndmreset) begin - if (verbosity != 0) - $display ("%0d: %m.dmcontrol_write 0x%08h: ndmreset: 0->1: ignoring", - cur_cycle, dm_word); - end - - // Non-Debug-Module reset (platform reset) negedge: do it - else if (rg_dmcontrol_ndmreset && (! ndmreset)) begin - Bool running = (! haltreq); - if (verbosity != 0) begin - $display ("%0d: %m.dmcontrol_write 0x%08h: ndmreset: 1->0: resetting platform", - cur_cycle, dm_word); - $display (" Requested 'running' state = ", fshow (running)); + // Ignore if NDM reset is in progress + if (rg_ndm_reset_pending) begin + $display ("%0d: %m.dmcontrol_write 0x%0h: ndm reset in progress; ignoring this write", + cur_cycle, dm_word); end - f_ndm_reset_reqs.enq (running); - rg_ndm_reset_pending <= True; - - // Error-checking - if (hartreset) begin - $display (" WARNING: %m.dmcontrol_write 0x%08h:", dm_word); - $display (" Both ndmreset [1] and hartreset [29] are asserted"); - $display (" ndmreset has priority; ignoring hartreset"); + // Non-Debug-Module reset (platform reset) posedge: ignore + else if ((! rg_dmcontrol_ndmreset) && ndmreset) begin + if (verbosity != 0) + $display ("%0d: %m.dmcontrol_write 0x%08h: ndmreset: 0->1: ignoring", + cur_cycle, dm_word); end - end + // Non-Debug-Module reset (platform reset) negedge: do it + else if (rg_dmcontrol_ndmreset && (! ndmreset)) begin + Bool running = (! haltreq); + if (verbosity != 0) begin + $display ("%0d: %m.dmcontrol_write 0x%08h: ndmreset: 1->0: resetting platform", + cur_cycle, dm_word); + $display (" Requested 'running' state = ", fshow (running)); + end - // Hart reset - else if (hartreset) begin - Bool running = (! haltreq); - f_harts_reset_reqs[hartsel].enq (running); - rg_harts_hasreset[hartsel] <= True; + f_ndm_reset_reqs.enq (running); + rg_ndm_reset_pending <= True; + + // Error-checking + if (hartreset) begin + $display (" WARNING: %m.dmcontrol_write 0x%08h:", dm_word); + $display (" Both ndmreset [1] and hartreset [29] are asserted"); + $display (" ndmreset has priority; ignoring hartreset"); + end - // Deassert platform reset - if (verbosity != 0) begin - $display ("%0d: %m.dmcontrol_write 0x%08h: hartreset=1: resetting hart", - cur_cycle, dm_word); - $display (" Requested 'running' state = ", fshow (running)); end - end - // run/halt commands - else begin - // Deassert hart reset - if ((verbosity != 0) && rg_dmcontrol_hartreset) - $display ("%0d: %m.dmcontrol_write 0x%08h: clearing hartreset", - cur_cycle, dm_word); + // Hart reset + else if (hartreset) begin + Bool running = (! haltreq); + f_harts_reset_reqs[hartsel].enq (running); + rg_harts_hasreset[hartsel] <= True; - if (hasel) - $display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hasel is not supported", - cur_cycle, dm_word); - - if (hartsel >= core_num_sel) - $display ("%0d:WARNING: %m.dmcontrol_write 0x%08h: hartsel 0x%0h refers to non-existent hart", - cur_cycle, dm_word, hartsel); - - if (haltreq && resumereq) begin - $display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: haltreq=1 and resumereq=1", - cur_cycle, dm_word); - $display (" This behavior is 'undefined' in the spec; ignoring"); + // Deassert platform reset + if (verbosity != 0) begin + $display ("%0d: %m.dmcontrol_write 0x%08h: hartreset=1: resetting hart", + cur_cycle, dm_word); + $display (" Requested 'running' state = ", fshow (running)); + end end - // Resume hart(s) if not running - else if (resumereq && (! rg_harts_running[hartsel])) begin - f_harts_run_halt_reqs[hartsel].enq (True); - rg_harts_resumeack[hartsel] <= False; - $display ("%0d: %m.dmcontrol_write: hart %0d resume request", cur_cycle, hartsel); - end - // Halt hart(s) - else if (haltreq && rg_harts_running[hartsel]) begin - f_harts_run_halt_reqs[hartsel].enq (False); - $display ("%0d: %m.dmcontrol_write: hart %0d halt request", cur_cycle, hartsel); + + // run/halt commands + else begin + // Deassert hart reset + if ((verbosity != 0) && rg_dmcontrol_hartreset) + $display ("%0d: %m.dmcontrol_write 0x%08h: clearing hartreset", + cur_cycle, dm_word); + + if (hasel) + $display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hasel is not supported", + cur_cycle, dm_word); + + if (hartsel >= core_num_sel) + $display ("%0d:WARNING: %m.dmcontrol_write 0x%08h: hartsel 0x%0h refers to non-existent hart", + cur_cycle, dm_word, hartsel); + + if (haltreq && resumereq) begin + $display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: haltreq=1 and resumereq=1", + cur_cycle, dm_word); + $display (" This behavior is 'undefined' in the spec; ignoring"); + end + // Resume hart(s) if not running + else if (resumereq && (! rg_harts_running[hartsel])) begin + f_harts_run_halt_reqs[hartsel].enq (True); + rg_harts_resumeack[hartsel] <= False; + $display ("%0d: %m.dmcontrol_write: hart %0d resume request", cur_cycle, hartsel); + end + // Halt hart(s) + else if (haltreq && rg_harts_running[hartsel]) begin + f_harts_run_halt_reqs[hartsel].enq (False); + $display ("%0d: %m.dmcontrol_write: hart %0d halt request", cur_cycle, hartsel); + end end end endaction @@ -355,8 +358,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC); // ---------------------------------------------------------------- // INTERFACE - method Bool dmactive; - return rg_dmcontrol_dmactive; + method Bool dmactive_cleared; + return rg_dmactive_cleared; endmethod method Action reset; @@ -375,7 +378,9 @@ module mkDM_Run_Control (DM_Run_Control_IFC); rg_dmcontrol_haltreq <= False; rg_dmcontrol_hartreset <= False; rg_dmcontrol_ndmreset <= False; - rg_dmcontrol_dmactive <= True; // DM module is now active + rg_dmcontrol_dmactive <= False; // Debug module stays inactive so debugger can confirm it has reset + + rg_dmactive_cleared <= False; writeVReg(rg_harts_hasreset, replicate(False)); writeVReg(rg_harts_resumeack, replicate(False)); diff --git a/src_Core/Debug_Module/Debug_Module.bsv b/src_Core/Debug_Module/Debug_Module.bsv index dfd73a5..1a36a43 100644 --- a/src_Core/Debug_Module/Debug_Module.bsv +++ b/src_Core/Debug_Module/Debug_Module.bsv @@ -150,6 +150,8 @@ module mkDebug_Module (Debug_Module_IFC); // Local verbosity: 0 = quiet; 1 = print DMI transactions Integer verbosity = 0; + Reg #(Maybe#(DM_Reset_Count)) rg_reset_count <- mkReg(Valid(~0)); + // The three parts DM_Run_Control_IFC dm_run_control <- mkDM_Run_Control; DM_Abstract_Commands_IFC dm_abstract_commands <- mkDM_Abstract_Commands; @@ -158,13 +160,22 @@ module mkDebug_Module (Debug_Module_IFC); FIFO#(DM_Addr) f_read_addr <- mkFIFO1; // ================================================================ - // Reset all three parts when dm_run_control.dmactive is low + // Reset all three parts: triggered when dm_run_control.dmactive is low - rule rl_reset (! dm_run_control.dmactive); - $display ("%0d: Debug_Module reset", cur_cycle); + rule rl_reset_start (dm_run_control.dmactive_cleared && rg_reset_count == Invalid); + rg_reset_count <= Valid(~0); + endrule + + rule rl_reset_wait (rg_reset_count matches tagged Valid .c &&& c != 0); + rg_reset_count <= Valid(c - 1); + endrule + + rule rl_reset_done (rg_reset_count == Valid(0)); + $display ("%0d: Debug_Module reset complete", cur_cycle); dm_run_control.reset; dm_abstract_commands.reset; dm_system_bus.reset; + rg_reset_count <= Invalid; endrule // ================================================================ @@ -174,7 +185,7 @@ module mkDebug_Module (Debug_Module_IFC); // Facing GDB/DMI (Debug Module Interface) interface DMI dmi; - method Action read_addr (DM_Addr dm_addr) if (dm_run_control.dmactive); + method Action read_addr (DM_Addr dm_addr); f_read_addr.enq(dm_addr); if (verbosity != 0) @@ -241,58 +252,60 @@ module mkDebug_Module (Debug_Module_IFC); return dm_word; endmethod - method Action write (DM_Addr dm_addr, DM_Word dm_word) if (dm_run_control.dmactive); + method Action write (DM_Addr dm_addr, DM_Word dm_word); Bool handled = False; - if ( (dm_addr == dm_addr_dmcontrol) - || (dm_addr == dm_addr_dmstatus) - || (dm_addr == dm_addr_hartinfo) - || (dm_addr == dm_addr_haltsum0) - || (dm_addr == dm_addr_hawindowsel) - || (dm_addr == dm_addr_hawindow) - || (dm_addr == dm_addr_devtreeaddr0) - || (dm_addr == dm_addr_authdata) - || (dm_addr == dm_addr_verbosity)) begin + if (rg_reset_count == Invalid) begin + if ( (dm_addr == dm_addr_dmcontrol) + || (dm_addr == dm_addr_dmstatus) + || (dm_addr == dm_addr_hartinfo) + || (dm_addr == dm_addr_haltsum0) + || (dm_addr == dm_addr_hawindowsel) + || (dm_addr == dm_addr_hawindow) + || (dm_addr == dm_addr_devtreeaddr0) + || (dm_addr == dm_addr_authdata) + || (dm_addr == dm_addr_verbosity)) begin - dm_run_control.write (dm_addr, dm_word); - handled = True; - end + dm_run_control.write (dm_addr, dm_word); + handled = True; + end - if ( (dm_addr == dm_addr_dmcontrol) - || (dm_addr == dm_addr_abstractcs) - || (dm_addr == dm_addr_command) - || (dm_addr == dm_addr_data0) - || (dm_addr == dm_addr_data1) - || (dm_addr == dm_addr_data2) - || (dm_addr == dm_addr_data3) - || (dm_addr == dm_addr_data4) - || (dm_addr == dm_addr_data5) - || (dm_addr == dm_addr_data6) - || (dm_addr == dm_addr_data7) - || (dm_addr == dm_addr_data8) - || (dm_addr == dm_addr_data9) - || (dm_addr == dm_addr_data10) - || (dm_addr == dm_addr_data11) - || (dm_addr == dm_addr_abstractauto) - || (dm_addr == dm_addr_progbuf0)) begin + if ( (dm_addr == dm_addr_dmcontrol) + || (dm_addr == dm_addr_abstractcs) + || (dm_addr == dm_addr_command) + || (dm_addr == dm_addr_data0) + || (dm_addr == dm_addr_data1) + || (dm_addr == dm_addr_data2) + || (dm_addr == dm_addr_data3) + || (dm_addr == dm_addr_data4) + || (dm_addr == dm_addr_data5) + || (dm_addr == dm_addr_data6) + || (dm_addr == dm_addr_data7) + || (dm_addr == dm_addr_data8) + || (dm_addr == dm_addr_data9) + || (dm_addr == dm_addr_data10) + || (dm_addr == dm_addr_data11) + || (dm_addr == dm_addr_abstractauto) + || (dm_addr == dm_addr_progbuf0)) begin - dm_abstract_commands.write (dm_addr, dm_word); - handled = True; - end + dm_abstract_commands.write (dm_addr, dm_word); + handled = True; + end - if ( (dm_addr == dm_addr_sbcs) - || (dm_addr == dm_addr_sbaddress0) - || (dm_addr == dm_addr_sbaddress1) - || (dm_addr == dm_addr_sbaddress2) - || (dm_addr == dm_addr_sbdata0) - || (dm_addr == dm_addr_sbdata1) - || (dm_addr == dm_addr_sbdata2) - || (dm_addr == dm_addr_sbdata3)) begin + if ( (dm_addr == dm_addr_sbcs) + || (dm_addr == dm_addr_sbaddress0) + || (dm_addr == dm_addr_sbaddress1) + || (dm_addr == dm_addr_sbaddress2) + || (dm_addr == dm_addr_sbdata0) + || (dm_addr == dm_addr_sbdata1) + || (dm_addr == dm_addr_sbdata2) + || (dm_addr == dm_addr_sbdata3)) begin - dm_system_bus.write (dm_addr, dm_word); - handled = True; - end + dm_system_bus.write (dm_addr, dm_word); + handled = True; + end + end if (! handled) begin // TODO: set error status?