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?