Fixed up logic for "Non-Debug-Module reset" request/response from the Debug Module
Now able to run multiple ISA tests in a single simulation run connected to remote debugger DSharp, using either hart_reset or ndm_reset between tests to bring the system back into reset state. All Debug Module commands working: - dm_reset, hart_reset, ndm_reset - break (set breakpoint) - step - continue (until breakpoint of 'halt' command) - halt - read/write GPR, FPR, CSR, memory - elf_load
This commit is contained in:
@@ -58,18 +58,18 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
Reg #(Bool) rg_start_reg_access <- mkReg (False);
|
||||
|
||||
// FIFOs for request/response to access GPRs
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_hart0_gpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_gpr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(5, XLEN)) f_hart0_gpr_reqs <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_gpr_rsps <- mkFIFOF;
|
||||
|
||||
// FIFOs for request/response to access FPRs
|
||||
`ifdef ISA_F
|
||||
FIFOF #(DM_CPU_Req #(5, FLEN)) f_hart0_fpr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(FLEN)) f_hart0_fpr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(5, FLEN)) f_hart0_fpr_reqs <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(FLEN)) f_hart0_fpr_rsps <- mkFIFOF;
|
||||
`endif
|
||||
|
||||
// FIFOs for request/response to access CSRs
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_hart0_csr_reqs <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_csr_rsps <- mkFIFOF1;
|
||||
FIFOF #(DM_CPU_Req #(12, XLEN)) f_hart0_csr_reqs <- mkFIFOF;
|
||||
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_csr_rsps <- mkFIFOF;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// rg_data0
|
||||
@@ -89,15 +89,18 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
|
||||
Reg #(Bool) rg_abstractcs_busy <- mkRegU;
|
||||
Reg #(DM_abstractcs_cmderr) rg_abstractcs_cmderr <- mkRegU;
|
||||
|
||||
Bit #(5) abstractcs_progsize = 0;
|
||||
Bit #(5) abstractcs_datacount = 0;
|
||||
// Size of program buffer, in 32b words
|
||||
Bit #(5) abstractcs_progbufsize = 0;
|
||||
// Number of data registers implemented (rg_data0, rg_data1)
|
||||
Bit #(4) abstractcs_datacount = ((xlen == 32) ? 1 : 2);
|
||||
|
||||
DM_Word virt_rg_abstractcs = {3'b0,
|
||||
abstractcs_progsize,
|
||||
abstractcs_progbufsize,
|
||||
11'b0,
|
||||
pack (rg_abstractcs_busy),
|
||||
1'b0,
|
||||
pack (rg_abstractcs_cmderr),
|
||||
3'b0,
|
||||
4'b0,
|
||||
abstractcs_datacount};
|
||||
|
||||
function Action fa_rg_abstractcs_write (DM_Word dm_word);
|
||||
|
||||
@@ -9,9 +9,15 @@ package DM_Run_Control;
|
||||
// ================================================================
|
||||
// BSV library imports
|
||||
|
||||
import FIFOF :: *;
|
||||
import GetPut :: *;
|
||||
import ClientServer :: *;
|
||||
import FIFOF :: *;
|
||||
import GetPut :: *;
|
||||
import ClientServer :: *;
|
||||
|
||||
// ----------------
|
||||
// Other library imports
|
||||
|
||||
import Cur_Cycle :: *;
|
||||
import GetPut_Aux :: *;
|
||||
|
||||
// ================================================================
|
||||
// Project imports
|
||||
@@ -33,13 +39,14 @@ interface DM_Run_Control_IFC;
|
||||
|
||||
// ----------------
|
||||
// Facing a hart: reset and run-control
|
||||
interface Get #(Token) hart0_get_reset_req;
|
||||
interface Client #(Bool, Bool) hart0_reset_client;
|
||||
interface Client #(Bool, Bool) hart0_client_run_halt;
|
||||
interface Get #(Bit #(4)) hart0_get_other_req;
|
||||
|
||||
// ----------------
|
||||
// Facing Platform: Non-Debug-Module Reset (reset all except DM)
|
||||
interface Get #(Token) get_ndm_reset_req;
|
||||
// Bool indicates 'running' hart state.
|
||||
interface Client #(Bool, Bool) ndm_reset_client;
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
@@ -52,7 +59,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
// ----------------------------------------------------------------
|
||||
// NDM Reset
|
||||
|
||||
FIFOF #(Token) f_ndm_reset_reqs <- mkFIFOF;
|
||||
FIFOF #(Bool) f_ndm_reset_reqs <- mkFIFOF;
|
||||
FIFOF #(Bool) f_ndm_reset_rsps <- mkFIFOF;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Hart0 run control
|
||||
@@ -60,7 +68,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
Reg #(Bool) rg_hart0_running <- mkRegU;
|
||||
|
||||
// Reset requests to hart
|
||||
FIFOF #(Token) f_hart0_reset_reqs <- mkFIFOF;
|
||||
FIFOF #(Bool) f_hart0_reset_reqs <- mkFIFOF;
|
||||
FIFOF #(Bool) f_hart0_reset_rsps <- mkFIFOF;
|
||||
|
||||
// Run/halt requests to hart and responses
|
||||
FIFOF #(Bool) f_hart0_run_halt_reqs <- mkFIFOF;
|
||||
@@ -81,7 +90,13 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
// 'anyXX' = 'allXX'
|
||||
// 'allrunning' = NOT 'allhalted'
|
||||
|
||||
Reg#(Bool) rg_dmstatus_allresumeack <- mkRegU;
|
||||
Bool dmstatus_impebreak = False;
|
||||
|
||||
Reg #(Bool) rg_hart0_hasreset <- mkRegU;
|
||||
Bool dmstatus_allhavereset = rg_hart0_hasreset;
|
||||
Bool dmstatus_anyhavereset = rg_hart0_hasreset;
|
||||
|
||||
Reg #(Bool) rg_dmstatus_allresumeack <- mkRegU;
|
||||
|
||||
Bool dmstatus_allresumeack = rg_dmstatus_allresumeack;
|
||||
Bool dmstatus_anyresumeack = rg_dmstatus_allresumeack;
|
||||
@@ -89,8 +104,9 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
Bool dmstatus_allnonexistent = False;
|
||||
Bool dmstatus_anynonexistent = dmstatus_allnonexistent;
|
||||
|
||||
Bool dmstatus_allunavail = False;
|
||||
Bool dmstatus_anyunavail = dmstatus_allunavail;
|
||||
Reg #(Bool) rg_dmstatus_allunavail <- mkReg (False);
|
||||
Bool dmstatus_allunavail = rg_dmstatus_allunavail;
|
||||
Bool dmstatus_anyunavail = rg_dmstatus_allunavail;
|
||||
|
||||
Bool dmstatus_allrunning = rg_hart0_running;
|
||||
Bool dmstatus_anyrunning = dmstatus_allrunning;
|
||||
@@ -98,7 +114,11 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
Bool dmstatus_allhalted = (! rg_hart0_running);
|
||||
Bool dmstatus_anyhalted = dmstatus_allhalted;
|
||||
|
||||
DM_Word virt_rg_dmstatus = {14'b0,
|
||||
DM_Word virt_rg_dmstatus = {9'b0,
|
||||
pack (dmstatus_impebreak),
|
||||
2'b0,
|
||||
pack (dmstatus_allhavereset),
|
||||
pack (dmstatus_anyhavereset),
|
||||
pack (dmstatus_allresumeack),
|
||||
pack (dmstatus_anyresumeack),
|
||||
pack (dmstatus_allnonexistent),
|
||||
@@ -151,19 +171,17 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
// Debug Module reset
|
||||
if (! dmactive) begin
|
||||
// Reset the DM module itself
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h (dmactive=0): resetting Debug Module",
|
||||
dm_word);
|
||||
$display ("%0d: %m.dmcontrol_write 0x%08h (dmactive=0): resetting Debug Module",
|
||||
cur_cycle, dm_word);
|
||||
|
||||
// Error-checking
|
||||
if (ndmreset) begin
|
||||
$display ("DM_Run_Control.write: WARNING: in word written to dmcontrol (0x%08h):",
|
||||
dm_word);
|
||||
$display (" WARNING: DM_Run_Control: dmcontrol_write 0x%08h:", dm_word);
|
||||
$display (" [1] (ndmreset) and [0] (dmactive) both asserted");
|
||||
$display (" dmactive has priority; ignoring ndmreset");
|
||||
end
|
||||
if (hartreset) begin
|
||||
$display ("DM_Run_Control.write: WARNING: in word written to dmcontrol (0x%08h):",
|
||||
dm_word);
|
||||
$display (" WARNING: DM_Run_Control: dmcontrol_write 0x%08h:", dm_word);
|
||||
$display (" [29] (hartreset) and [0] (dmactive) both asserted");
|
||||
$display (" dmactive has priority; ignoring hartreset");
|
||||
end
|
||||
@@ -172,63 +190,84 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
noAction;
|
||||
end
|
||||
|
||||
// Platform reset (non-Debug Module)
|
||||
else if (ndmreset) begin
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: ndmreset=1: resetting platform",
|
||||
dm_word);
|
||||
f_ndm_reset_reqs.enq (?);
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_reset!
|
||||
// Ignore if NDM reset is in progress
|
||||
else if (rg_dmstatus_allunavail) begin
|
||||
$display ("%0d: %m.dmcontrol_write 0x%0h: ndm reset in progress; ignoring this write",
|
||||
cur_cycle, dm_word);
|
||||
end
|
||||
|
||||
// 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));
|
||||
end
|
||||
|
||||
f_ndm_reset_reqs.enq (running);
|
||||
rg_dmstatus_allunavail <= True;
|
||||
|
||||
// Error-checking
|
||||
if (hartreset) begin
|
||||
$display ("DM_Run_Control.write: WARNING: in word written to dmcontrol (0x%08h):",
|
||||
dm_word);
|
||||
$display (" Both ndmreset (bit 1) and hartreset (bit 29) are asserted");
|
||||
$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
|
||||
|
||||
end
|
||||
else begin
|
||||
|
||||
// Hart reset
|
||||
else if (hartreset) begin
|
||||
Bool running = (! haltreq);
|
||||
f_hart0_reset_reqs.enq (running);
|
||||
rg_hart0_hasreset <= True;
|
||||
|
||||
// Deassert platform reset
|
||||
if ((verbosity != 0) && rg_dmcontrol_ndmreset)
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: clearing ndmreset", dm_word);
|
||||
|
||||
// Hart reset
|
||||
if (hartreset) begin
|
||||
if (verbosity != 0)
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: hartreset=1: resetting hart",
|
||||
dm_word);
|
||||
f_hart0_reset_reqs.enq (?);
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_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
|
||||
else begin
|
||||
// Deassert hart reset
|
||||
if ((verbosity != 0) && rg_dmcontrol_hartreset)
|
||||
$display ("DM_Run_Control.write: dmcontrol 0x%08h: clearing hartreset", dm_word);
|
||||
end
|
||||
|
||||
if (hasel)
|
||||
$display ("DM_Run_Control.write: ERROR: dmcontrol 0x%08h: 'hasel' is not supported",
|
||||
dm_word);
|
||||
// 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 (hartsel != 0)
|
||||
$display ("DM_Run_Control.write: ERROR: dmcontrol 0x%08h: hartsel 0x%0h not supported",
|
||||
dm_word, hartsel);
|
||||
if (hasel)
|
||||
$display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hasel is not supported",
|
||||
cur_cycle, dm_word);
|
||||
|
||||
if (haltreq && resumereq) begin
|
||||
$display ("DM_Run_Control.write: ERROR: dmcontrol 0x%08h: haltreq=1 and resumereq=1",
|
||||
dm_word);
|
||||
$display (" This behavior is 'undefined' in the spec; ignoring");
|
||||
end
|
||||
// Resume hart(s) if not running
|
||||
else if (resumereq && (! rg_hart0_running)) begin
|
||||
f_hart0_run_halt_reqs.enq (True);
|
||||
rg_dmstatus_allresumeack <= False;
|
||||
$display ("DM_Run_Control.write: hart0 resume request");
|
||||
end
|
||||
// Halt hart(s)
|
||||
else if (haltreq && rg_hart0_running) begin
|
||||
f_hart0_run_halt_reqs.enq (False);
|
||||
$display ("DM_Run_Control.write: hart0 halt request");
|
||||
end
|
||||
if (hartsel != 0)
|
||||
$display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hartsel 0x%0h not supported",
|
||||
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_hart0_running)) begin
|
||||
f_hart0_run_halt_reqs.enq (True);
|
||||
rg_dmstatus_allresumeack <= False;
|
||||
$display ("%0d: %m.dmcontrol_write: hart0 resume request", cur_cycle);
|
||||
end
|
||||
// Halt hart(s)
|
||||
else if (haltreq && rg_hart0_running) begin
|
||||
f_hart0_run_halt_reqs.enq (False);
|
||||
$display ("%0d: %m.dmcontrol_write: hart0 halt request", cur_cycle);
|
||||
end
|
||||
end
|
||||
endaction
|
||||
@@ -250,19 +289,37 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
Reg #(Bit #(4)) rg_verbosity <- mkRegU;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// System responses
|
||||
|
||||
rule rl_hart0_run_rsp;
|
||||
let x = f_hart0_run_halt_rsps.first;
|
||||
f_hart0_run_halt_rsps.deq;
|
||||
// Response from system for hart0 reset
|
||||
rule rl_hart0_reset_rsp;
|
||||
Bool running <- pop (f_hart0_reset_rsps);
|
||||
rg_hart0_hasreset <= False;
|
||||
rg_hart0_running <= running;
|
||||
|
||||
rg_hart0_running <= x;
|
||||
if (x) begin
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: %m.rl_hart0_reset_rsp: hart running = ", cur_cycle, fshow (running));
|
||||
endrule
|
||||
|
||||
// Response from system for NDM reset
|
||||
rule rl_ndm_reset_rsp;
|
||||
Bool running <- pop (f_ndm_reset_rsps);
|
||||
rg_hart0_running <= running;
|
||||
rg_dmstatus_allunavail <= False;
|
||||
|
||||
// if (verbosity != 0) TODO: UNCOMMENT AFTER DEBUGGING
|
||||
$display ("%0d: %m.rl_ndm_reset_rsp: hart running = ", cur_cycle, fshow (running));
|
||||
endrule
|
||||
|
||||
// Response from system for run/halt request
|
||||
rule rl_hart0_run_rsp (! f_ndm_reset_rsps.notEmpty);
|
||||
let running <- pop (f_hart0_run_halt_rsps);
|
||||
rg_hart0_running <= running;
|
||||
if (running)
|
||||
rg_dmstatus_allresumeack <= True;
|
||||
$display ("DM_Run_Control: hart0 running");
|
||||
end
|
||||
else begin
|
||||
$display ("DM_Run_Control: hart0 halted");
|
||||
end
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: %m.rl_hart0_run_rsp: 'running' = ", cur_cycle, fshow (running));
|
||||
endrule
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
@@ -274,9 +331,12 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
|
||||
method Action reset;
|
||||
f_ndm_reset_reqs.clear;
|
||||
f_ndm_reset_rsps.clear;
|
||||
|
||||
rg_hart0_running <= True; // Must be same as run/halt state of CPU after hart_reset!
|
||||
f_hart0_reset_reqs.clear;
|
||||
f_hart0_reset_rsps.clear;
|
||||
|
||||
rg_hart0_running <= True; // Safe approximation of whether the CPU is running or not
|
||||
f_hart0_run_halt_reqs.clear;
|
||||
f_hart0_run_halt_rsps.clear;
|
||||
|
||||
@@ -285,12 +345,14 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
rg_dmcontrol_ndmreset <= False;
|
||||
rg_dmcontrol_dmactive <= True; // DM module is now active
|
||||
|
||||
rg_hart0_hasreset <= False;
|
||||
rg_dmstatus_allresumeack <= False;
|
||||
rg_dmstatus_allunavail <= False; // NDM not in progress
|
||||
|
||||
rg_verbosity <= 0;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("DM_Run_Control: reset");
|
||||
$display ("%0d: %m.reset", cur_cycle);
|
||||
endmethod
|
||||
|
||||
// ----------------
|
||||
@@ -307,7 +369,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
endcase;
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("DM_Run_Control.av_read: [", fshow_dm_addr (dm_addr), "] => 0x%08h", dm_word);
|
||||
$display ("%0d: %m.av_read: [", cur_cycle, fshow_dm_addr (dm_addr), "] => 0x%08h", dm_word);
|
||||
|
||||
return dm_word;
|
||||
endactionvalue
|
||||
@@ -316,7 +378,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
method Action write (DM_Addr dm_addr, DM_Word dm_word);
|
||||
action
|
||||
if (verbosity != 0)
|
||||
$display ("DM_Run_Control.write: [", fshow_dm_addr (dm_addr), "] <= 0x%08h", dm_word);
|
||||
$display ("%0d: %m.write: [", cur_cycle, fshow_dm_addr (dm_addr), "] <= 0x%08h", dm_word);
|
||||
|
||||
case (dm_addr)
|
||||
dm_addr_dmcontrol: fa_rg_dmcontrol_write (dm_word);
|
||||
@@ -331,13 +393,13 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
|
||||
|
||||
// ----------------
|
||||
// Facing Hart: Reset, Run-control, etc.
|
||||
interface Get hart0_get_reset_req = toGet (f_hart0_reset_reqs);
|
||||
interface Client hart0_reset_client = toGPClient (f_hart0_reset_reqs, f_hart0_reset_rsps);
|
||||
interface Client hart0_client_run_halt = toGPClient (f_hart0_run_halt_reqs, f_hart0_run_halt_rsps);
|
||||
interface Get hart0_get_other_req = toGet (f_hart0_other_reqs);
|
||||
|
||||
// ----------------
|
||||
// Facing Platform: Non-Debug-Module Reset (reset all except DM)
|
||||
interface Get get_ndm_reset_req = toGet (f_ndm_reset_reqs);
|
||||
interface Client ndm_reset_client = toGPClient (f_ndm_reset_reqs, f_ndm_reset_rsps);
|
||||
endmodule
|
||||
|
||||
// ================================================================
|
||||
|
||||
@@ -179,7 +179,7 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// Interface to memory fabric
|
||||
AXI4_Master_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master_xactor <- mkAXI4_Master_Xactor_2;
|
||||
AXI4_Master_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master_xactor <- mkAXI4_Master_Xactor;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// System Bus state
|
||||
@@ -318,8 +318,7 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
|
||||
awuser: fabric_default_user};
|
||||
master_xactor.i_wr_addr.enq (wra);
|
||||
|
||||
let wrd = AXI4_Wr_Data {wid: fabric_default_id,
|
||||
wdata: fabric_data,
|
||||
let wrd = AXI4_Wr_Data {wdata: fabric_data,
|
||||
wstrb: fabric_strb,
|
||||
wlast: True,
|
||||
wuser: fabric_default_user};
|
||||
|
||||
@@ -96,7 +96,7 @@ interface Debug_Module_IFC;
|
||||
// This section replicated for additional harts.
|
||||
|
||||
// Reset and run-control
|
||||
interface Get #(Token) hart0_get_reset_req;
|
||||
interface Client #(Bool, Bool) hart0_reset_client;
|
||||
interface Client #(Bool, Bool) hart0_client_run_halt;
|
||||
interface Get #(Bit #(4)) hart0_get_other_req;
|
||||
|
||||
@@ -115,7 +115,8 @@ interface Debug_Module_IFC;
|
||||
// Facing Platform
|
||||
|
||||
// Non-Debug-Module Reset (reset all except DM)
|
||||
interface Get #(Token) get_ndm_reset_req;
|
||||
// Bool indicates 'running' hart state.
|
||||
interface Client #(Bool, Bool) ndm_reset_client;
|
||||
|
||||
// Read/Write RISC-V memory
|
||||
interface AXI4_Master_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master;
|
||||
@@ -126,6 +127,9 @@ endinterface
|
||||
(* synthesize *)
|
||||
module mkDebug_Module (Debug_Module_IFC);
|
||||
|
||||
// Local verbosity: 0 = quiet; 1 = print DMI transactions
|
||||
Integer verbosity = 0;
|
||||
|
||||
// The three parts
|
||||
DM_Run_Control_IFC dm_run_control <- mkDM_Run_Control;
|
||||
DM_Abstract_Commands_IFC dm_abstract_commands <- mkDM_Abstract_Commands;
|
||||
@@ -152,6 +156,9 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
interface DMI dmi;
|
||||
method Action read_addr (DM_Addr dm_addr);
|
||||
f_read_addr.enq(dm_addr);
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: %m.DMI read: dm_addr 0x%0h", cur_cycle, dm_addr);
|
||||
endmethod
|
||||
|
||||
method ActionValue #(DM_Word) read_data;
|
||||
@@ -209,6 +216,10 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
dm_word = 0;
|
||||
end
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: %m.DMI read response: dm_addr 0x%0h, dm_word 0x%0h",
|
||||
cur_cycle, dm_addr, dm_word);
|
||||
|
||||
return dm_word;
|
||||
endmethod
|
||||
|
||||
@@ -261,6 +272,10 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
// TODO: set error status?
|
||||
noAction;
|
||||
end
|
||||
|
||||
if (verbosity != 0)
|
||||
$display ("%0d: %m.DMI write: dm_addr 0x%0h, dm_word 0x%0h",
|
||||
cur_cycle, dm_addr, dm_word);
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
@@ -268,7 +283,7 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
// Facing CPU/hart0
|
||||
|
||||
// Reset and run-control
|
||||
interface Get hart0_get_reset_req = dm_run_control.hart0_get_reset_req;
|
||||
interface Client hart0_reset_client = dm_run_control.hart0_reset_client;
|
||||
interface Client hart0_client_run_halt = dm_run_control.hart0_client_run_halt;
|
||||
interface Get hart0_get_other_req = dm_run_control.hart0_get_other_req;
|
||||
|
||||
@@ -287,7 +302,7 @@ module mkDebug_Module (Debug_Module_IFC);
|
||||
// Facing Platform
|
||||
|
||||
// Non-Debug-Module Reset (reset all except DM)
|
||||
interface Get get_ndm_reset_req = dm_run_control.get_ndm_reset_req;
|
||||
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;
|
||||
|
||||
@@ -1,3 +1,206 @@
|
||||
'Debug_Module' implements a Debug Module for RISC-V processors in
|
||||
accordance with the RISC-V standard "External Debug Support" spec:
|
||||
|
||||
RISC-V External Debug Support
|
||||
Version 0.13.2
|
||||
d5029366d59e8563c08b6b9435f82573b603e48e
|
||||
Fri Mar 22 09:06:04 2019 -0700
|
||||
|
||||
Note: the spec is independent of any particular RISC-V CPU
|
||||
implementation. It just specifies the standard registers in the Debug
|
||||
Module that can be read and written by an external debugger (such as
|
||||
GDB). It specifies the address map of these registers, and the
|
||||
semantics, i.e., what happens when one reads or writes these
|
||||
registers. The spec does not say anything about how this spec is
|
||||
implemented.
|
||||
|
||||
Please see comments in Debug_Module.bsv for more details on our
|
||||
implementation of the Debug Module spec. This implementation is also
|
||||
not specific to any particular CPU implementation. We use it in
|
||||
multiple Bluespec RISC-V CPU implementations, and it could be used
|
||||
with other CPU implementations as well.
|
||||
|
||||
// ================================================================
|
||||
What follows is a concise cheat-sheet for the registers in the Debug Module.
|
||||
|
||||
DM_Addr dm_addr_data0 = 'h04;
|
||||
DM_Addr dm_addr_data1 = 'h05;
|
||||
DM_Addr dm_addr_data2 = 'h06;
|
||||
DM_Addr dm_addr_data3 = 'h07;
|
||||
DM_Addr dm_addr_data4 = 'h08;
|
||||
DM_Addr dm_addr_data5 = 'h09;
|
||||
DM_Addr dm_addr_data6 = 'h0a;
|
||||
DM_Addr dm_addr_data7 = 'h0b;
|
||||
DM_Addr dm_addr_data8 = 'h0c;
|
||||
DM_Addr dm_addr_data9 = 'h0d;
|
||||
DM_Addr dm_addr_data10 = 'h0d;
|
||||
DM_Addr dm_addr_data11 = 'h0f;
|
||||
|
||||
// ----------------
|
||||
// Run Control
|
||||
|
||||
DM_Addr dm_addr_dmcontrol = 'h10;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
| | | | 0 | | | | | 0 0 | | | |dmactive
|
||||
| | | | | | | | | | | |ndmreset
|
||||
| | | | | | | | | | |clrresethaltreq
|
||||
| | | | | | | | | |setresethaltreq
|
||||
| | | | | | | |-----------10-----------|hartselhi
|
||||
| | | | | |------------10--------------|hartsello
|
||||
| | | | |hasel
|
||||
| | | | 0: Single hart selected (hartsel)
|
||||
| | | | 1: Multiple harts selected (hartsel + hart array mask)
|
||||
| | | |ackhavereset
|
||||
| | |hartreset
|
||||
| |resumereq
|
||||
|haltreq
|
||||
|
||||
DM_Addr dm_addr_dmstatus = 'h11;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
0 0 0 0 0 0 0 0 | | 0 0 | | | | | | | | | | | | | | | | |--4--|version
|
||||
| | | | | | | | | | | | | | | | | | | 0: no DM present
|
||||
| | | | | | | | | | | | | | | | | | | 1: DM v011
|
||||
| | | | | | | | | | | | | | | | | | | 2: DM v013
|
||||
| | | | | | | | | | | | | | | | | | | 15: DM vUnknown
|
||||
| | | | | | | | | | | | | | | | | |confstrptrvalid
|
||||
| | | | | | | | | | | | | | | | |hasresethaltreq
|
||||
| | | | | | | | | | | | | | | |authbusy
|
||||
| | | | | | | | | | | | | | |authenticated
|
||||
| | | | | | | | | | | | | |anyhalted
|
||||
| | | | | | | | | | | | |allhalted
|
||||
| | | | | | | | | | | |anyrunning
|
||||
| | | | | | | | | | |allrunning
|
||||
| | | | | | | | | |anyunavail
|
||||
| | | | | | | | |allunavail
|
||||
| | | | | | | |anynonexistent
|
||||
| | | | | | |allnonexistent
|
||||
| | | | | |anyresumeack
|
||||
| | | | |allresumeack
|
||||
| | | |anyhavereset
|
||||
| | |allhavereset
|
||||
| |impebreak
|
||||
| 0 No implicit EBREAK at end of PB
|
||||
| 1 Implicit EBREAK at end of PB
|
||||
|
||||
DM_Addr dm_addr_hartinfo = 'h12;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
0 0 0 0 0 0 0 0 | | 0 0 0 | | | |-----------12-----------|dataaddr
|
||||
| | | |----4---|datasize
|
||||
|----4---|nscratch |dataaccess
|
||||
|
||||
|
||||
DM_Addr dm_addr_haltsum1 = 'h13;
|
||||
DM_Addr dm_addr_hawindowsel = 'h14;
|
||||
DM_Addr dm_addr_hawindow = 'h15;
|
||||
|
||||
// ----------------
|
||||
// Abstract commands (read/write RISC-V registers and RISC-V CSRs)
|
||||
|
||||
DM_Addr dm_addr_abstractcs = 'h16;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
0 0 0 | | 0 0 0 0 0 0 0 0 0 0 0 | 0 | | 0 0 0 0 |--4--|datacount
|
||||
0 0 0 |-----5------|progbufsize |busy |-3-|cmderr
|
||||
|
||||
DM_Addr dm_addr_command = 'h17;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
| 0 | | | | | | |-----------------16------------------|regno
|
||||
| | | | | | | | 0x0000-0x0FFF CSRs (dpc => PC)
|
||||
| | | | | | | | 0x1000-0x101F GPRs
|
||||
| | | | | | | | 0x1020-0x103F Floating Point Regs
|
||||
| | | | | | | | 0xC000-0xFFFF Reserved
|
||||
| | | | | | |write
|
||||
| | | | | | 0: specified reg -> arg0 of data
|
||||
| | | | | | 1: specified reg <- arg0 of data
|
||||
| | | | | |transfer
|
||||
| | | | | 0 Don't do the 'write' op
|
||||
| | | | | 1 Do the 'write' op
|
||||
| | | | | Allows exec of PB without valid vals in 'size' and 'regno'
|
||||
| | | | |postexec
|
||||
| | | | 1 exec Program Buffer exactly once after the xfer
|
||||
| | | |aarpostincrement
|
||||
| |--3--|aarsize
|
||||
| 2 Lowest 32b of reg
|
||||
| 3 Lowest 64b of reg
|
||||
| 4 Lowest 128b of reg
|
||||
|---------8-----------|cmdtype
|
||||
0 ACCESS_REG
|
||||
1 QUICK_ACCESS
|
||||
|
||||
DM_Addr dm_addr_abstractauto = 'h18;
|
||||
DM_Addr dm_addr_confstrptr0 = 'h19;
|
||||
DM_Addr dm_addr_confstrptr1 = 'h1a;
|
||||
DM_Addr dm_addr_confstrptr2 = 'h1b;
|
||||
DM_Addr dm_addr_confstrptr3 = 'h1c;
|
||||
DM_Addr dm_addr_nextdm = 'h1d;
|
||||
|
||||
DM_Addr dm_addr_progbuf0 = 'h20;
|
||||
DM_Addr dm_addr_progbuf1 = 'h21;
|
||||
DM_Addr dm_addr_progbuf2 = 'h22;
|
||||
DM_Addr dm_addr_progbuf3 = 'h23;
|
||||
DM_Addr dm_addr_progbuf4 = 'h24;
|
||||
DM_Addr dm_addr_progbuf5 = 'h25;
|
||||
DM_Addr dm_addr_progbuf6 = 'h26;
|
||||
DM_Addr dm_addr_progbuf7 = 'h27;
|
||||
DM_Addr dm_addr_progbuf8 = 'h28;
|
||||
DM_Addr dm_addr_progbuf9 = 'h29;
|
||||
DM_Addr dm_addr_progbuf10 = 'h2a;
|
||||
DM_Addr dm_addr_progbuf11 = 'h2b;
|
||||
DM_Addr dm_addr_progbuf12 = 'h2c;
|
||||
DM_Addr dm_addr_progbuf13 = 'h2d;
|
||||
DM_Addr dm_addr_progbuf14 = 'h2e;
|
||||
DM_Addr dm_addr_progbuf15 = 'h2f;
|
||||
|
||||
DM_Addr dm_addr_authdata = 'h30;
|
||||
DM_Addr dm_addr_haltsum2 = 'h34;
|
||||
DM_Addr dm_addr_haltsum3 = 'h35;
|
||||
|
||||
DM_Addr dm_addr_sbaddress3 = 'h37;
|
||||
|
||||
// ----------------
|
||||
// System Bus access (read/write RISC-V memory/devices)
|
||||
|
||||
DM_Addr dm_addr_sbcs = 'h38;
|
||||
31.30.29.28| 27.26.25.24| 23.22.21.20| 19.18.17.16| 15.14.13.12| 11.10.9.8| 7.6.5.4| 3.2.1.0|
|
||||
| | 0 0 0 0 0 0 | | | | | | | | | | | | | | | |sbaccess8
|
||||
| | | | | | | | | | | | | | | | |sbaccess16
|
||||
| | | | | | | | | | | | | | | |sbaccess32
|
||||
| | | | | | | | | | | | | | |sbaccess64
|
||||
| | | | | | | | | | | | | |sbaccess128
|
||||
| | | | | | | | | | | |-----7-------|sbasize
|
||||
| | | | | | | | | |--3--|sberror
|
||||
| | | | | | | | | 0: no bus err
|
||||
| | | | | | | | | 1: timeout
|
||||
| | | | | | | | | 2: bad addr
|
||||
| | | | | | | | | 3: alignment err
|
||||
| | | | | | | | | 4: unsupported size
|
||||
| | | | | | | | | 7: other
|
||||
| | | | | | | | |sbreadondata: read on sbdata0 triggers sb read
|
||||
| | | | | | | |sbautoincrement
|
||||
| | | | | |--3--|sbaccess
|
||||
| | | | | 0:8b, 1:16b, 2:32b, 3:64b, 4:128b
|
||||
| | | | |sbreadonaddr
|
||||
| | | | 1 Every write to sbaddress0 triggers sb read at new addr
|
||||
| | | |sbbusy
|
||||
| | |sbbusyerror
|
||||
|--3--|sbversion
|
||||
0: System Bus interface spec version < 2018-01-01
|
||||
1: This System Bus interface spec version
|
||||
|
||||
DM_Addr dm_addr_sbaddress0 = 'h39;
|
||||
DM_Addr dm_addr_sbaddress1 = 'h3a;
|
||||
DM_Addr dm_addr_sbaddress2 = 'h3b;
|
||||
DM_Addr dm_addr_sbdata0 = 'h3c;
|
||||
DM_Addr dm_addr_sbdata1 = 'h3d;
|
||||
DM_Addr dm_addr_sbdata2 = 'h3e;
|
||||
DM_Addr dm_addr_sbdata3 = 'h3f;
|
||||
DM_Addr dm_addr_haltsum0 = 'h40;
|
||||
|
||||
// ================================================================
|
||||
// ================================================================
|
||||
// OLDER VERSIONS OF THE DEBUG MODULE SPEC
|
||||
// ================================================================
|
||||
// ================================================================
|
||||
|
||||
'Debug_Module' implements a Debug Module for RISC-V processors in
|
||||
accordance with the RISC-V standard "External Debug Support" spec:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user