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:
rsnikhil
2020-02-04 16:02:53 -05:00
parent 4960a59da0
commit 83829590dd
70 changed files with 94735 additions and 89999 deletions

View File

@@ -136,9 +136,6 @@ interface CoreRenameDebug;
endinterface
interface Core;
// Initialize
interface Server #(Bit #(0), Bit #(0)) init_server;
// core request & indication
interface CoreReq coreReq;
interface CoreIndInv coreIndInv;
@@ -206,13 +203,6 @@ module mkCore#(CoreId coreId)(Core);
// ================================================================
Integer verbosity = 0; // More levels of verbosity control than 'Bool verbose'
// ----------------
// Init requests and responses
FIFOF #(Bit #(0)) f_init_reqs <- mkFIFOF;
FIFOF #(Bit #(0)) f_init_rsps <- mkFIFOF;
Reg#(Bool) outOfReset <- mkReg(False);
rule rl_outOfReset if (!outOfReset);
$fwrite(stderr, "mkProc came out of reset\n");
@@ -1297,28 +1287,9 @@ module mkCore#(CoreId coreId)(Core);
// ================================================================
`endif
// ================================================================
// Init interface
rule rl_init;
let tok <- pop (f_init_reqs);
csrf.init;
started <= False;
`ifdef INCLUDE_GDB_CONTROL
rg_core_run_state <= CORE_RUNNING;
`endif
f_init_rsps.enq (tok);
endrule
// ================================================================
// INTERFACE
// Initialize
interface init_server = toGPServer (f_init_reqs, f_init_rsps);
interface CoreReq coreReq;
method Action start(
Bit#(64) startpc,
@@ -1330,7 +1301,7 @@ module mkCore#(CoreId coreId)(Core);
rg_core_run_state <= CORE_RUNNING;
`endif
mmio.setHtifAddrs(toHostAddr, fromHostAddr);
// start rename debug
commitStage.startRenameDebug;
endmethod

View File

@@ -49,9 +49,6 @@ import SoC_Map :: *;
// ================================================================
interface CsrFile;
// Initialize to platform-level reset spec
method Action init;
// Read
method Data rd(CSR csr);
// normal write by CSRXXX inst to any CSR
@@ -672,28 +669,6 @@ module mkCsrFile #(Data hartid)(CsrFile);
// ================================================================
// INTERFACE
method Action init;
// Note: we initialize only certain CSRs (platform-level spec)
// Current privilege
prv_reg <= prvM;
// Machine-level CSRs
mstatus_csr <= 0;
mie_csr <= 0;
mip_csr <= 0;
minstret_csr <= 0;
mcycle_csr <= 0;
// User-level CSRs
time_reg <= 0;
`ifdef INCLUDE_GDB_CONTROL
// Debug Module CSRs
rg_dcsr <= zeroExtend (dcsr_reset_value);
rg_dpc <= truncate (soc_map_struct.pc_reset_value);
`endif
endmethod
method Data rd(CSR csr);
return get_csr(csr)._read;
endmethod

View File

@@ -107,8 +107,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
awregion: fabric_default_region,
awuser: fabric_default_user};
let mem_req_wr_data = AXI4_Wr_Data {wid: fabric_default_id,
wdata: st_val,
let mem_req_wr_data = AXI4_Wr_Data {wdata: st_val,
wstrb: strb,
wlast: True,
wuser: fabric_default_user};

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2018 Massachusetts Institute of Technology
// Portions (c) 2019-2020 Bluespec, Inc.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -21,8 +22,6 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Portions (c) 2019 Bluespec, Inc.
// This file is adapted from: MIT-riscy/riscy-OOO/procs/lib/MMIOPlatform.bsv
// Modifications to fit into Bluespec's RISC-V execution environments.

View File

@@ -108,8 +108,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
awregion: fabric_default_region,
awuser: fabric_default_user};
let mem_req_wr_data = AXI4_Wr_Data {wid: fabric_default_id,
wdata: st_val,
let mem_req_wr_data = AXI4_Wr_Data {wdata: st_val,
wstrb: strb,
wlast: True,
wuser: fabric_default_user};

View File

@@ -1,5 +1,7 @@
package Proc;
// Note: this module corresponds to module 'mkCPU' in Piccolo/Flute.
// Copyright (c) 2018 Massachusetts Institute of Technology
// Portions Copyright (c) 2019-2020 Bluespec, Inc.
//
@@ -103,12 +105,6 @@ module mkProc (Proc_IFC);
// Verbosity: 0=quiet; 1=instruction trace; 2=more detail
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0);
// ----------------
// Init requests and responses
FIFOF #(Bit #(0)) f_init_reqs <- mkFIFOF;
FIFOF #(Bit #(0)) f_init_rsps <- mkFIFOF;
// ----------------
// MMIO
@@ -201,25 +197,6 @@ module mkProc (Proc_IFC);
end
// ================================================================
// Init
rule rl_init_start;
let x <- pop (f_init_reqs);
llc_axi4_adapter.reset;
mmio_axi4_adapter.reset;
for (Integer j = 0; j < valueof(CoreNum); j = j+1)
core [j].init_server.request.put (?);
endrule
rule rl_init_finish;
for (Integer j = 0; j < valueof(CoreNum); j = j+1)
let tok <- core [j].init_server.response.get;
f_init_rsps.enq (?);
endrule
// ----------------
// Termination detection
for(Integer i = 0; i < valueof(CoreNum); i = i+1) begin
@@ -229,7 +206,9 @@ module mkProc (Proc_IFC);
endrule
end
// ================================================================
// Print out values written 'tohost'
rule rl_tohost;
let x <- mmioPlatform.to_host;
$display ("%0d: mmioPlatform.rl_tohost: 0x%0x (= %0d)", cur_cycle, x, x);
@@ -251,11 +230,9 @@ module mkProc (Proc_IFC);
// ================================================================
// INTERFACE
// Reset
interface Server init_server = toGPServer (f_init_reqs, f_init_rsps);
// ----------------
// Start the cores running
// Use toHostAddr = 0 if not monitoring tohost
method Action start (Addr startpc, Addr tohostAddr, Addr fromhostAddr);
action
for(Integer i = 0; i < valueof(CoreNum); i = i+1)
@@ -264,8 +241,8 @@ module mkProc (Proc_IFC);
mmioPlatform.start (tohostAddr, fromhostAddr);
$display ("Proc.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h",
startpc, tohostAddr, fromhostAddr);
$display ("%0d: %m.method start: startpc %0h, tohostAddr %0h, fromhostAddr %0h",
cur_cycle, startpc, tohostAddr, fromhostAddr);
endmethod
// ----------------
@@ -312,18 +289,19 @@ module mkProc (Proc_IFC);
`ifdef INCLUDE_GDB_CONTROL
// run/halt, gpr, mem and csr control goes to core
interface Server hart0_run_halt_server = core [0].hart0_run_halt_server;
interface Put hart0_put_other_req;
method Action put (Bit #(4) req);
cfg_verbosity <= req;
endmethod
endinterface
interface Server hart0_gpr_mem_server = core[0].hart0_gpr_mem_server;
`ifdef ISA_F
interface Server hart0_fpr_mem_server = core[0].hart0_fpr_mem_server;
`endif
interface Server hart0_csr_mem_server = core[0].hart0_csr_mem_server;
// We don't implement 'other' functionality
interface Put hart0_put_other_req;
method Action put (Bit #(4) req);
cfg_verbosity <= req;
endmethod
endinterface
`endif
`ifdef INCLUDE_TANDEM_VERIF

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2019 Bluespec, Inc. All Rights Reserved
// Copyright (c) 2016-2020 Bluespec, Inc. All Rights Reserved
package Proc_IFC;
@@ -34,11 +34,10 @@ import Trace_Data2 :: *;
// because the RISCY-OOO mkProc contains those elements.
interface Proc_IFC;
// Init
interface Server #(Token, Token) init_server;
// ----------------
// Start the cores running
// Use toHostAddr = 0 if not monitoring tohost
method Action start (Addr startpc, Addr tohostAddr, Addr fromhostAddr);
// ----------------

View File

@@ -91,7 +91,53 @@ import DM_CPU_Req_Rsp ::*;
// The Core module
(* synthesize *)
module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
module mkCoreW #(Reset dm_power_on_reset)
(CoreW_IFC #(N_External_Interrupt_Sources));
// ================================================================
// Notes on 'reset'
// This module's default reset (Verilog RST_N) is a
// 'non-debug-module reset', or 'ndm-reset': it resets everything
// in mkCoreW other than the optional RISC-V Debug Module (DM).
// DM is reset ONLY by 'dm_power_on_reset' (parameter of this module).
// This is expected to be performed exactly once, on power-up.
// Note: DM has an internal functionality that the DM spec calls
// 'dm_reset'. This is not really an electrical reset, it is just
// a module initializer wholly within the DM to put it into a
// known state. To be able to do a dm_reset, the DM has to be
// working already, at least to the point that it can field DMI
// requests from the external debugger asking the DM to proform a
// dm_reset.
// DM can ask the environment to perform an 'ndm-reset', which the
// environment does by asserting the default reset (RST_N). At the
// same time, the environment may also reset part or all of the
// rest of the SoC.
// DM can also individually reset each hart in mkCPU.
// 'hart' = hardware thread = independent PC and fetch-and-execute pipeline.
// mkCPU (instantiated in this module) has one or more harts.
// This hart-reset logic is entirely within this module.
// ================================================================
// The CPU's (hart's) reset is the ``or'' of the default reset
// (power-on reset) and the Debug Module's 'hart_reset' control.
let ndm_reset <- exposeCurrentReset;
`ifdef INCLUDE_GDB_CONTROL
let clk <- exposeCurrentClock;
Bool initial_reset_val = False;
Integer hart_reset_duration = 10; // NOTE: assuming 10 cycle reset enough for hart
let dm_hart0_reset_controller <- mkReset(hart_reset_duration, initial_reset_val, clk);
let hart0_reset <- mkResetEither (ndm_reset, dm_hart0_reset_controller.new_rst);
`else
let hart0_reset = ndm_reset;
`endif
// ================================================================
// STATE
@@ -100,7 +146,8 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
SoC_Map_IFC soc_map <- mkSoC_Map;
// RISCY-OOO processor
Proc_IFC proc <- mkProc;
// TODO (when we do multicore): need resets for each core.
Proc_IFC proc <- mkProc (reset_by hart0_reset);
// A 2x3 fabric for connecting {CPU, Debug_Module} to {Fabric, PLIC}
Fabric_2x3_IFC fabric_2x3 <- mkFabric_2x3;
@@ -108,13 +155,9 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
// PLIC (Platform-Level Interrupt Controller)
PLIC_IFC_16_2_7 plic <- mkPLIC_16_2_7;
// Reset requests from SoC and responses to SoC
FIFOF #(Bit #(0)) f_reset_reqs <- mkFIFOF;
FIFOF #(Bit #(0)) f_reset_rsps <- mkFIFOF;
`ifdef INCLUDE_GDB_CONTROL
// Debug Module
Debug_Module_IFC debug_module <- mkDebug_Module;
Debug_Module_IFC debug_module <- mkDebug_Module (reset_by dm_power_on_reset);
`endif
`ifdef INCLUDE_TANDEM_VERIF
@@ -127,97 +170,37 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
TV_Encode_IFC tv_encode <- mkTV_Encode;
`endif
// HTIF locations (for debugging only)
Reg #(Bit #(64)) rg_tohost_addr <- mkReg (0);
Reg #(Bit #(64)) rg_fromhost_addr <- mkReg (0);
// ================================================================
// RESET
// There are two sources of reset requests to the CPU: externally
// from the SoC and, optionally, the DM. The SoC requires a
// response, the DM does not. When both requestors are present
// (i.e., DM is present), we merge the reset requests into the CPU,
// and we remember which one was the requestor in
// f_reset_requestor, so that we know whether or not to respond to
// the SoC.
// TODO (multicore): currently the incoming 'init' token is from
// Debug Module's hart0_get_reset_req, but when we call
// proc.init_server here, we are resetting all the cores, i.e., all
// the harts. Needs to be cleaned up.
Bit #(1) reset_requestor_dm = 0;
Bit #(1) reset_requestor_soc = 1;
`ifdef INCLUDE_GDB_CONTROL
FIFOF #(Bit #(1)) f_reset_requestor <- mkFIFOF;
`endif
// Reset-hart0 request from SoC
rule rl_cpu_hart0_reset_from_soc_start;
let req <- pop (f_reset_reqs);
proc.init_server.request.put (?); // CPU
plic.server_reset.request.put (?); // PLIC
fabric_2x3.reset; // Local 2x3 Fabric
`ifdef INCLUDE_TANDEM_VERIF
tv_encode.reset;
`endif
// Hart-reset from DM
`ifdef INCLUDE_GDB_CONTROL
// Remember the requestor, so we can respond to it
f_reset_requestor.enq (reset_requestor_soc);
`endif
$display ("%0d: Core.rl_cpu_hart0_reset_from_soc_start (requestor %0d)", cur_cycle, reset_requestor_soc);
Reg #(Bit #(8)) rg_hart0_reset_delay <- mkReg (0);
Reg #(Bit #(64)) rg_tohost_addr <- mkReg (0);
Reg #(Bit #(64)) rg_fromhost_addr <- mkReg (0);
rule rl_dm_hart0_reset (rg_hart0_reset_delay == 0);
let x <- debug_module.hart0_reset_client.request.get;
dm_hart0_reset_controller.assertReset;
rg_hart0_reset_delay <= fromInteger (hart_reset_duration + 200); // NOTE: heuristic
$display ("%0d: %m.rl_dm_hart0_reset: asserting hart0 reset for %0d cycles",
cur_cycle, hart_reset_duration);
endrule
`ifdef INCLUDE_GDB_CONTROL
// Reset-hart0 from Debug Module
rule rl_cpu_hart0_reset_from_dm_start;
let req <- debug_module.hart0_get_reset_req.get;
rule rl_dm_hart0_reset_wait (rg_hart0_reset_delay != 0);
if (rg_hart0_reset_delay == 1) begin
let pc = soc_map_struct.pc_reset_value;
proc.start (pc, rg_tohost_addr, rg_fromhost_addr);
proc.init_server.request.put (?); // CPU
plic.server_reset.request.put (?); // PLIC
fabric_2x3.reset; // Local 2x3 fabric
`ifdef INCLUDE_TANDEM_VERIF
tv_encode.reset;
`endif
// Remember the requestor, so we can respond to it
f_reset_requestor.enq (reset_requestor_dm);
$display ("%0d: Core.rl_cpu_hart0_reset_from_dm_start (requestor %0d)", cur_cycle, reset_requestor_dm);
endrule
`endif
FIFOF #(Bit #(0)) f_proc_start <- mkFIFOF;
rule rl_cpu_hart0_reset_complete;
let rsp1 <- proc.init_server.response.get; // CPU
let rsp3 <- plic.server_reset.response.get; // PLIC
plic.set_addr_map (zeroExtend (soc_map.m_plic_addr_base),
zeroExtend (soc_map.m_plic_addr_lim));
Bit #(1) requestor = reset_requestor_soc;
`ifdef INCLUDE_GDB_CONTROL
requestor <- pop (f_reset_requestor);
`endif
if (requestor == reset_requestor_soc)
f_reset_rsps.enq (?);
// Start running the cores
f_proc_start.enq (?);
$display ("%0d: Core.rl_cpu_hart0_reset_complete; starting proc", cur_cycle);
endrule
rule rl_cpu_hart0_reset_proc_start;
let x <- pop (f_proc_start);
proc.start (soc_map_struct.pc_reset_value,
rg_tohost_addr,
rg_fromhost_addr);
$display ("%0d: Core.rl_cpu_hart0_reset_proc_start; started running proc", cur_cycle);
Bool is_running = True;
debug_module.hart0_reset_client.response.put (is_running);
$display ("%0d: %m.rl_dm_hart0_reset_wait: proc.start (pc %0h, tohostAddr %0h, fromhostAddr %0h",
cur_cycle, pc, rg_tohost_addr, rg_fromhost_addr);
end
rg_hart0_reset_delay <= rg_hart0_reset_delay - 1;
endrule
`endif
`ifdef INCLUDE_GDB_CONTROL
// ================================================================
@@ -359,13 +342,6 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
// $display ("%0d: Core.rl_relay_external_interrupts: relaying: %d", cur_cycle, pack (x));
endrule
// TODO: fixup. Need to combine NMIs from multiple sources (cache, fabric, devices, ...)
rule rl_relay_non_maskable_interrupt;
proc.non_maskable_interrupt_req (False);
// $display ("%0d: Core.rl_relay_non_maskable_interrupts: relaying: %d", cur_cycle, pack (x));
endrule
// ================================================================
// INTERFACE
@@ -377,16 +353,26 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
proc.set_verbosity (verbosity);
endmethod
method Action set_htif_addrs (Bit #(64) tohost_addr, Bit #(64) fromhost_addr);
// ----------------------------------------------------------------
// Start
method Action start (Bit #(64) tohost_addr, Bit #(64) fromhost_addr);
plic.set_addr_map (zeroExtend (soc_map.m_plic_addr_base),
zeroExtend (soc_map.m_plic_addr_lim));
let pc = soc_map_struct.pc_reset_value;
proc.start (pc, tohost_addr, fromhost_addr);
`ifdef INCLUDE_GDB_CONTROL
// Save for potential future use by rl_dm_hart0_reset
rg_tohost_addr <= tohost_addr;
rg_fromhost_addr <= fromhost_addr;
`endif
$display ("%0d: %m.method start: proc.start (pc %0d, tohostAddr %0h, fromhostAddr %0h)",
cur_cycle, pc, tohost_addr, fromhost_addr);
endmethod
// ----------------------------------------------------------------
// Soft reset
interface Server cpu_reset_server = toGPServer (f_reset_reqs, f_reset_rsps);
// ----------------------------------------------------------------
// AXI4 Fabric interfaces
@@ -401,6 +387,14 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
interface core_external_interrupt_sources = plic.v_sources;
// ----------------------------------------------------------------
// Non-maskable interrupt request
method Action nmi_req (Bool set_not_clear);
// TODO: fixup; passing const False for now
proc.non_maskable_interrupt_req (False);
endmethod
`ifdef INCLUDE_GDB_CONTROL
// ----------------------------------------------------------------
// Optional DM interfaces
@@ -408,13 +402,13 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources));
// ----------------
// DMI (Debug Module Interface) facing remote debugger
interface DMI dm_dmi = debug_module.dmi;
interface DMI dmi = debug_module.dmi;
// ----------------
// Facing Platform
// Non-Debug-Module Reset (reset all except DM)
interface Get dm_ndm_reset_req_get = debug_module.get_ndm_reset_req;
interface Client ndm_reset_client = debug_module.ndm_reset_client;
`endif
`ifdef INCLUDE_TANDEM_VERIF

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2019 Bluespec, Inc. All Rights Reserved.
// Copyright (c) 2018-2020 Bluespec, Inc. All Rights Reserved.
package CoreW_IFC;
@@ -6,9 +6,8 @@ package CoreW_IFC;
// This package defines the interface of a CoreW module which
// contains:
// - mkProc (the RISC-V CPU; this a variant of MIT's RISCY-OOO mkProc)
// Note: MIT's RISCY-OOO internally contains a 'mkCore'
// and hence this interface and its module is called
// 'CoreW', to disambiguate.
// Note: MIT's RISCY-OOO internally has a 'mkCore' and hence this
// interface and its module is called 'CoreW', to disambiguate.
// - mkFabric_2x3
// - mkNear_Mem_IO_AXI4
// - mkPLIC_16_2_7
@@ -48,16 +47,14 @@ import TV_Info :: *;
interface CoreW_IFC #(numeric type t_n_interrupt_sources);
// ----------------------------------------------------------------
// Debugging: set core's verbosity, htif addrs
// Debugging: set core's verbosity
method Action set_verbosity (Bit #(4) verbosity, Bit #(64) logdelay);
method Action set_htif_addrs (Bit #(64) tohost_addr, Bit #(64) fromhost_addr);
// ----------------------------------------------------------------
// Soft reset
// Start
interface Server #(Bit #(0), Bit #(0)) cpu_reset_server;
method Action start (Bit #(64) tohost_addr, Bit #(64) fromhost_addr);
// ----------------------------------------------------------------
// AXI4 Fabric interfaces
@@ -73,6 +70,12 @@ interface CoreW_IFC #(numeric type t_n_interrupt_sources);
interface Vector #(t_n_interrupt_sources, PLIC_Source_IFC) core_external_interrupt_sources;
// ----------------------------------------------------------------
// Non-maskable interrupt request
(* always_ready, always_enabled *)
method Action nmi_req (Bool set_not_clear);
`ifdef INCLUDE_GDB_CONTROL
// ----------------------------------------------------------------
// Optional Debug Module interfaces
@@ -80,13 +83,13 @@ interface CoreW_IFC #(numeric type t_n_interrupt_sources);
// ----------------
// DMI (Debug Module Interface) facing remote debugger
interface DMI dm_dmi;
interface DMI dmi;
// ----------------
// Facing Platform
// Non-Debug-Module Reset (reset all except DM)
interface Get #(Bit #(0)) dm_ndm_reset_req_get;
interface Client #(Bool, Bool) ndm_reset_client;
`endif
`ifdef INCLUDE_TANDEM_VERIF

View File

@@ -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);

View File

@@ -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
// ================================================================

View File

@@ -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};

View File

@@ -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;

View File

@@ -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:

View File

@@ -1,16 +1,19 @@
// This file is a modified version of: RISCY_OOO/procs/lib/LLCDmaConnect.bsv
// The original module had, as 2nd parameter, MemLoaderMemClient memLoader
// The memLoader assumed only write-transactions (to load memory), and
// discarded load responses.
// Here, the module instead offers an AXI4_Slave interface to be
// connected to the AXI4_Master of the Debug Module.
// This axi4_slave accepts and responds to both read and write transactions.
// Copyright (c) 2017 Massachusetts Institute of Technology
// Portions Copyright (c) 2019-2020 Bluespec, Inc.
//
// This file is a modified version of: RISCY_OOO/procs/lib/LLCDmaConnect.bsv
// Bluespec: this file is has many modifications.
// The original module had 3 params and had an Empty interface.
// The 2nd param was: MemLoaderMemClient memLoader
// which issued only write-transactions (to load memory).
// The module discarded write responses, and ignored read-requests.
// Here, that module parameter is removed and, instead, the module has an
// AXI4_Slave interface, to be connected to the AXI4_Master of the
// Debug Module. This axi4_slave accepts, processes and responds
// to both read and write transactions.
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -87,31 +90,33 @@ typedef union tagged {
} LLCDmaReqId deriving(Bits, Eq, FShow);
// ================================================================
// Functions to insert/extract axi4 data into/from a cache line
// Help functions for read-modify-writes of 4-Byte values on a 64-Byte Cache Line
// For writing, position the AXI4 8-byte data and 8-bit byte-enable
// into a 64-byte line and 64-bit line-byte-enable
function Tuple3 #(Addr,
Line,
LineByteEn) fn_line_and_line_byteen_from_axi4 (Addr axi4_addr,
Bit #(8) axi4_byteen,
Bit #(64) axi4_data);
Vector #(8, Bit #(64)) line_dwords = replicate (0);
Vector #(8, Bit #(8)) line_dword_byteen = replicate (0);
Bit #(3) dword_index = axi4_addr [5:3];
line_dwords [dword_index] = axi4_data;
line_dword_byteen [dword_index] = axi4_byteen;
Addr line_addr = { axi4_addr [63:6], 6'b0 };
return tuple3 (line_addr,
unpack (pack (line_dwords)),
unpack (pack (line_dword_byteen)));
typedef enum {CACHELINE_CACHE_INVALID,
CACHELINE_CACHE_WRITING_BACK,
CACHELINE_CACHE_RELOADING,
CACHELINE_CACHE_CLEAN,
CACHELINE_CACHE_DIRTY
} Cacheline_Cache_State
deriving (Bits, Eq, FShow);
function Addr fn_align_addr_to_line (Addr addr);
Addr line_addr = { addr [63:6], 6'b0 };
return line_addr;
endfunction
// For reading, extract 8-byte AXI4 data from a 64-byte line
function Bit #(64) fn_axi4_data_from_line (Line line, Bit #(3) dword_in_line);
Vector #(8, Bit #(64)) line_words = unpack (pack (line));
Bit #(64) dw = line_words [dword_in_line];
return dw;
function Bool fn_addr_is_in_line (Addr addr, Addr line_addr);
return (fn_align_addr_to_line (addr) == line_addr);
endfunction
function Bit #(64) fn_expand_strb_to_mask (Bit #(8) strb);
function Bit #(8) fn_bit_to_byte (Integer j);
return ((strb [j] == 1'b1) ? 8'hFF : 8'h00);
endfunction
Vector #(8, Bit #(8)) v = genWith (fn_bit_to_byte);
return pack (v);
endfunction
// ================================================================
@@ -133,6 +138,228 @@ module mkLLCDmaConnect #(
// Slave transactor for requests from Debug Module
AXI4_Slave_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) axi4_slave_xactor <- mkAXI4_Slave_Xactor;
// ================================================================
// These regs are a 1-location local cache for an LLC Cache Line,
// to avoid doing a full read-modify-write to the LLC on each transaction.
Reg #(Cacheline_Cache_State) rg_cacheline_cache_state <- mkReg (CACHELINE_CACHE_CLEAN);
Reg #(Addr) rg_cacheline_cache_addr <- mkReg (1); // never matches an LLC line addr
Reg #(Line) rg_cacheline_cache_data <- mkRegU;
// Writeback dirty cacheline_cache if no new store requests within n-cycles
Reg #(Bit #(10)) rg_cacheline_cache_dirty_delay <- mkReg (0);
// ================================================================
// Write transactions from the external client (e.g., Debug Module)
// Respond to store-requests from the external client on store-hit
rule rl_handle_MemLoader_st_req ( ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
|| (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY))
&& (fn_addr_is_in_line (axi4_slave_xactor.o_wr_addr.first.awaddr,
rg_cacheline_cache_addr)));
let wr_addr <- pop_o (axi4_slave_xactor.o_wr_addr);
let wr_data <- pop_o (axi4_slave_xactor.o_wr_data);
Addr addr = wr_addr.awaddr;
Bit #(64) data = wr_data.wdata;
Bit #(64) mask = fn_expand_strb_to_mask (wr_data.wstrb);
// Read rg_cacheline_cache_data as 64-bit words
Vector #(8, Bit #(64)) line_dwords = unpack (pack (rg_cacheline_cache_data));
// Modify relevant bytes of relevant dword
Bit #(3) dword_in_line = addr [5:3];
Bit #(64) old_dword = line_dwords [dword_in_line];
Bit #(64) new_dword = ((old_dword & (~ mask)) | (data & mask));
line_dwords [dword_in_line] = new_dword;
// Save it
rg_cacheline_cache_data <= unpack (pack (line_dwords));
rg_cacheline_cache_state <= CACHELINE_CACHE_DIRTY;
rg_cacheline_cache_dirty_delay <= '1; // start write-back delay countdown
// Send response to external client
AXI4_Wr_Resp #(Wd_Id, Wd_User)
wr_resp = AXI4_Wr_Resp {bid: 0, // TODO: change uniformly to Fabric_id
bresp: axi4_resp_okay,
buser: ?};
axi4_slave_xactor.i_wr_resp.enq (wr_resp);
if (verbosity >= 2) begin
$display ("%0d: %m.rl_handle_MemLoader_st_req: addr %0h data %0h strb %0h",
cur_cycle, wr_addr.awaddr, wr_data.wdata, wr_data.wstrb);
$display (" old_dword: %0h", old_dword);
$display (" new_dword: %0h", old_dword);
end
endrule
// ================================================================
// Read transactions from the external memory client (e.g., Debug Module)
// Responds to load-requests from the external client on load-hit
rule rl_handle_MemLoader_ld_req ( ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
|| (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY))
&& (fn_addr_is_in_line (axi4_slave_xactor.o_rd_addr.first.araddr,
rg_cacheline_cache_addr)));
let rd_addr <- pop_o (axi4_slave_xactor.o_rd_addr);
Addr addr = rd_addr.araddr;
// Read rg_cacheline_cache as 64-bit words
Vector #(8, Bit #(64)) line_dwords = unpack (pack (rg_cacheline_cache_data));
Bit #(3) dword_in_line = addr [5:3];
Bit #(64) dword = line_dwords [dword_in_line];
// Send response to external client
AXI4_Rd_Data #(Wd_Id, Wd_Data, Wd_User)
rd_data = AXI4_Rd_Data {rid: 0, // TODO: fixup
rdata: dword,
rresp: axi4_resp_okay,
rlast: True,
ruser: ?};
axi4_slave_xactor.i_rd_data.enq (rd_data);
if (verbosity >= 2) begin
$display ("%0d: %m.rl_handle_MemLoader_ld_req: addr %0h", cur_cycle, rd_addr.araddr);
$display (" dword: %0h", dword);
end
endrule
// ----------------------------------------------------------------
// Miss and writeback processing
// Maintain dirty delay countdown
rule rl_cacheline_cache_writeback_dirty_delay ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (rg_cacheline_cache_dirty_delay != 0));
rg_cacheline_cache_dirty_delay <= rg_cacheline_cache_dirty_delay - 1;
endrule
function Action fa_writeback;
action
dmaRqT req = DmaRq {addr: rg_cacheline_cache_addr,
byteEn: replicate (True), // Write all bytes
data: rg_cacheline_cache_data,
id: tagged MemLoader (?) // TODO: use wr_addr.awid?
};
llc.memReq.enq (req);
// $display ("%0d: %m.fa_writeback line at %0h", cur_cycle, rg_cacheline_cache_addr);
// $display (" data %0128h", rg_cacheline_cache_data);
endaction
endfunction
// Initiate writeback if dirty for full delay
rule rl_cacheline_cache_writeback_dirty_aged ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (rg_cacheline_cache_dirty_delay == 0));
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_dirty_aged.", cur_cycle);
$display (" Old line addr %0h", rg_cacheline_cache_addr);
end
fa_writeback;
rg_cacheline_cache_state <= CACHELINE_CACHE_WRITING_BACK;
endrule
// Initiate writeback if dirty and next request is store-miss
rule rl_cacheline_cache_writeback_st_miss ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (! fn_addr_is_in_line (axi4_slave_xactor.o_wr_addr.first.awaddr,
rg_cacheline_cache_addr)));
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_st_miss.", cur_cycle);
$display (" Old line addr %0h", rg_cacheline_cache_addr);
$display (" New addr %0h", axi4_slave_xactor.o_wr_addr.first.awaddr);
end
fa_writeback;
rg_cacheline_cache_state <= CACHELINE_CACHE_WRITING_BACK;
endrule
// Initiate writeback if dirty and next request is load-miss
rule rl_cacheline_cache_writeback_ld_miss ( (rg_cacheline_cache_state == CACHELINE_CACHE_DIRTY)
&& (! fn_addr_is_in_line (axi4_slave_xactor.o_rd_addr.first.araddr,
rg_cacheline_cache_addr)));
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_ld_miss.", cur_cycle);
$display (" Old line addr %0h", rg_cacheline_cache_addr);
$display (" New addr %0h", axi4_slave_xactor.o_wr_addr.first.awaddr);
end
fa_writeback;
rg_cacheline_cache_state <= CACHELINE_CACHE_WRITING_BACK;
endrule
// Finish writeback
rule rl_cacheline_cache_writeback_finish (llc.respSt.first matches tagged MemLoader .id
&&& (rg_cacheline_cache_state == CACHELINE_CACHE_WRITING_BACK));
let resp = llc.respSt.first;
llc.respSt.deq;
rg_cacheline_cache_state <= CACHELINE_CACHE_CLEAN;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_writeback_finish. Line addr %0h",
cur_cycle, rg_cacheline_cache_addr);
$display (" Line data %0h", rg_cacheline_cache_data);
end
endrule
function Action fa_initiate_reload (Addr addr);
action
let line_addr = fn_align_addr_to_line (addr);
dmaRqT req = DmaRq {addr: line_addr,
byteEn: replicate (False), // all False means 'read'
data: ?,
id: tagged MemLoader (?)}; // TODO: change uniformly to wr_addr.awid
llc.memReq.enq (req);
rg_cacheline_cache_addr <= line_addr;
if (verbosity >= 2) begin
$display (" fa_initiate_reload: line_addr %0h", line_addr);
end
endaction
endfunction
// Initiate reload when cacheline_cache is clean on store-miss
rule rl_cacheline_cache_reload_req_st ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
&& (! fn_addr_is_in_line (axi4_slave_xactor.o_wr_addr.first.awaddr,
rg_cacheline_cache_addr)));
let addr = axi4_slave_xactor.o_wr_addr.first.awaddr;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_reload_req_st for addr %0h", cur_cycle, addr);
end
fa_initiate_reload (addr);
rg_cacheline_cache_state <= CACHELINE_CACHE_RELOADING;
endrule
// Initiate reload when cacheline_cache is clean on load-miss
rule rl_cacheline_cache_reload_req_ld ( (rg_cacheline_cache_state == CACHELINE_CACHE_CLEAN)
&& (! fn_addr_is_in_line (axi4_slave_xactor.o_rd_addr.first.araddr,
rg_cacheline_cache_addr)));
let addr = axi4_slave_xactor.o_rd_addr.first.araddr;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_reload_req_ld for addr %0h", cur_cycle, addr);
end
fa_initiate_reload (addr);
rg_cacheline_cache_state <= CACHELINE_CACHE_RELOADING;
endrule
// Finish reload
rule rl_cacheline_cache_reload_finish (llc.respLd.first.id matches tagged MemLoader .id
&&& (rg_cacheline_cache_state == CACHELINE_CACHE_RELOADING));
let resp = llc.respLd.first;
llc.respLd.deq;
rg_cacheline_cache_state <= CACHELINE_CACHE_CLEAN;
rg_cacheline_cache_data <= resp.data;
if (verbosity >= 2) begin
$display ("%0d: %m.rl_cacheline_cache_reload_finish. Line addr %0h", cur_cycle, rg_cacheline_cache_addr);
$display (" Line data %0h", resp.data);
end
endrule
// ================================================================
// Transactions from the TLB
// Expecting only LOAD requests from TLB
// This section is unchanged from the original riscy-ooo module.
// helper functions for cross bar
function XBarDstInfo#(Bit#(0), Tuple2#(CoreId, TlbMemReq)) getTlbDst(CoreId core, TlbMemReq r);
return XBarDstInfo {idx: 0, data: tuple2(core, r)};
@@ -159,84 +386,13 @@ module mkLLCDmaConnect #(
};
endfunction
rule sendMemLoaderReqToLLC_wr; // write requests
let wr_addr <- pop_o (axi4_slave_xactor.o_wr_addr);
let wr_data <- pop_o (axi4_slave_xactor.o_wr_data);
// Prioritize external mem client over Tlb
(* descending_urgency = "rl_cacheline_cache_writeback_dirty_aged, sendTlbReqToLLC" *)
(* descending_urgency = "rl_cacheline_cache_writeback_st_miss, sendTlbReqToLLC" *)
(* descending_urgency = "rl_cacheline_cache_writeback_ld_miss, sendTlbReqToLLC" *)
(* descending_urgency = "rl_cacheline_cache_reload_req_st, sendTlbReqToLLC" *)
(* descending_urgency = "rl_cacheline_cache_reload_req_ld, sendTlbReqToLLC" *)
if (wr_addr.awlen != 0) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_wr: ERROR: awlen is not 0 (burst length is not 1)", cur_cycle);
$display (" ", fshow (wr_addr));
$display (" ", fshow (wr_data));
end
else if ( (wr_addr.awsize != axsize_1)
&& (wr_addr.awsize != axsize_2)
&& (wr_addr.awsize != axsize_4)
&& (wr_addr.awsize != axsize_8)) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_wr: ERROR: awsize is not code for 1,2,4,8", cur_cycle);
$display (" ", fshow (wr_addr));
$display (" ", fshow (wr_data));
end
else if (! wr_data.wlast) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_wr: ERROR: wlast is 1", cur_cycle);
$display (" ", fshow (wr_addr));
$display (" ", fshow (wr_data));
end
else begin
match {.line_addr,
.line_data,
.line_byteen } = fn_line_and_line_byteen_from_axi4 (wr_addr.awaddr,
wr_data.wstrb,
wr_data.wdata);
dmaRqT req = DmaRq {addr: line_addr,
byteEn: line_byteen,
data: line_data,
id: tagged MemLoader (?) // TODO: change uniformly to wr_addr.awid
};
llc.memReq.enq(req);
if (verbosity != 0) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_wr", cur_cycle);
$display (" ", fshow (wr_addr));
$display (" ", fshow (wr_data));
$display (" ", fshow (req));
end
end
endrule
rule sendMemLoaderReqToLLC_rd; // read requests
let rd_addr <- pop_o (axi4_slave_xactor.o_rd_addr);
if (rd_addr.arlen != 0) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_rd: ERROR: arlen is not 0 (burst length is not 1)", cur_cycle);
$display (" ", fshow (rd_addr));
end
else if ( (rd_addr.arsize != axsize_1)
&& (rd_addr.arsize != axsize_2)
&& (rd_addr.arsize != axsize_4)
&& (rd_addr.arsize != axsize_8)) begin
$display ("%0d: %m.sendMemLoaderReqToLLC_rd: ERROR: arsize is not code for 1,2,4,8", cur_cycle);
$display (" ", fshow (rd_addr));
end
else begin
Addr line_addr = { rd_addr.araddr [63:6], 6'b0 };
dmaRqT req = DmaRq {addr: line_addr,
byteEn: replicate (False),
data: ?,
id: MemLoader (?) // TODO: change uniformly to rd_addr.arid
};
llc.memReq.enq(req);
Bit #(3) dword_in_line = rd_addr.araddr [5:3];
f_dword_in_line.enq (dword_in_line);
if (verbosity != 0) begin
$display("[LLCDmaConnect sendMemLoaderReqToLLC_rd]");
$display (" ", fshow (rd_addr));
$display (" ", fshow (req));
end
end
endrule
(* descending_urgency = "sendMemLoaderReqToLLC_wr, sendTlbReqToLLC" *)
(* descending_urgency = "sendMemLoaderReqToLLC_rd, sendTlbReqToLLC" *)
rule sendTlbReqToLLC;
let {c, r} <- toGet(tlbQ).get;
let req = getTlbDmaReq(c, r);
@@ -246,26 +402,6 @@ module mkLLCDmaConnect #(
end
endrule
// send Ld resp from LLC
rule sendLdRespToMemLoader(llc.respLd.first.id matches tagged MemLoader .id);
let resp = llc.respLd.first;
llc.respLd.deq;
let dword_in_line = f_dword_in_line.first;
f_dword_in_line.deq;
AXI4_Rd_Data #(Wd_Id, Wd_Data, Wd_User)
rd_data = AXI4_Rd_Data {rid: 0, // TODO: change uniformly to Fabric_Id
rdata: fn_axi4_data_from_line (resp.data, dword_in_line),
rresp: axi4_resp_okay,
rlast: True,
ruser: ?};
axi4_slave_xactor.i_rd_data.enq (rd_data);
if (verbosity != 0) begin
$display ("[LLCDmaConnect sendLdRespToMemLoader]");
$display (" ", fshow (resp));
$display (" ", fshow (rd_data));
end
endrule
rule sendLdRespToTlb(llc.respLd.first.id matches tagged Tlb .id);
llc.respLd.deq;
let resp = llc.respLd.first;
@@ -279,23 +415,6 @@ module mkLLCDmaConnect #(
end
endrule
// send St resp from LLC
rule sendStRespToMemLoader(llc.respSt.first matches tagged MemLoader .id);
let resp = llc.respSt.first;
llc.respSt.deq;
AXI4_Wr_Resp #(Wd_Id, Wd_User)
wr_resp = AXI4_Wr_Resp {bid: 0, // TODO: change uniformly to Fabric_id
bresp: axi4_resp_okay,
buser: ?};
axi4_slave_xactor.i_wr_resp.enq (wr_resp);
if (verbosity != 0) begin
$display ("[LLCDmaConnect sendStRespToMemLoader]");
$display (" ", fshow (resp));
$display (" ", fshow (wr_resp));
end
endrule
rule sendStRespToTlb(llc.respSt.first matches tagged Tlb .id);
llc.respSt.deq;
if(verbose) begin
@@ -304,5 +423,8 @@ module mkLLCDmaConnect #(
doAssert(False, "No TLB st");
endrule
// ================================================================
// INTERFACE
return axi4_slave_xactor.axi_side;
endmodule