Multicore debug-module

This commit is contained in:
Peter Rugg
2021-01-21 20:25:26 +00:00
parent 3417fb454e
commit 30e7090213
8 changed files with 427 additions and 347 deletions

View File

@@ -28,6 +28,7 @@ import FIFOF :: *;
import GetPut :: *;
import ClientServer :: *;
import ConfigReg :: *;
import Vector :: *;
// ----------------
// Other library imports
@@ -41,6 +42,7 @@ import Cur_Cycle :: *;
import ISA_Decls :: *;
import DM_Common :: *;
import DM_CPU_Req_Rsp :: *;
import ProcTypes :: *;
// ================================================================
// Interface
@@ -55,11 +57,11 @@ interface DM_Abstract_Commands_IFC;
// ----------------
// Facing CPU/hart
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN))) harts_gpr_mem_client;
`ifdef ISA_F
interface Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN))) harts_fpr_mem_client;
`endif
interface Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN))) harts_csr_mem_client;
endinterface
// ================================================================
@@ -73,19 +75,21 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
Reg #(Bool) rg_start_reg_access <- mkConfigReg (False);
Reg #(Bit#(20)) rg_dmcontrol_hartsel <- mkConfigReg(0);
// FIFOs for request/response to access GPRs
FIFOF #(DM_CPU_Req #(5, XLEN)) f_hart0_gpr_reqs <- mkFIFOF;
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_gpr_rsps <- mkFIFOF;
Vector #(CoreNum, FIFOF #(DM_CPU_Req #(5, XLEN))) f_harts_gpr_reqs <- replicateM(mkFIFOF);
Vector #(CoreNum, FIFOF #(DM_CPU_Rsp #(XLEN))) f_harts_gpr_rsps <- replicateM(mkFIFOF);
// FIFOs for request/response to access FPRs
`ifdef ISA_F
FIFOF #(DM_CPU_Req #(5, FLEN)) f_hart0_fpr_reqs <- mkFIFOF;
FIFOF #(DM_CPU_Rsp #(FLEN)) f_hart0_fpr_rsps <- mkFIFOF;
Vector #(CoreNum, FIFOF #(DM_CPU_Req #(5, FLEN))) f_harts_fpr_reqs <- replicateM(mkFIFOF);
Vector #(CoreNum, FIFOF #(DM_CPU_Rsp #(FLEN))) f_harts_fpr_rsps <- replicateM(mkFIFOF);
`endif
// FIFOs for request/response to access CSRs
FIFOF #(DM_CPU_Req #(12, XLEN)) f_hart0_csr_reqs <- mkFIFOF;
FIFOF #(DM_CPU_Rsp #(XLEN)) f_hart0_csr_rsps <- mkFIFOF;
Vector #(CoreNum, FIFOF #(DM_CPU_Req #(12, XLEN))) f_harts_csr_reqs <- replicateM(mkFIFOF);
Vector #(CoreNum, FIFOF #(DM_CPU_Rsp #(XLEN))) f_harts_csr_rsps <- replicateM(mkFIFOF);
// ----------------------------------------------------------------
// rg_data0
@@ -227,8 +231,8 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
rg_abstractcs_busy <= True;
rg_start_reg_access <= True;
cmderr = DM_ABSTRACTCS_CMDERR_NONE;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: OKAY", cur_cycle, dm_word);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.write: [command] <= 0x%08h: OKAY", cur_cycle, dm_word);
end
rg_abstractcs_cmderr <= cmderr;
end
@@ -258,217 +262,253 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
// ----------------------------------------------------------------
// Write CSR
rule rl_csr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_csr);
let req = DM_CPU_Req {write: True,
address: csr_addr,
Rules finishRules = emptyRules;
for (Integer core = 0; core < valueOf(CoreNum); core = core + 1) begin
rule rl_csr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_csr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
let req = DM_CPU_Req {write: True,
address: csr_addr,
`ifdef RV32
data: rg_data0
data: rg_data0
`endif
`ifdef RV64
data: {rg_data1, rg_data0}
data: {rg_data1, rg_data0}
`endif
};
f_hart0_csr_reqs.enq (req);
rg_start_reg_access <= False;
};
f_harts_csr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_write_start: ", cur_cycle, fshow (req));
endrule
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_write_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_csr_write_finish (rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_csr);
let rsp <- pop (f_hart0_csr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_write_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_csr_write_finish (rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_csr);
let rsp <- pop (f_harts_csr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_write_finish hart %i: ", cur_cycle, core, fshow (rsp));
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
endrules
);
// ----------------------------------------------------------------
// Read CSR
// ----------------------------------------------------------------
// Read CSR
rule rl_csr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_csr);
Bit #(XLEN) data = ?;
let req = DM_CPU_Req {write: False, address: csr_addr, data: data};
f_hart0_csr_reqs.enq (req);
rg_start_reg_access <= False;
rule rl_csr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_csr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
Bit #(XLEN) data = ?;
let req = DM_CPU_Req {write: False, address: csr_addr, data: data};
f_harts_csr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_read_start: ", cur_cycle, fshow (req));
endrule
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_read_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_csr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_csr);
let rsp <- pop (f_hart0_csr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_read_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_csr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_csr);
let rsp <- pop (f_harts_csr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_csr_read_finish hart %i: ", cur_cycle, core, fshow (rsp));
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
`ifdef RV32
rg_data0 <= rsp.data;
rg_data0 <= rsp.data;
`endif
`ifdef RV64
rg_data0 <= truncate (rsp.data);
rg_data1 <= rsp.data[63:32];
rg_data0 <= truncate (rsp.data);
rg_data1 <= rsp.data[63:32];
`endif
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_busy <= False;
endrule
endrules
);
// ----------------------------------------------------------------
// Write GPR
// ----------------------------------------------------------------
// Write GPR
rule rl_gpr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_gpr);
let req = DM_CPU_Req {write: True,
address: gpr_addr,
rule rl_gpr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_gpr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
let req = DM_CPU_Req {write: True,
address: gpr_addr,
`ifdef RV32
data: rg_data0
data: rg_data0
`endif
`ifdef RV64
data: {rg_data1, rg_data0}
data: {rg_data1, rg_data0}
`endif
};
f_hart0_gpr_reqs.enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_start: ", cur_cycle, fshow (req));
endrule
};
f_harts_gpr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_gpr_write_finish ( rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_gpr);
let rsp <- pop (f_hart0_gpr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_gpr_write_finish ( rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_gpr);
let rsp <- pop (f_harts_gpr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_write_finish hart %i: ", cur_cycle, core, fshow (rsp));
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
endrules
);
// ----------------------------------------------------------------
// Read GPR
// ----------------------------------------------------------------
// Read GPR
rule rl_gpr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_gpr);
Bit #(XLEN) data = ?;
let req = DM_CPU_Req {write: False, address: gpr_addr, data: data };
f_hart0_gpr_reqs.enq (req);
rg_start_reg_access <= False;
rule rl_gpr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_gpr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
Bit #(XLEN) data = ?;
let req = DM_CPU_Req {write: False, address: gpr_addr, data: data };
f_harts_gpr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_start: ", cur_cycle, fshow (req));
endrule
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_gpr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_gpr);
let rsp <- pop (f_hart0_gpr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_gpr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_gpr);
let rsp <- pop (f_harts_gpr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_gpr_read_finish hart %i: ", cur_cycle, core, fshow (rsp));
`ifdef RV32
rg_data0 <= rsp.data;
rg_data0 <= rsp.data;
`endif
`ifdef RV64
rg_data0 <= truncate (rsp.data);
rg_data1 <= rsp.data[63:32];
rg_data0 <= truncate (rsp.data);
rg_data1 <= rsp.data[63:32];
`endif
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
endrules
);
// ----------------------------------------------------------------
// Write FPR
// ----------------------------------------------------------------
// Write FPR
`ifdef ISA_F
rule rl_fpr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_fpr);
DM_CPU_Req#(5, ISA_Decls::FLEN) req = DM_CPU_Req {write: True,
address: fpr_addr,
rule rl_fpr_write_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& rg_command_access_reg_write
&& is_fpr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
DM_CPU_Req#(5, ISA_Decls::FLEN) req = DM_CPU_Req {write: True,
address: fpr_addr,
`ifdef RV32
data: unpack(zeroExtend(rg_data0))
data: unpack(zeroExtend(rg_data0))
`endif
`ifdef RV64
data: unpack({rg_data1, rg_data0})
data: unpack({rg_data1, rg_data0})
`endif
};
f_hart0_fpr_reqs.enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_start: ", cur_cycle, fshow (req));
endrule
};
f_harts_fpr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_fpr_write_finish ( rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_fpr);
let rsp <- pop (f_hart0_fpr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_fpr_write_finish ( rg_abstractcs_busy
&& rg_command_access_reg_write
&& is_fpr);
let rsp <- pop (f_harts_fpr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_write_finish hart %i: ", cur_cycle, core, fshow (rsp));
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
endrules
);
// ----------------------------------------------------------------
// Read FPR
// ----------------------------------------------------------------
// Read FPR
rule rl_fpr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_fpr);
Bit #(FLEN) data = ?;
let req = DM_CPU_Req {write: False, address: fpr_addr, data: data };
f_hart0_fpr_reqs.enq (req);
rg_start_reg_access <= False;
rule rl_fpr_read_start ( rg_abstractcs_busy
&& rg_start_reg_access
&& (! rg_command_access_reg_write)
&& is_fpr
&& (fromInteger(core) == rg_dmcontrol_hartsel));
Bit #(FLEN) data = ?;
let req = DM_CPU_Req {write: False, address: fpr_addr, data: data };
f_harts_fpr_reqs[core].enq (req);
rg_start_reg_access <= False;
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_start: ", cur_cycle, fshow (req));
endrule
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_start hart %i: ", cur_cycle, core, fshow (req));
endrule
// ----------------
// ----------------
rule rl_fpr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_fpr);
let rsp <- pop (f_hart0_fpr_rsps);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_finish: ", cur_cycle, fshow (rsp));
finishRules = rJoinMutuallyExclusive(finishRules,
rules
rule rl_fpr_read_finish ( rg_abstractcs_busy
&& (! rg_command_access_reg_write)
&& is_fpr);
let rsp <- pop (f_harts_fpr_rsps[core]);
if (verbosity != 0)
$display ("%0d: DM_Abstract_Commands.rl_fpr_read_finish hart: ", cur_cycle, core, fshow (rsp));
rg_data0 <= truncate (rsp.data);
rg_data0 <= truncate (rsp.data);
`ifdef RV64
rg_data1 <= rsp.data[63:32];
rg_data1 <= rsp.data[63:32];
`endif
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
rg_abstractcs_cmderr <= (rsp.ok ? DM_ABSTRACTCS_CMDERR_NONE : DM_ABSTRACTCS_CMDERR_HALT_RESUME);
rg_abstractcs_busy <= False;
endrule
endrules
);
`endif
end
`endif
addRules(finishRules);
// ----------------------------------------------------------------
// Read/Write unknown address
@@ -505,10 +545,12 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
method Action reset;
rg_start_reg_access <= False;
f_hart0_gpr_reqs.clear;
f_hart0_gpr_rsps.clear;
f_hart0_csr_reqs.clear;
f_hart0_csr_rsps.clear;
function proj_clear (x) = x.clear();
mapM_(proj_clear, f_harts_gpr_reqs);
mapM_(proj_clear, f_harts_gpr_rsps);
mapM_(proj_clear, f_harts_csr_reqs);
mapM_(proj_clear, f_harts_csr_rsps);
rg_abstractcs_busy <= False;
rg_abstractcs_cmderr <= DM_ABSTRACTCS_CMDERR_NONE;
@@ -552,7 +594,15 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
action
let dm_addr_name = fshow_dm_addr (dm_addr);
if (dm_addr == dm_addr_abstractcs)
if (dm_addr == dm_addr_dmcontrol) begin
rg_dmcontrol_hartsel <= fn_dmcontrol_hartsel(dm_word);
// It is specified that the debugger must not change hartsel while this module is busy.
// If this is done, the debug unit will wedge, so print a warning.
$display ("%0d: DM_Abstract_Commands.write: [", cur_cycle, dm_addr_name,
"] <= 0x%08h: ERROR: must not change hartsel while busy", dm_word);
end
else if (dm_addr == dm_addr_abstractcs)
fa_rg_abstractcs_write (dm_word);
else if (rg_abstractcs_cmderr != DM_ABSTRACTCS_CMDERR_NONE) begin
@@ -593,11 +643,11 @@ module mkDM_Abstract_Commands (DM_Abstract_Commands_IFC);
// ----------------
// Facing CPU/hart
interface Client hart0_gpr_mem_client = toGPClient (f_hart0_gpr_reqs, f_hart0_gpr_rsps);
interface harts_gpr_mem_client = zipWith (toGPClient, f_harts_gpr_reqs, f_harts_gpr_rsps);
`ifdef ISA_F
interface Client hart0_fpr_mem_client = toGPClient (f_hart0_fpr_reqs, f_hart0_fpr_rsps);
interface harts_fpr_mem_client = zipWith (toGPClient, f_harts_fpr_reqs, f_harts_fpr_rsps);
`endif
interface Client hart0_csr_mem_client = toGPClient (f_hart0_csr_reqs, f_hart0_csr_rsps);
interface harts_csr_mem_client = zipWith (toGPClient, f_harts_csr_reqs, f_harts_csr_rsps);
endmodule
// ================================================================

View File

@@ -35,13 +35,14 @@ typedef Bit #(32) DM_Word;
DM_Addr dm_addr_dmcontrol = 'h10;
DM_Addr dm_addr_dmstatus = 'h11;
DM_Addr dm_addr_hartinfo = 'h12;
DM_Addr dm_addr_haltsum = 'h13;
DM_Addr dm_addr_haltsum1 = 'h13;
DM_Addr dm_addr_hawindowsel = 'h14;
DM_Addr dm_addr_hawindow = 'h15;
DM_Addr dm_addr_devtreeaddr0 = 'h19;
DM_Addr dm_addr_authdata = 'h30;
DM_Addr dm_addr_haltregion0 = 'h40;
DM_Addr dm_addr_haltregion31 = 'h5F;
DM_Addr dm_addr_haltsum2 = 'h34;
DM_Addr dm_addr_haltsum3 = 'h35;
DM_Addr dm_addr_haltsum0 = 'h40;
DM_Addr dm_addr_verbosity = 'h60; // Non-standard (not in spec)
@@ -87,14 +88,15 @@ function Fmt fshow_dm_addr (DM_Addr dm_addr);
dm_addr_dmcontrol: $format ("dm_addr_dmcontrol");
dm_addr_dmstatus: $format ("dm_addr_dmstatus");
dm_addr_hartinfo: $format ("dm_addr_hartinfo");
dm_addr_haltsum: $format ("dm_addr_haltsum");
dm_addr_haltsum1: $format ("dm_addr_haltsum1");
dm_addr_hawindowsel: $format ("dm_addr_hawindowsel");
dm_addr_hawindow: $format ("dm_addr_hawindow");
dm_addr_devtreeaddr0: $format ("dm_addr_devtreeaddr0");
dm_addr_authdata: $format ("dm_addr_authdata");
dm_addr_haltregion0: $format ("dm_addr_haltregion0");
dm_addr_haltregion31: $format ("dm_addr_haltregion31");
dm_addr_verbosity: $format ("dm_addr_verbosity");
dm_addr_haltsum2: $format ("dm_addr_haltsum2");
dm_addr_haltsum3: $format ("dm_addr_haltsum3");
dm_addr_haltsum0: $format ("dm_addr_haltsum0");
dm_addr_verbosity: $format ("dm_addr_verbosity");
// Abstract Commands
dm_addr_abstractcs: $format ("dm_addr_abstractcs");
@@ -168,8 +170,8 @@ function Bool fn_dmcontrol_hasel (DM_Word dm_word);
return unpack (dm_word [26]);
endfunction
function Bit #(10) fn_dmcontrol_hartsel (DM_Word dm_word);
return dm_word [25:16];
function Bit #(20) fn_dmcontrol_hartsel (DM_Word dm_word);
return {dm_word [15:6], dm_word[25:16]};
endfunction
function Bool fn_dmcontrol_ndmreset (DM_Word dm_word);

View File

@@ -28,6 +28,7 @@ import FIFOF :: *;
import GetPut :: *;
import ClientServer :: *;
import ConfigReg :: *;
import Vector :: *;
// ----------------
// Other library imports
@@ -40,6 +41,7 @@ import GetPut_Aux :: *;
import ISA_Decls :: *;
import DM_Common :: *;
import ProcTypes :: *;
// ================================================================
// Interface
@@ -54,10 +56,10 @@ interface DM_Run_Control_IFC;
method Action write (DM_Addr dm_addr, DM_Word dm_word);
// ----------------
// Facing a hart: reset and run-control
interface Client #(Bool, Bool) hart0_reset_client;
interface Client #(Bool, Bool) hart0_client_run_halt;
interface Get #(Bit #(4)) hart0_get_other_req;
// Facing harts: reset and run-control
interface Vector #(CoreNum, Client #(Bool, Bool)) harts_reset_client;
interface Vector #(CoreNum, Client #(Bool, Bool)) harts_client_run_halt;
interface Vector #(CoreNum, Get #(Bit #(4))) harts_get_other_req;
// ----------------
// Facing Platform: Non-Debug-Module Reset (reset all except DM)
@@ -78,56 +80,69 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
FIFOF #(Bool) f_ndm_reset_reqs <- mkFIFOF;
FIFOF #(Bool) f_ndm_reset_rsps <- mkFIFOF;
// ----------------------------------------------------------------
// Hart0 run control
Reg #(Bool) rg_ndm_reset_pending <- mkConfigReg(False);
Reg #(Bool) rg_hart0_running <- mkRegU;
// ----------------------------------------------------------------
// Hart run control
Vector #(CoreNum, Reg #(Bool)) rg_harts_hasreset <- replicateM(mkRegU);
Vector #(CoreNum, Reg #(Bool)) rg_harts_resumeack <- replicateM(mkRegU);
Vector #(CoreNum, Reg #(Bool)) rg_harts_running <- replicateM(mkRegU);
// Reset requests to hart
FIFOF #(Bool) f_hart0_reset_reqs <- mkFIFOF;
FIFOF #(Bool) f_hart0_reset_rsps <- mkFIFOF;
Vector #(CoreNum, FIFOF #(Bool)) f_harts_reset_reqs <- replicateM(mkFIFOF);
Vector #(CoreNum, FIFOF #(Bool)) f_harts_reset_rsps <- replicateM(mkFIFOF);
// Run/halt requests to hart and responses
FIFOF #(Bool) f_hart0_run_halt_reqs <- mkFIFOF;
FIFOF #(Bool) f_hart0_run_halt_rsps <- mkFIFOF;
Vector #(CoreNum, FIFOF #(Bool)) f_harts_run_halt_reqs <- replicateM(mkFIFOF);
Vector #(CoreNum, FIFOF #(Bool)) f_harts_run_halt_rsps <- replicateM(mkFIFOF);
// Non-standard requests to hart and responses
// Currently only verbosity
FIFOF #(Bit #(4)) f_hart0_other_reqs <- mkFIFOF;
Vector #(CoreNum, FIFOF #(Bit #(4))) f_harts_other_reqs <- replicateM(mkFIFOF);
// ----------------------------------------------------------------
// rg_dmcontrol
Reg #(Bool) rg_dmcontrol_haltreq <- mkRegU;
// resumereq is a W1 field, no need for a register
Reg #(Bool) rg_dmcontrol_hartreset <- mkRegU;
Reg #(Bool) rg_dmcontrol_ndmreset <- mkRegU;
Reg #(Bool) rg_dmcontrol_dmactive <- mkReg (False);
Reg #(Bit#(20)) rg_dmcontrol_hartsel <- mkReg (0);
Bit#(20) core_num_sel = fromInteger(valueOf(CoreNum));
// ----------------------------------------------------------------
Bit #(32) haltregion0 = { 31'h0, pack (! rg_hart0_running) };
Bit #(32) haltsum = { 31'h0, pack (! rg_hart0_running) };
// We only support haltsum0, so can only support < 33 harts. This will give
// a type error if an unsupported number of cores are requested.
Bit #(32) haltsum0 = zeroExtend(~pack(readVReg(rg_harts_running)));
// ----------------------------------------------------------------
// rg_dmstatus
// Since we currently support only 1 hart,
// Since we currently support only 1 hart at a time,
// 'anyXX' = 'allXX'
// 'allrunning' = NOT 'allhalted'
Bool dmstatus_impebreak = False;
Reg #(Bool) rg_hart0_hasreset <- mkRegU;
Bool dmstatus_allhavereset = rg_hart0_hasreset;
Bool dmstatus_anyhavereset = rg_hart0_hasreset;
Bool dmstatus_allhavereset = rg_dmcontrol_hartsel < core_num_sel && rg_harts_hasreset[rg_dmcontrol_hartsel];
Bool dmstatus_anyhavereset = dmstatus_allhavereset;
Reg #(Bool) rg_dmstatus_allresumeack <- mkRegU;
Bool dmstatus_allresumeack = rg_dmcontrol_hartsel < core_num_sel && rg_harts_resumeack[rg_dmcontrol_hartsel];
Bool dmstatus_anyresumeack = dmstatus_allresumeack;
Bool dmstatus_allresumeack = rg_dmstatus_allresumeack;
Bool dmstatus_anyresumeack = rg_dmstatus_allresumeack;
Bool dmstatus_allnonexistent = False;
Bool dmstatus_allnonexistent = rg_dmcontrol_hartsel >= core_num_sel;
Bool dmstatus_anynonexistent = dmstatus_allnonexistent;
Reg #(Bool) rg_dmstatus_allunavail <- mkReg (False);
Bool dmstatus_allunavail = rg_dmstatus_allunavail;
Bool dmstatus_anyunavail = rg_dmstatus_allunavail;
Bool dmstatus_allunavail = rg_dmcontrol_hartsel < core_num_sel && rg_ndm_reset_pending;
Bool dmstatus_anyunavail = dmstatus_allunavail;
Bool dmstatus_allrunning = rg_hart0_running;
Bool dmstatus_allrunning = rg_dmcontrol_hartsel < core_num_sel && rg_harts_running[rg_dmcontrol_hartsel];
Bool dmstatus_anyrunning = dmstatus_allrunning;
Bool dmstatus_allhalted = (! rg_hart0_running);
Bool dmstatus_allhalted = rg_dmcontrol_hartsel < core_num_sel && (! rg_harts_running[rg_dmcontrol_hartsel]);
Bool dmstatus_anyhalted = dmstatus_allhalted;
DM_Word virt_rg_dmstatus = {9'b0,
@@ -151,21 +166,16 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
pack (False), // devtreevalid
4'h2}; // version
// ----------------------------------------------------------------
// rg_dmcontrol
Reg #(Bool) rg_dmcontrol_haltreq <- mkRegU;
// resumereq is a W1 field, no need for a register
Reg #(Bool) rg_dmcontrol_hartreset <- mkRegU;
Reg #(Bool) rg_dmcontrol_ndmreset <- mkRegU;
Reg #(Bool) rg_dmcontrol_dmactive <- mkConfigReg (False);
DM_Word virt_rg_dmcontrol = {2'b0, // haltreq, resumereq (w-o)
pack (rg_dmcontrol_hartreset),
2'b0,
pack (False), // hasel
10'b0, // hartsel
14'b0,
rg_dmcontrol_hartsel[9:0],
rg_dmcontrol_hartsel[19:10],
1'b0, // setkeepalive
1'b0, // clrkeepalive
1'b0, // setresethaltreq
1'b0, // clrkeepalive
pack (rg_dmcontrol_ndmreset),
pack (rg_dmcontrol_dmactive)};
@@ -183,6 +193,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
rg_dmcontrol_hartreset <= hartreset;
rg_dmcontrol_ndmreset <= ndmreset;
rg_dmcontrol_dmactive <= dmactive;
rg_dmcontrol_hartsel <= hartsel;
// Debug Module reset
if (! dmactive) begin
@@ -207,7 +218,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
end
// Ignore if NDM reset is in progress
else if (rg_dmstatus_allunavail) begin
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
@@ -229,7 +240,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
end
f_ndm_reset_reqs.enq (running);
rg_dmstatus_allunavail <= True;
rg_ndm_reset_pending <= True;
// Error-checking
if (hartreset) begin
@@ -243,8 +254,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
// Hart reset
else if (hartreset) begin
Bool running = (! haltreq);
f_hart0_reset_reqs.enq (running);
rg_hart0_hasreset <= True;
f_harts_reset_reqs[hartsel].enq (running);
rg_harts_hasreset[hartsel] <= True;
// Deassert platform reset
if (verbosity != 0) begin
@@ -265,8 +276,8 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
$display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hasel is not supported",
cur_cycle, dm_word);
if (hartsel != 0)
$display ("%0d:ERROR: %m.dmcontrol_write 0x%08h: hartsel 0x%0h not supported",
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
@@ -275,15 +286,15 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
$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);
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 %i resume request", cur_cycle, hartsel);
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);
else if (haltreq && rg_harts_running[hartsel]) begin
f_harts_run_halt_reqs[hartsel].enq (False);
$display ("%0d: %m.dmcontrol_write: hart %i halt request", cur_cycle, hartsel);
end
end
endaction
@@ -307,35 +318,37 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
// ----------------------------------------------------------------
// System responses
// 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;
// Response from system for hart reset
for (Integer core = 0; core < valueOf(CoreNum); core = core + 1)
rule rl_harts_reset_rsp;
Bool running <- pop (f_harts_reset_rsps[core]);
rg_harts_hasreset[core] <= False;
rg_harts_running[core] <= running;
if (verbosity != 0)
$display ("%0d: %m.rl_hart0_reset_rdp: hart running = ", cur_cycle, fshow (running));
if (verbosity != 0)
$display ("%0d: %m.rl_harts_reset_rsp: hart %i running = ", cur_cycle, core, 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;
writeVReg(rg_harts_running, replicate(running));
rg_ndm_reset_pending <= False;
if (verbosity != 0)
$display ("%0d: %m.rl_ndm_reset_rsp: hart running = ", cur_cycle, fshow (running));
$display ("%0d: %m.rl_ndm_reset_rsp: harts running = ", cur_cycle, fshow (running));
endrule
for (Integer core = 0; core < valueOf(CoreNum); core = core + 1)
// 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;
rule rl_harts_run_rsp (! f_ndm_reset_rsps.notEmpty);
let running <- pop (f_harts_run_halt_rsps[core]);
rg_harts_running[core] <= running;
if (running)
rg_dmstatus_allresumeack <= True;
rg_harts_resumeack[core] <= True;
if (verbosity != 0)
$display ("%0d: %m.rl_hart0_run_rsp: 'running' = ", cur_cycle, fshow (running));
$display ("%0d: %m.rl_harts_run_rsp hart: hart %i 'running' = ", cur_cycle, core, fshow (running));
endrule
// ----------------------------------------------------------------
@@ -349,21 +362,24 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
f_ndm_reset_reqs.clear;
f_ndm_reset_rsps.clear;
f_hart0_reset_reqs.clear;
f_hart0_reset_rsps.clear;
function proj_clear (x) = x.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;
mapM_(proj_clear, f_harts_reset_reqs);
mapM_(proj_clear, f_harts_reset_rsps);
writeVReg(rg_harts_running, replicate(True)); // Safe approximation of whether the CPU is running or not
mapM_(proj_clear, f_harts_run_halt_reqs);
mapM_(proj_clear, f_harts_run_halt_rsps);
rg_dmcontrol_haltreq <= False;
rg_dmcontrol_hartreset <= False;
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
writeVReg(rg_harts_hasreset, replicate(False));
writeVReg(rg_harts_resumeack, replicate(False));
rg_ndm_reset_pending <= False;
rg_verbosity <= 0;
@@ -379,8 +395,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
DM_Word dm_word = case (dm_addr)
dm_addr_dmcontrol: virt_rg_dmcontrol;
dm_addr_dmstatus: virt_rg_dmstatus;
dm_addr_haltsum: haltsum;
dm_addr_haltregion0: haltregion0;
dm_addr_haltsum0: haltsum0;
dm_addr_verbosity: extend (rg_verbosity);
endcase;
@@ -400,7 +415,7 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
dm_addr_dmcontrol: fa_rg_dmcontrol_write (dm_word);
dm_addr_verbosity: begin
rg_verbosity <= truncate (dm_word);
f_hart0_other_reqs.enq (truncate (dm_word));
f_harts_other_reqs[rg_dmcontrol_hartsel].enq (truncate (dm_word));
end
default: noAction;
endcase
@@ -409,13 +424,13 @@ module mkDM_Run_Control (DM_Run_Control_IFC);
// ----------------
// Facing Hart: Reset, Run-control, etc.
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);
interface harts_reset_client = zipWith(toGPClient, f_harts_reset_reqs, f_harts_reset_rsps);
interface harts_client_run_halt = zipWith(toGPClient, f_harts_run_halt_reqs, f_harts_run_halt_rsps);
interface harts_get_other_req = map (toGet, f_harts_other_reqs);
// ----------------
// Facing Platform: Non-Debug-Module Reset (reset all except DM)
interface Client ndm_reset_client = toGPClient (f_ndm_reset_reqs, f_ndm_reset_rsps);
interface ndm_reset_client = toGPClient (f_ndm_reset_reqs, f_ndm_reset_rsps);
endmodule
// ================================================================

View File

@@ -71,6 +71,7 @@ import FIFO :: *;
import GetPut :: *;
import ClientServer :: *;
import SpecialFIFOs :: *;
import Vector :: *;
// ----------------
// Other library imports
@@ -84,6 +85,7 @@ import AXI4 :: *;
import ISA_Decls :: *;
import Fabric_Defs :: *;
import ProcTypes :: *;
import DM_Common :: *;
import DM_CPU_Req_Rsp :: *;
@@ -111,20 +113,20 @@ interface Debug_Module_IFC;
// This section replicated for additional harts.
// Reset and run-control
interface Client #(Bool, Bool) hart0_reset_client;
interface Client #(Bool, Bool) hart0_client_run_halt;
interface Get #(Bit #(4)) hart0_get_other_req;
interface Vector #(CoreNum, Client #(Bool, Bool)) harts_reset_client;
interface Vector #(CoreNum, Client #(Bool, Bool)) harts_client_run_halt;
interface Vector #(CoreNum, Get #(Bit #(4))) harts_get_other_req;
// GPR access
interface Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN))) harts_gpr_mem_client;
// FPR access
`ifdef ISA_F
interface Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN))) harts_fpr_mem_client;
`endif
// CSR access
interface Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_client;
interface Vector #(CoreNum, Client #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN))) harts_csr_mem_client;
// ----------------
// Facing Platform
@@ -187,13 +189,11 @@ module mkDebug_Module (Debug_Module_IFC);
if ( (dm_addr == dm_addr_dmcontrol)
|| (dm_addr == dm_addr_dmstatus)
|| (dm_addr == dm_addr_hartinfo)
|| (dm_addr == dm_addr_haltsum)
|| (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_haltregion0)
|| (dm_addr == dm_addr_haltregion31)
|| (dm_addr == dm_addr_verbosity))
dm_word <- dm_run_control.av_read (dm_addr);
@@ -241,21 +241,25 @@ module mkDebug_Module (Debug_Module_IFC);
endmethod
method Action write (DM_Addr dm_addr, DM_Word dm_word) if (dm_run_control.dmactive);
Bool handled = False;
if ( (dm_addr == dm_addr_dmcontrol)
|| (dm_addr == dm_addr_dmstatus)
|| (dm_addr == dm_addr_hartinfo)
|| (dm_addr == dm_addr_haltsum)
|| (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_haltregion0)
|| (dm_addr == dm_addr_haltregion31)
|| (dm_addr == dm_addr_verbosity))
|| (dm_addr == dm_addr_verbosity)) begin
dm_run_control.write (dm_addr, dm_word);
handled = True;
end
else if ( (dm_addr == dm_addr_abstractcs)
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)
@@ -270,22 +274,26 @@ module mkDebug_Module (Debug_Module_IFC);
|| (dm_addr == dm_addr_data10)
|| (dm_addr == dm_addr_data11)
|| (dm_addr == dm_addr_abstractauto)
|| (dm_addr == dm_addr_progbuf0))
|| (dm_addr == dm_addr_progbuf0)) begin
dm_abstract_commands.write (dm_addr, dm_word);
handled = True;
end
else if ( (dm_addr == dm_addr_sbcs)
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))
|| (dm_addr == dm_addr_sbdata3)) begin
dm_system_bus.write (dm_addr, dm_word);
handled = True;
end
else begin
if (! handled) begin
// TODO: set error status?
noAction;
end
@@ -297,23 +305,23 @@ module mkDebug_Module (Debug_Module_IFC);
endinterface
// ----------------
// Facing CPU/hart0
// Facing CPU/harts
// Reset and run-control
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;
interface harts_reset_client = dm_run_control.harts_reset_client;
interface harts_client_run_halt = dm_run_control.harts_client_run_halt;
interface harts_get_other_req = dm_run_control.harts_get_other_req;
// GPR access
interface Client hart0_gpr_mem_client = dm_abstract_commands.hart0_gpr_mem_client;
interface harts_gpr_mem_client = dm_abstract_commands.harts_gpr_mem_client;
// FPR access
`ifdef ISA_F
interface Client hart0_fpr_mem_client = dm_abstract_commands.hart0_fpr_mem_client;
interface harts_fpr_mem_client = dm_abstract_commands.harts_fpr_mem_client;
`endif
// CSR access
interface Client hart0_csr_mem_client = dm_abstract_commands.hart0_csr_mem_client;
interface harts_csr_mem_client = dm_abstract_commands.harts_csr_mem_client;
// ----------------
// Facing Platform