Merge branch 'CHERI' into ks980-prefetch
This commit is contained in:
@@ -88,11 +88,11 @@ BSC_COMPILATION_FLAGS += \
|
||||
-D MULT_SYNTH \
|
||||
-D Near_Mem_Caches \
|
||||
-D FABRIC64 \
|
||||
-D CheriBusBytes=8 \
|
||||
-D CheriBusBytes=64 \
|
||||
-D CheriMasterIDWidth=1 \
|
||||
-D CheriTransactionIDWidth=6 \
|
||||
-D CAP128 -D BLUESIM \
|
||||
-D MEM64 \
|
||||
-D MEM512 \
|
||||
-D RISCV \
|
||||
-D PERFORMANCE_MONITORING \
|
||||
-D RAS_HIT_TRACING \
|
||||
|
||||
Submodule libs/BlueStuff updated: 4dec54bc42...f4e4e9d59f
Submodule libs/TagController updated: c01eded449...720ee78f58
@@ -48,6 +48,10 @@ import SourceSink :: *;
|
||||
import Fabric_Defs :: *;
|
||||
import SoC_Map :: *;
|
||||
|
||||
import VnD :: *;
|
||||
import Bag :: *;
|
||||
import ProcTypes :: *;
|
||||
|
||||
// ================================================================
|
||||
|
||||
interface LLC_AXI4_Adapter_IFC;
|
||||
@@ -61,16 +65,27 @@ endinterface
|
||||
|
||||
// ================================================================
|
||||
|
||||
typedef struct {
|
||||
Bool tag_req; // meaningful to upgrade to E if toState is S
|
||||
idT id; // slot id in child cache
|
||||
childT child; // from which child
|
||||
} LLC_AXI_ID#(type idT, type childT) deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef 16 OutstandingWrites;
|
||||
typedef 16 WriteAddressHashW;
|
||||
|
||||
module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
(LLC_AXI4_Adapter_IFC)
|
||||
provisos(Bits#(idT, a__),
|
||||
Bits#(childT, b__),
|
||||
provisos(Bits#(idT, idSz),
|
||||
Bits#(childT, childSz),
|
||||
FShow#(ToMemMsg#(idT, childT)),
|
||||
FShow#(MemRsMsg#(idT, childT)),
|
||||
Add#(SizeOf#(Line), 0, TAdd#(512, 4))); // assert Line sz = 512 + 4 tags
|
||||
Add#(SizeOf#(Line), 0, TAdd#(512, 4)), // assert Line sz = 512 + 4 tags
|
||||
Add#(a__, SizeOf#(LLC_AXI_ID#(idT, childT)), Wd_MId) // LLC_AXI_ID must fit into the external ID.
|
||||
);
|
||||
|
||||
// Verbosity: 0: quiet; 1: LLC transactions; 2: loop detail
|
||||
Integer verbosity = 0;
|
||||
Integer verbosity = 2;
|
||||
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (fromInteger (verbosity));
|
||||
|
||||
// ================================================================
|
||||
@@ -79,25 +94,28 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
let masterPortShim <- mkAXI4ShimFF;
|
||||
|
||||
// For discarding write-responses
|
||||
CreditCounter_IFC #(4) ctr_wr_rsps_pending <- mkCreditCounter; // Max 15 writes outstanding
|
||||
CreditCounter_IFC #(TLog#(OutstandingWrites)) ctr_wr_rsps_pending <- mkCreditCounter; // 16 outstanding writes.
|
||||
|
||||
Bag#(OutstandingWrites, Bit#(Wd_MId), Bit#(WriteAddressHashW)) outstandingWrites <- mkSmallBag;
|
||||
|
||||
// ================================================================
|
||||
// Functions to interact with the fabric
|
||||
|
||||
// Send a read-request into the fabric
|
||||
function Action fa_fabric_send_read_req (Fabric_Addr addr, Bool tag_req);
|
||||
function Action fa_fabric_send_read_req (Fabric_Addr addr, LLC_AXI_ID#(idT, childT) id);
|
||||
action
|
||||
let mem_req_rd_addr = AXI4_ARFlit {arid: fabric_default_mid,
|
||||
Bit#(Wd_MId) arid = zeroExtend(pack(id));
|
||||
let mem_req_rd_addr = AXI4_ARFlit {arid: arid,
|
||||
araddr: addr,
|
||||
arlen: tag_req ? 0 : 7, // burst len = arlen+1
|
||||
arsize: tag_req ? 1 : 8,
|
||||
arlen: 0, // burst len = arlen+1
|
||||
arsize: id.tag_req ? 1 : 64,
|
||||
arburst: INCR,
|
||||
arlock: fabric_default_lock,
|
||||
arcache: fabric_default_arcache,
|
||||
arprot: fabric_default_prot,
|
||||
arqos: fabric_default_qos,
|
||||
arregion: fabric_default_region,
|
||||
aruser: pack(tag_req)};
|
||||
aruser: pack(id.tag_req)};
|
||||
|
||||
masterPortShim.slave.ar.put(mem_req_rd_addr);
|
||||
|
||||
@@ -110,16 +128,8 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
|
||||
// ================================================================
|
||||
// Handle read requests and responses
|
||||
// Don't do reads while writes are outstanding.
|
||||
|
||||
// Each 512b cache line takes 8 beats, each handling 64 bits
|
||||
Reg #(Bit #(3)) rg_rd_rsp_beat <- mkReg (0);
|
||||
|
||||
FIFOF #(LdMemRq #(idT, childT)) f_pending_reads <- mkFIFOF;
|
||||
Reg #(CLine) rg_cline <- mkRegU;
|
||||
|
||||
rule rl_handle_read_req (llc.toM.first matches tagged Ld .ld
|
||||
&&& (ctr_wr_rsps_pending.value == 0));
|
||||
rule rl_handle_read_req (llc.toM.first matches tagged Ld .ld &&& !outstandingWrites.dataMatch(hash(ld.addr[63:6])));
|
||||
if ((cfg_verbosity > 0)) begin
|
||||
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_req: Ld request from LLC to memory",
|
||||
cur_cycle);
|
||||
@@ -127,105 +137,72 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
end
|
||||
|
||||
Addr line_addr = {ld.addr [63:6], 6'h0 }; // Addr of containing cache line
|
||||
fa_fabric_send_read_req (line_addr, ld.tag_req);
|
||||
f_pending_reads.enq (ld);
|
||||
fa_fabric_send_read_req (line_addr, LLC_AXI_ID{tag_req: ld.tag_req, id: ld.id, child: ld.child});
|
||||
llc.toM.deq;
|
||||
endrule
|
||||
|
||||
rule rl_handle_read_rsps;
|
||||
let mem_rsp <- get(masterPortShim.slave.r);
|
||||
|
||||
if (cfg_verbosity > 1) begin
|
||||
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_rsps: beat %0d ", cur_cycle, rg_rd_rsp_beat);
|
||||
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_rsps: ", cur_cycle);
|
||||
$display (" ", fshow (mem_rsp));
|
||||
end
|
||||
|
||||
if (mem_rsp.rresp != OKAY) begin
|
||||
// TODO: need to raise a non-maskable interrupt (NMI) here
|
||||
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_rsp: fabric response error; exit", cur_cycle);
|
||||
$display (" ", fshow (mem_rsp));
|
||||
$finish (1);
|
||||
end
|
||||
|
||||
// Shift next 64 bits from fabric into the cache line being assembled
|
||||
let new_cline_tag = { mem_rsp.ruser, pack(rg_cline.tag) [3:1] };
|
||||
let new_cline_data = { mem_rsp.rdata, pack(rg_cline.data) [511:64] };
|
||||
let new_cline = CLine { tag: rg_rd_rsp_beat[0] == 0 ? unpack(new_cline_tag) : rg_cline.tag
|
||||
, data: unpack(new_cline_data) };
|
||||
|
||||
if (mem_rsp.rlast) begin
|
||||
let ldreq <- pop (f_pending_reads);
|
||||
MemRsMsg #(idT, childT) resp = MemRsMsg {data: new_cline,
|
||||
child: ldreq.child,
|
||||
id: ldreq.id};
|
||||
|
||||
if (ldreq.tag_req) begin
|
||||
resp.data = CLine { tag: unpack(truncate(mem_rsp.rdata)), data: ?};
|
||||
end
|
||||
|
||||
llc.rsFromM.enq (resp);
|
||||
|
||||
if (cfg_verbosity > 1)
|
||||
$display (" Response to LLC: ", fshow (resp));
|
||||
|
||||
rg_rd_rsp_beat <= 0;
|
||||
rg_cline <= unpack(0);
|
||||
end else begin
|
||||
rg_rd_rsp_beat <= rg_rd_rsp_beat + 1;
|
||||
rg_cline <= new_cline;
|
||||
let new_cline = CLine { tag: unpack(mem_rsp.ruser)
|
||||
, data: unpack(mem_rsp.rdata) };
|
||||
LLC_AXI_ID#(idT, childT) id = unpack(truncate(mem_rsp.rid));
|
||||
MemRsMsg #(idT, childT) resp = MemRsMsg {data: new_cline,
|
||||
child: id.child,
|
||||
id: id.id};
|
||||
if (id.tag_req) begin
|
||||
resp.data = CLine { tag: unpack(truncate(mem_rsp.rdata)), data: ?};
|
||||
end
|
||||
llc.rsFromM.enq (resp);
|
||||
if (cfg_verbosity > 1)
|
||||
$display (" Response to LLC: ", fshow (resp));
|
||||
endrule
|
||||
|
||||
// ================================================================
|
||||
// Handle write requests and responses
|
||||
|
||||
// Each 512b cache line takes 8 beats, each handling 64 bits
|
||||
Reg #(Bit #(3)) rg_wr_req_beat <- mkReg (0);
|
||||
|
||||
rule rl_handle_write_req (llc.toM.first matches tagged Wb .wb);
|
||||
if ((cfg_verbosity > 0) && (rg_wr_req_beat == 0)) begin
|
||||
Reg#(Bit#(Wd_MId)) wid_reg <- mkRegU;
|
||||
rule rl_handle_write_req (llc.toM.first matches tagged Wb .wb &&& !outstandingWrites.isMember(wid_reg).v);
|
||||
if (cfg_verbosity > 0) begin
|
||||
$display ("%d: LLC_AXI4_Adapter.rl_handle_write_req: Wb request from LLC to memory:", cur_cycle);
|
||||
$display (" ", fshow (wb));
|
||||
end
|
||||
|
||||
// on first flit...
|
||||
// ================
|
||||
if (rg_wr_req_beat == 0) begin
|
||||
// send AXI4 AW flit
|
||||
masterPortShim.slave.aw.put (AXI4_AWFlit {
|
||||
awid: fabric_default_mid,
|
||||
awaddr: { wb.addr [63:6], 6'h0 },
|
||||
awlen: 7, // burst len = awlen+1
|
||||
awsize: 8,
|
||||
awburst: INCR,
|
||||
awlock: fabric_default_lock,
|
||||
awcache: fabric_default_awcache,
|
||||
awprot: fabric_default_prot,
|
||||
awqos: fabric_default_qos,
|
||||
awregion: fabric_default_region,
|
||||
awuser: 0});
|
||||
// Expect a fabric response
|
||||
ctr_wr_rsps_pending.incr;
|
||||
end
|
||||
// send AXI4 AW flit
|
||||
masterPortShim.slave.aw.put (AXI4_AWFlit {
|
||||
awid: wid_reg,
|
||||
awaddr: { wb.addr [63:6], 6'h0 },
|
||||
awlen: 0, // burst len = awlen+1
|
||||
awsize: 64,
|
||||
awburst: INCR,
|
||||
awlock: fabric_default_lock,
|
||||
awcache: fabric_default_awcache,
|
||||
awprot: fabric_default_prot,
|
||||
awqos: fabric_default_qos,
|
||||
awregion: fabric_default_region,
|
||||
awuser: 0});
|
||||
// Expect a fabric response
|
||||
ctr_wr_rsps_pending.incr;
|
||||
outstandingWrites.insert(wid_reg, hash(wb.addr[63:6]));
|
||||
wid_reg <= wid_reg + 1; // Best effort to use unique IDs to allow reordering in the fabric.
|
||||
llc.toM.deq;
|
||||
|
||||
// on last flit...
|
||||
// ===============
|
||||
if (rg_wr_req_beat == 7) begin
|
||||
llc.toM.deq;
|
||||
rg_wr_req_beat <= 0;
|
||||
end else // increment flit counter
|
||||
rg_wr_req_beat <= rg_wr_req_beat + 1;
|
||||
|
||||
// on each flit ...
|
||||
// ================
|
||||
Vector #(8, Bit #(8)) line_strb = unpack(pack(wb.byteEn));
|
||||
Vector #(4, MemTaggedData) line_data = clineToMemTaggedDataVector(wb.data);
|
||||
// send AXI4 W flit
|
||||
masterPortShim.slave.w.put(AXI4_WFlit {
|
||||
wdata: line_data[rg_wr_req_beat[2:1]].data[rg_wr_req_beat[0]],
|
||||
wstrb: line_strb[rg_wr_req_beat],
|
||||
wlast: rg_wr_req_beat == 7,
|
||||
wuser: pack(line_data[rg_wr_req_beat[2:1]].tag)});
|
||||
wdata: pack(wb.data.data),
|
||||
wstrb: pack(wb.byteEn),
|
||||
wlast: True,
|
||||
wuser: pack(wb.data.tag)});
|
||||
endrule
|
||||
|
||||
// ----------------
|
||||
@@ -242,6 +219,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
end
|
||||
|
||||
ctr_wr_rsps_pending.decr;
|
||||
outstandingWrites.remove(wr_resp.bid);
|
||||
|
||||
if (wr_resp.bresp != OKAY) begin
|
||||
// TODO: need to raise a non-maskable interrupt (NMI) here
|
||||
@@ -255,7 +233,9 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
||||
// INTERFACE
|
||||
|
||||
method Action reset;
|
||||
ctr_wr_rsps_pending.clear;
|
||||
error("Reset called for LLC AXI4 adapter");
|
||||
// XXX resetting this module would cause wedges unless the surrounding
|
||||
// fabric was also fully reset
|
||||
endmethod
|
||||
|
||||
// Fabric interface for memory
|
||||
|
||||
@@ -66,7 +66,7 @@ interface MMIO_AXI4_Adapter_IFC;
|
||||
interface Server #(MMIOCRq, MMIODataPRs) core_side;
|
||||
|
||||
// Fabric master interface for IO
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User) mmio_master;
|
||||
endinterface
|
||||
@@ -251,7 +251,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
|
||||
|
||||
// on each flit...
|
||||
// ===============
|
||||
AXI4_WFlit #(Wd_Data, Wd_W_User)
|
||||
AXI4_WFlit #(Wd_Data_Periph, Wd_W_User)
|
||||
wflit = AXI4_WFlit {wdata: req.data.data[whichHalf],
|
||||
wstrb: line_strb[whichHalf],
|
||||
wlast: last,
|
||||
|
||||
@@ -79,7 +79,7 @@ interface Proc_IFC;
|
||||
Wd_AR_User, Wd_R_User) master0;
|
||||
|
||||
// Fabric master interface for IO (from MMIOPlatform)
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User) master1;
|
||||
|
||||
@@ -106,9 +106,10 @@ interface Proc_IFC;
|
||||
// ----------------
|
||||
// Coherent port into LLC (used by Debug Module, DMA engines, ... to read/write memory)
|
||||
|
||||
interface AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User) debug_module_mem_server;
|
||||
interface AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph)
|
||||
debug_module_mem_server;
|
||||
|
||||
`ifdef RVFI_DII
|
||||
interface Toooba_RVFI_DII_Server rvfi_dii_server;
|
||||
|
||||
@@ -66,8 +66,7 @@ import Clocks :: *;
|
||||
import Cur_Cycle :: *;
|
||||
import GetPut_Aux :: *;
|
||||
import Routable :: *;
|
||||
import AXI4 :: *;
|
||||
import AXI4Lite :: *;
|
||||
import BlueAXI4 :: *;
|
||||
import SourceSink :: *;
|
||||
import TagControllerAXI :: *;
|
||||
import CacheCore :: *;
|
||||
@@ -124,11 +123,11 @@ typedef WindCoreMid #( // AXI lite subordinate control port parameters
|
||||
// AXI manager 0 port parameters
|
||||
, TAdd #(Wd_MId, 1), Wd_Addr, Wd_Data, 0, 0, 0, 0, 0
|
||||
// AXI manager 1 port parameters
|
||||
, TAdd #(Wd_MId, 1), Wd_Addr, Wd_Data, 0, 0, 0, 0, 0
|
||||
, TAdd #(Wd_MId, 1), Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0
|
||||
// AXI subordinate 0 port parameters
|
||||
, Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User
|
||||
, Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph
|
||||
// Number of interrupt lines
|
||||
, t_n_irq) CoreW_IFC #(numeric type t_n_irq);
|
||||
|
||||
@@ -226,8 +225,8 @@ module mkCoreW_reset #(Reset porReset)
|
||||
Proc_IFC proc <- mkProc (reset_by all_harts_reset);
|
||||
|
||||
// handle uncached interface
|
||||
let proc_uncached =
|
||||
prepend_AXI4_Master_id (0, zero_AXI4_Master_user (proc.master1));
|
||||
AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0)
|
||||
proc_uncached = prepend_AXI4_Master_id (0, zero_AXI4_Master_user (proc.master1));
|
||||
// Bridge for uncached expernal bus transactions.
|
||||
let uncached_mem_shim <- mkAXI4ShimFF(reset_by all_harts_reset);
|
||||
|
||||
@@ -236,6 +235,11 @@ module mkCoreW_reset #(Reset porReset)
|
||||
TagControllerAXI #(Wd_MId, Wd_Addr, Wd_Data)
|
||||
tagController <- mkTagControllerAXI (reset_by all_harts_reset); // TODO double check if reseting like this is good enough
|
||||
mkConnection (proc.master0, tagController.slave, reset_by all_harts_reset);
|
||||
AXI4_Shim#(TAdd #(Wd_MId, 1), Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
tag_controller_deburster <- mkBurstToNoBurst;
|
||||
mkConnection (tagController.master, tag_controller_deburster.slave, reset_by all_harts_reset);
|
||||
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
rule report_tagController_events;
|
||||
EventsCacheCore cache_core_evts = tagController.events;
|
||||
@@ -310,7 +314,7 @@ module mkCoreW_reset #(Reset porReset)
|
||||
rule rl_dm_harts_reset (rg_harts_reset_delay == 0);
|
||||
let x <- debug_module.harts_reset_client[core].request.get;
|
||||
dm_harts_reset_controller[core].assertReset;
|
||||
rg_harts_reset_delay <= fromInteger (hart_reset_duration + 200); // NOTE: heuristic
|
||||
rg_harts_reset_delay <= fromInteger (hart_reset_duration + 200); // NOTE: heuristic
|
||||
rg_harts_reset_running <= x;
|
||||
$display ("%0d: %m.rl_dm_harts_reset: asserting harts reset for %0d cycles",
|
||||
cur_cycle, hart_reset_duration);
|
||||
@@ -363,7 +367,10 @@ module mkCoreW_reset #(Reset porReset)
|
||||
// Create a tap for DM's memory-writes to the bus, and merge-in the trace data.
|
||||
DM_Mem_Tap_IFC dm_mem_tap <- mkDM_Mem_Tap;
|
||||
mkConnection (debug_module.master, dm_mem_tap.slave);
|
||||
let dm_master_local = dm_mem_tap.master;
|
||||
AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph )
|
||||
dm_master_local = dm_mem_tap.master;
|
||||
|
||||
rule rl_merge_dm_mem_trace_data;
|
||||
let tmp <- dm_mem_tap.trace_data_out.get;
|
||||
@@ -429,7 +436,10 @@ module mkCoreW_reset #(Reset porReset)
|
||||
mkConnection (debug_module.harts_csr_mem_client, proc.harts_csr_mem_server, reset_by porReset);
|
||||
|
||||
// DM's bus master is directly the bus master
|
||||
let dm_master_local = debug_module.master;
|
||||
AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph )
|
||||
dm_master_local = debug_module.master;
|
||||
|
||||
// END SECTION: DM, no TV
|
||||
// ================================================================
|
||||
@@ -440,7 +450,10 @@ module mkCoreW_reset #(Reset porReset)
|
||||
// BEGIN SECTION: no DM
|
||||
|
||||
// No DM, so 'DM bus master' is AXI4 dummy
|
||||
let dm_master_local = culDeSac;
|
||||
AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph )
|
||||
dm_master_local = culDeSac;
|
||||
|
||||
`ifdef INCLUDE_TANDEM_VERIF
|
||||
// TV, no DM: stub out the dm input to TV
|
||||
@@ -460,9 +473,10 @@ module mkCoreW_reset #(Reset porReset)
|
||||
|
||||
// Masters on the local bus
|
||||
Vector #( CoreW_Bus_Num_Masters
|
||||
, AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User))
|
||||
, AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph
|
||||
, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph ))
|
||||
master_vector = newVector;
|
||||
master_vector[cpu_uncached_master_num] = proc_uncached;
|
||||
master_vector[debug_module_sba_master_num] = dm_master_local;
|
||||
@@ -471,12 +485,12 @@ module mkCoreW_reset #(Reset porReset)
|
||||
// Slaves on the local bus
|
||||
// default slave is forwarded out directly to the Core interface
|
||||
Vector #( CoreW_Bus_Num_Slaves
|
||||
, AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User))
|
||||
, AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph ))
|
||||
slave_vector = newVector;
|
||||
slave_vector[default_slave_num] = uncached_mem_shim.slave;
|
||||
slave_vector[llc_slave_num] = proc.debug_module_mem_server;
|
||||
slave_vector[llc_slave_num] = zero_AXI4_Slave_user (proc.debug_module_mem_server);
|
||||
slave_vector[plic_slave_num] = zero_AXI4_Slave_user (plic.axi4_slave);
|
||||
|
||||
function Vector #(CoreW_Bus_Num_Slaves, Bool) route (Bit #(Wd_Addr) addr);
|
||||
@@ -618,7 +632,7 @@ module mkCoreW_reset #(Reset porReset)
|
||||
// memory interfaces
|
||||
// -----------------
|
||||
// Cached master to Fabric master interface
|
||||
interface manager_0 = tagController.master;
|
||||
interface manager_0 = tag_controller_deburster.master;
|
||||
// Uncached master to Fabric master interface
|
||||
interface manager_1 = prepend_AXI4_Master_id
|
||||
(0, zero_AXI4_Master_user (uncached_mem_shim.master));
|
||||
|
||||
@@ -67,7 +67,7 @@ Integer bytes_per_fabric_addr = valueOf (Bytes_per_Fabric_Addr);
|
||||
// |
|
||||
// Periph
|
||||
|
||||
typedef 64 Wd_Data;
|
||||
typedef 512 Wd_Data;
|
||||
|
||||
// ----------------
|
||||
// Width of fabric 'user' datapaths. Carry capability tags on data lines.
|
||||
@@ -118,6 +118,11 @@ Bit#(Wd_W_User) fabric_default_wuser = 0;
|
||||
Bit#(Wd_B_User) fabric_default_buser = 0;
|
||||
Bit#(Wd_AR_User) fabric_default_aruser = 0;
|
||||
Bit#(Wd_R_User) fabric_default_ruser = 0;
|
||||
Bit#(Wd_AW_User_Periph) fabric_default_awuser_periph = 0;
|
||||
Bit#(Wd_W_User_Periph) fabric_default_wuser_periph = 0;
|
||||
Bit#(Wd_B_User_Periph) fabric_default_buser_periph = 0;
|
||||
Bit#(Wd_AR_User_Periph) fabric_default_aruser_periph = 0;
|
||||
Bit#(Wd_R_User_Periph) fabric_default_ruser_periph = 0;
|
||||
|
||||
// ================================================================
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ interface DM_System_Bus_IFC;
|
||||
// ----------------
|
||||
// Facing System
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User) master;
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph) master;
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
@@ -292,7 +292,7 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
|
||||
arprot: fabric_default_prot,
|
||||
arqos: fabric_default_qos,
|
||||
arregion: fabric_default_region,
|
||||
aruser: fabric_default_aruser};
|
||||
aruser: fabric_default_aruser_periph};
|
||||
axiShim.slave.ar.put(rda);
|
||||
|
||||
// Save read-address for byte-lane extraction from later response
|
||||
@@ -333,13 +333,13 @@ module mkDM_System_Bus (DM_System_Bus_IFC);
|
||||
awprot: fabric_default_prot,
|
||||
awqos: fabric_default_qos,
|
||||
awregion: fabric_default_region,
|
||||
awuser: fabric_default_awuser};
|
||||
awuser: fabric_default_awuser_periph};
|
||||
axiShim.slave.aw.put(wra);
|
||||
|
||||
let wrd = AXI4_WFlit {wdata: fabric_data,
|
||||
wstrb: fabric_strb,
|
||||
wlast: True,
|
||||
wuser: fabric_default_wuser};
|
||||
wuser: fabric_default_wuser_periph};
|
||||
axiShim.slave.w.put(wrd);
|
||||
|
||||
if (verbosity != 0) begin
|
||||
|
||||
@@ -138,8 +138,8 @@ interface Debug_Module_IFC;
|
||||
|
||||
// Read/Write RISC-V memory
|
||||
interface AXI4_Master #( Wd_CoreW_Bus_MId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User) master;
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph) master;
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
|
||||
@@ -98,7 +98,7 @@ interface PLIC_IFC #(numeric type t_n_external_sources,
|
||||
method Action set_addr_map (Bit #(64) addr_base, Bit #(64) addr_lim);
|
||||
|
||||
// Memory-mapped access
|
||||
interface AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data
|
||||
interface AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data_Periph
|
||||
, 0, 0, 0, 0, 0) axi4_slave;
|
||||
|
||||
// sources
|
||||
@@ -381,13 +381,12 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
|
||||
$display (" ", fshow (rda));
|
||||
end
|
||||
|
||||
if ((valueOf (Wd_Data) == 64) && ((addr_offset & 'h7) == 'h4))
|
||||
if ((valueOf (Wd_Data_Periph) == 64) && ((addr_offset & 'h7) == 'h4))
|
||||
rdata = { rdata [31:0], 32'h0 };
|
||||
|
||||
// Send read-response to bus
|
||||
Fabric_Data x = truncate (rdata);
|
||||
let rdr = AXI4_RFlit {rid: rda.arid,
|
||||
rdata: x,
|
||||
rdata: rdata,
|
||||
rresp: rresp,
|
||||
rlast: True,
|
||||
ruser: rda.aruser}; // XXX This requires that Wd_AR_User == Wd_R_User
|
||||
@@ -416,7 +415,7 @@ module mkPLIC (PLIC_IFC #(t_n_external_sources, t_n_targets, t_max_priority))
|
||||
end
|
||||
|
||||
let addr_offset = wra.awaddr - rg_addr_base;
|
||||
let wdata32 = (((valueOf (Wd_Data) == 64) && ((addr_offset & 'h7) == 'h4))
|
||||
let wdata32 = (((valueOf (Wd_Data_Periph) == 64) && ((addr_offset & 'h7) == 'h4))
|
||||
? wrd.wdata [63:32]
|
||||
: wrd.wdata [31:0]);
|
||||
let bresp = OKAY;
|
||||
|
||||
@@ -519,6 +519,8 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
|
||||
dInst.csr = tagged Invalid;
|
||||
dInst.execFunc = tagged Br AT;
|
||||
|
||||
if (funct3 != 0) illegalInst = True;
|
||||
|
||||
dInst.capChecks.check_enable = True;
|
||||
dInst.capChecks.check_low_src = Src1Addr;
|
||||
dInst.capChecks.check_high_src = Src1AddrPlus2;
|
||||
@@ -542,14 +544,18 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
|
||||
|
||||
opcBranch: begin
|
||||
dInst.iType = Br;
|
||||
dInst.execFunc = tagged Br (case(funct3)
|
||||
fnBEQ: Eq;
|
||||
fnBNE: Neq;
|
||||
fnBLT: Lt;
|
||||
fnBLTU: Ltu;
|
||||
fnBGE: Ge;
|
||||
fnBGEU: Geu;
|
||||
endcase);
|
||||
ExecFunc execFunc = ?;
|
||||
{illegalInst, execFunc} = case(funct3)
|
||||
fnBEQ: tuple2(False, Br(Eq));
|
||||
fnBNE: tuple2(False, Br(Neq));
|
||||
fnBLT: tuple2(False, Br(Lt));
|
||||
fnBLTU: tuple2(False, Br(Ltu));
|
||||
fnBGE: tuple2(False, Br(Ge));
|
||||
fnBGEU: tuple2(False, Br(Geu));
|
||||
default: tuple2(True, Br(?));
|
||||
endcase;
|
||||
dInst.execFunc = execFunc;
|
||||
|
||||
regs.dst = Invalid;
|
||||
regs.src1 = Valid(tagged Gpr rs1);
|
||||
regs.src2 = Valid(tagged Gpr rs2);
|
||||
|
||||
@@ -79,9 +79,7 @@ import ProcTypes::*;
|
||||
import CacheUtils::*;
|
||||
import CCTypes::*;
|
||||
import L2Tlb::*;
|
||||
import MemLoader::*;
|
||||
import CrossBar::*;
|
||||
import MemLoader::*;
|
||||
|
||||
// ----------------
|
||||
// From Toooba
|
||||
@@ -101,7 +99,7 @@ typedef struct {
|
||||
} TlbDmaReqId deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef union tagged {
|
||||
MemLoaderMemReqId MemLoader;
|
||||
void Client;
|
||||
TlbDmaReqId Tlb;
|
||||
} LLCDmaReqId deriving(Bits, Eq, FShow);
|
||||
|
||||
@@ -128,79 +126,82 @@ endfunction
|
||||
// ================================================================
|
||||
|
||||
module mkLLCDmaConnect #( DmaServer#(LLCDmaReqId) llc
|
||||
// REPLACED BY AXI4_Slave_interface
|
||||
//, MemLoaderMemClient memLoader
|
||||
, Vector#(CoreNum, TlbMemClient) tlb )
|
||||
(AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data
|
||||
, Wd_AW_User, Wd_W_User, Wd_B_User
|
||||
, Wd_AR_User, Wd_R_User))
|
||||
(AXI4_Slave #( Wd_CoreW_Bus_SId, Wd_Addr, Wd_Data_Periph
|
||||
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
|
||||
, Wd_AR_User_Periph, Wd_R_User_Periph ))
|
||||
provisos (Alias #(dmaRqT, DmaRq #(LLCDmaReqId)));
|
||||
Bool verbose = False;
|
||||
|
||||
Integer verbosity = 0;
|
||||
|
||||
// When debugger reads a word, request a line from LLC, and remember dword-in-line here
|
||||
FIFOF #(Bit #(3)) f_dword_in_line <- mkFIFOF;
|
||||
|
||||
// Connector to AXI4 fabric
|
||||
let slavePortShim <- mkAXI4ShimFF;
|
||||
|
||||
// ================================================================
|
||||
// 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 (slavePortShim.master.aw.peek.awaddr,
|
||||
rg_cacheline_cache_addr)));
|
||||
let internal_aw_ff <- mkFIFO;
|
||||
|
||||
rule rl_client_st;
|
||||
let wr_addr <- get (slavePortShim.master.aw);
|
||||
let wr_data <- get (slavePortShim.master.w);
|
||||
|
||||
// Modify relevant bytes of relevant dword
|
||||
let newLine = setDataAtBE( rg_cacheline_cache_data
|
||||
, getCLineDataSel(wr_addr.awaddr)
|
||||
, wr_data.wdata, unpack(pack(wr_data.wstrb)));
|
||||
// Save it
|
||||
rg_cacheline_cache_data <= newLine;
|
||||
rg_cacheline_cache_state <= CACHELINE_CACHE_DIRTY;
|
||||
rg_cacheline_cache_dirty_delay <= '1; // start write-back delay countdown
|
||||
internal_aw_ff.enq(wr_addr);
|
||||
|
||||
if (verbosity >= 2) begin
|
||||
$display ("%0d: %m.rl_client_st for addr %0h", cur_cycle, wr_addr.awaddr);
|
||||
end
|
||||
|
||||
let line_addr = fn_align_addr_to_line (wr_addr.awaddr);
|
||||
Vector#(TDiv#(CLineDataNumBytes,8), Bit#(TDiv#(Wd_Data_Periph,8))) line_be = replicate(0);
|
||||
line_be[getCLineDataSel(wr_addr.awaddr)] = wr_data.wstrb;
|
||||
dmaRqT req = DmaRq {addr: line_addr,
|
||||
byteEn: unpack(pack(line_be)),
|
||||
data: setDataAt(unpack(0), getCLineDataSel(wr_addr.awaddr), wr_data.wdata),
|
||||
id: tagged Client}; // TODO: change uniformly to wr_addr.awid
|
||||
llc.memReq.enq (req);
|
||||
endrule
|
||||
|
||||
rule rl_client_st_rsp(llc.respSt.first matches tagged Client);
|
||||
llc.respSt.deq;
|
||||
let wr_addr <- get (internal_aw_ff);
|
||||
|
||||
// Send response to external client
|
||||
slavePortShim.master.b.put(AXI4_BFlit{
|
||||
bid: wr_addr.awid, // TODO: change uniformly to Fabric_id
|
||||
bid: wr_addr.awid,
|
||||
bresp: OKAY,
|
||||
buser: ?
|
||||
});
|
||||
|
||||
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 (slavePortShim.master.ar.peek.araddr,
|
||||
rg_cacheline_cache_addr)));
|
||||
let internal_ar_ff <- mkFIFO;
|
||||
|
||||
rule rl_client_ld_req;
|
||||
let rd_addr <- get (slavePortShim.master.ar);
|
||||
let dword = getDataAt( rg_cacheline_cache_data
|
||||
internal_ar_ff.enq(rd_addr);
|
||||
let line_addr = fn_align_addr_to_line (rd_addr.araddr);
|
||||
dmaRqT req = DmaRq {addr: line_addr,
|
||||
byteEn: replicate(replicate(False)), // all False means 'read'
|
||||
data: ?,
|
||||
id: tagged Client}; // TODO: change uniformly to wr_addr.awid
|
||||
llc.memReq.enq (req);
|
||||
|
||||
if (verbosity >= 2) begin
|
||||
$display ("%0d: %m.rl_client_ld_req: line_addr %0h", cur_cycle, line_addr);
|
||||
end
|
||||
endrule
|
||||
|
||||
// Finish reload
|
||||
rule rl_client_ld_rsp (llc.respLd.first.id matches tagged Client);
|
||||
let resp = llc.respLd.first;
|
||||
llc.respLd.deq;
|
||||
|
||||
let rd_addr <- get (internal_ar_ff);
|
||||
let dword = getDataAt( resp.data
|
||||
, getCLineDataSel(rd_addr.araddr));
|
||||
|
||||
// Send response to external client
|
||||
@@ -213,145 +214,11 @@ module mkLLCDmaConnect #( DmaServer#(LLCDmaReqId) llc
|
||||
});
|
||||
|
||||
if (verbosity >= 2) begin
|
||||
$display ("%0d: %m.rl_handle_MemLoader_ld_req: addr %0h", cur_cycle, rd_addr.araddr);
|
||||
$display ("%0d: %m.rl_client_ld_rsp: 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(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 (slavePortShim.master.aw.peek.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", slavePortShim.master.aw.peek.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 (slavePortShim.master.ar.peek.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", slavePortShim.master.aw.peek.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(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 (slavePortShim.master.aw.peek.awaddr,
|
||||
rg_cacheline_cache_addr)));
|
||||
let addr = slavePortShim.master.aw.peek.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 (slavePortShim.master.ar.peek.araddr,
|
||||
rg_cacheline_cache_addr)));
|
||||
let addr = slavePortShim.master.ar.peek.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
|
||||
@@ -384,11 +251,8 @@ module mkLLCDmaConnect #( DmaServer#(LLCDmaReqId) llc
|
||||
endfunction
|
||||
|
||||
// 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" *)
|
||||
(* descending_urgency = "rl_client_st, sendTlbReqToLLC" *)
|
||||
(* descending_urgency = "rl_client_ld_req, sendTlbReqToLLC" *)
|
||||
|
||||
rule sendTlbReqToLLC;
|
||||
let {c, r} <- toGet(tlbQ).get;
|
||||
|
||||
@@ -27,7 +27,7 @@ BSC_COMPILATION_FLAGS += \
|
||||
-D ISA_PRIV_M -D ISA_PRIV_S -D ISA_PRIV_U \
|
||||
-D SV39 \
|
||||
-D ISA_I -D ISA_M -D ISA_A -D ISA_F -D ISA_D -D ISA_FD_DIV -D ISA_C \
|
||||
-D CheriBusBytes=8 \
|
||||
-D CheriBusBytes=64 \
|
||||
-D CheriMasterIDWidth=1 \
|
||||
-D CheriTransactionIDWidth=6 \
|
||||
-D PERFORMANCE_MONITORING \
|
||||
@@ -36,9 +36,8 @@ BSC_COMPILATION_FLAGS += \
|
||||
-D Near_Mem_Caches \
|
||||
-D FABRIC64 \
|
||||
-D CAP128 \
|
||||
-D MEM64 \
|
||||
-D MEM512 \
|
||||
-D RISCV \
|
||||
-D NO_SPEC_TRAINING -D NO_SPEC_REDIRECT -D NO_SPEC_STRAIGHT_PATH -D SPEC_RSB_FIXUP -D NO_SPEC_RSB_PUSH -D NO_SPEC_STL \
|
||||
-D TSO_MM \
|
||||
-D INCLUDE_GDB_CONTROL \
|
||||
-D BRVF_TRACE \
|
||||
|
||||
@@ -32,6 +32,7 @@ import Vector :: *;
|
||||
|
||||
import GetPut_Aux :: *;
|
||||
import Routable :: *;
|
||||
import BlueBasics :: *;
|
||||
import BlueAXI4 :: *;
|
||||
import SourceSink :: *;
|
||||
import WindCoreInterface :: *;
|
||||
@@ -71,10 +72,10 @@ interface P3_Core_IFC;
|
||||
// Core CPU interfaces
|
||||
|
||||
// CPU IMem to Fabric master interface
|
||||
interface AXI4_Master_Sig#(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
|
||||
interface AXI4_Master_Sig#(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data_Periph,
|
||||
0, 0, 0, 0, 0) master0;
|
||||
|
||||
interface AXI4_Master_Sig#(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
|
||||
interface AXI4_Master_Sig#(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data_Periph,
|
||||
0, 0, 0, 0, 0) master1;
|
||||
|
||||
// External interrupt sources
|
||||
@@ -165,6 +166,14 @@ module mkP3_Core (P3_Core_IFC);
|
||||
, CoreW_IFC #(N_External_Interrupt_Sources)) both
|
||||
<- mkCoreW_reset (dm_power_on_reset, reset_by ndm_reset);
|
||||
match {.otherRst, .corew} = both;
|
||||
// AXI4 Narrower Master in front of cached memory master
|
||||
NumProxy #(4) proxyInDepth = error ("don't look inside a proxy");
|
||||
NumProxy #(4) proxyOutDepth = error ("don't look inside a proxy");
|
||||
Tuple2 #( AXI4_Slave #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
, AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0) )
|
||||
wideS_narrowM <- mkAXI4DataWidthShim_WideToNarrow (proxyInDepth, proxyOutDepth);
|
||||
match {.wideS, .narrowM} = wideS_narrowM;
|
||||
mkConnection(corew.manager_0, wideS);
|
||||
|
||||
`ifdef INCLUDE_GDB_CONTROL
|
||||
|
||||
@@ -261,7 +270,7 @@ module mkP3_Core (P3_Core_IFC);
|
||||
|
||||
// ================================================================
|
||||
// INTERFACE
|
||||
let master0_sig <- toAXI4_Master_Sig (corew.manager_0);
|
||||
let master0_sig <- toAXI4_Master_Sig (narrowM);
|
||||
let master1_sig <- toAXI4_Master_Sig (corew.manager_1);
|
||||
// ----------------------------------------------------------------
|
||||
// Core CPU interfaces
|
||||
|
||||
@@ -126,7 +126,7 @@ typedef TLog #(Word64s_per_Raw_Mem_Word) Bits_per_Word64_in_Raw_Me
|
||||
// Type of index of a Word64 in a Raw_Mem_Word seen as a vector of Word64s
|
||||
typedef Bit #(Bits_per_Word64_in_Raw_Mem_Word) Word64_in_Raw_Mem_Word;
|
||||
|
||||
typedef TDiv #(Bytes_per_Raw_Mem_Word, Bytes_per_Fabric_Data) Fabric_Data_per_Raw_Mem_Word;
|
||||
typedef TDiv #(Bytes_per_Raw_Mem_Word, TDiv #(Wd_Data_Periph, 8)) Fabric_Data_per_Raw_Mem_Word;
|
||||
|
||||
// Index of bit that selects a fabric data word in an address
|
||||
`ifdef FABRIC32
|
||||
@@ -207,7 +207,7 @@ interface Mem_Controller_IFC;
|
||||
method Action set_addr_map (Fabric_Addr addr_base, Fabric_Addr addr_lim);
|
||||
|
||||
// Main Fabric Reqs/Rsps
|
||||
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0)
|
||||
slave;
|
||||
|
||||
// To raw memory (outside the SoC)
|
||||
@@ -245,8 +245,8 @@ typedef struct {Req_Op req_op;
|
||||
Bit #(Wd_User) user;
|
||||
|
||||
// Write data info
|
||||
Bit #(TDiv #(Wd_Data, 8)) wstrb;
|
||||
Fabric_Data data;
|
||||
Bit #(TDiv #(Wd_Data_Periph, 8)) wstrb;
|
||||
Bit #(Wd_Data_Periph) data;
|
||||
} Req
|
||||
deriving (Bits, FShow);
|
||||
|
||||
@@ -487,7 +487,7 @@ module mkMem_Controller (Mem_Controller_IFC);
|
||||
// We need to select the fabric data word from the raw mem word that contains the target address.
|
||||
|
||||
// View the raw mem word as a vector of fabric data words (Wd_Data width words)
|
||||
Vector #(Fabric_Data_per_Raw_Mem_Word, Bit #(Wd_Data)) raw_mem_word_V_fabric_data = unpack (rg_cached_raw_mem_word);
|
||||
Vector #(Fabric_Data_per_Raw_Mem_Word, Bit #(Wd_Data_Periph)) raw_mem_word_V_fabric_data = unpack (rg_cached_raw_mem_word);
|
||||
|
||||
// Get the index into this vector of the fabric word containing the target address.
|
||||
// For this index, use a generous size (here Bit #(16)), and let zeroExtend pad it automaticallly.
|
||||
@@ -496,7 +496,7 @@ module mkMem_Controller (Mem_Controller_IFC);
|
||||
n = (n >> lo_fabric_data);
|
||||
|
||||
// Select the fabric data word of interest
|
||||
Bit #(Wd_Data) rdata = raw_mem_word_V_fabric_data [n];
|
||||
Bit #(Wd_Data_Periph) rdata = raw_mem_word_V_fabric_data [n];
|
||||
|
||||
let rdr = AXI4_RFlit {rid: f_reqs.first.id,
|
||||
rdata: rdata,
|
||||
@@ -529,7 +529,7 @@ module mkMem_Controller (Mem_Controller_IFC);
|
||||
// Lane-adjust the new word64
|
||||
Bit #(64) word64_new = zeroExtend (f_reqs.first.data);
|
||||
Bit #(8) strobe = zeroExtend (f_reqs.first.wstrb);
|
||||
if ((valueOf (Wd_Data) == 32) && (f_reqs.first.addr [2] == 1'b1)) begin
|
||||
if ((valueOf (Wd_Data_Periph) == 32) && (f_reqs.first.addr [2] == 1'b1)) begin
|
||||
// Upper 32b only
|
||||
word64_new = { word64_new [31:0], 0 };
|
||||
strobe = { strobe [3:0], 0 };
|
||||
@@ -609,7 +609,7 @@ module mkMem_Controller (Mem_Controller_IFC);
|
||||
rule rl_invalid_rd_address ( (rg_state == STATE_READY)
|
||||
&& (! fn_addr_is_ok (rg_addr_base, f_reqs.first.addr, rg_addr_lim, f_reqs.first.size))
|
||||
&& (f_reqs.first.req_op == REQ_OP_RD));
|
||||
Fabric_Data rdata = zeroExtend (f_reqs.first.addr);
|
||||
Bit#(Wd_Data_Periph) rdata = zeroExtend (f_reqs.first.addr);
|
||||
let rdr = AXI4_RFlit {rid: f_reqs.first.id,
|
||||
rdata: rdata, // for debugging only
|
||||
rresp: SLVERR,
|
||||
|
||||
@@ -46,8 +46,8 @@ import Vector :: *;
|
||||
import Cur_Cycle :: *;
|
||||
import GetPut_Aux :: *;
|
||||
import Routable :: *;
|
||||
import AXI4 :: *;
|
||||
import AXI4Lite :: *;
|
||||
import BlueBasics :: *;
|
||||
import BlueAXI4 :: *;
|
||||
|
||||
// ================================================================
|
||||
// Project imports
|
||||
@@ -153,15 +153,24 @@ module mkSoC_Top #(Reset dm_power_on_reset)
|
||||
// SoC Boot ROM
|
||||
Boot_ROM_IFC boot_rom <- mkBoot_ROM;
|
||||
// AXI4 Deburster in front of Boot_ROM
|
||||
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0)
|
||||
boot_rom_axi4_deburster <- mkBurstToNoBurst;
|
||||
|
||||
// SoC Memory
|
||||
Mem_Controller_IFC mem0_controller <- mkMem_Controller;
|
||||
// AXI4 Deburster in front of SoC Memory
|
||||
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
AXI4_Shim#(Wd_SId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0)
|
||||
mem0_controller_axi4_deburster <- mkBurstToNoBurst;
|
||||
|
||||
// AXI4 Narrower Master in front of cached memory master
|
||||
NumProxy #(4) proxyInDepth = error ("don't look inside a proxy");
|
||||
NumProxy #(4) proxyOutDepth = error ("don't look inside a proxy");
|
||||
Tuple2 #( AXI4_Slave #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data, 0, 0, 0, 0, 0)
|
||||
, AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0) )
|
||||
wideS_narrowM <- mkAXI4DataWidthShim_WideToNarrow (proxyInDepth, proxyOutDepth);
|
||||
match {.wideS, .narrowM} = wideS_narrowM;
|
||||
mkConnection(corew.manager_0, wideS);
|
||||
|
||||
// SoC IPs
|
||||
UART_IFC uart0 <- mkUART;
|
||||
|
||||
@@ -174,12 +183,12 @@ module mkSoC_Top #(Reset dm_power_on_reset)
|
||||
// SoC fabric master connections
|
||||
// Note: see 'SoC_Map' for 'master_num' definitions
|
||||
|
||||
Vector#(Num_Masters, AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data,
|
||||
Vector#(Num_Masters, AXI4_Master #(TAdd#(Wd_MId,1), Wd_Addr, Wd_Data_Periph,
|
||||
0, 0, 0, 0, 0))
|
||||
master_vector = newVector;
|
||||
|
||||
// CPU IMem master to fabric
|
||||
master_vector[imem_master_num] = corew.manager_0;
|
||||
master_vector[imem_master_num] = narrowM;
|
||||
|
||||
// CPU DMem master to fabric
|
||||
master_vector[dmem_master_num] = corew.manager_1;
|
||||
@@ -188,7 +197,7 @@ module mkSoC_Top #(Reset dm_power_on_reset)
|
||||
// SoC fabric slave connections
|
||||
// Note: see 'SoC_Map' for 'slave_num' definitions
|
||||
|
||||
Vector#(Num_Slaves, AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data,
|
||||
Vector#(Num_Slaves, AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data_Periph,
|
||||
0, 0, 0, 0, 0))
|
||||
slave_vector = newVector;
|
||||
Vector#(Num_Slaves, Range#(Wd_Addr)) route_vector = newVector;
|
||||
|
||||
@@ -130,7 +130,7 @@ interface UART_IFC;
|
||||
method Action set_addr_map (Fabric_Addr addr_base, Fabric_Addr addr_lim);
|
||||
|
||||
// Main Fabric Reqs/Rsps
|
||||
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data, 0, 0, 0, 0, 0) slave;
|
||||
interface AXI4_Slave #(Wd_SId, Wd_Addr, Wd_Data_Periph, 0, 0, 0, 0, 0) slave;
|
||||
|
||||
// To external console
|
||||
interface Get #(Bit #(8)) get_to_console;
|
||||
@@ -367,8 +367,8 @@ module mkUART (UART_IFC);
|
||||
end
|
||||
|
||||
// Align data byte for AXI4 data bus based on fabric-width
|
||||
Fabric_Data rdata = zeroExtend (rdata_byte);
|
||||
if ((valueOf (Wd_Data) == 64) && (byte_addr [2:0] == 3'b100))
|
||||
Bit#(Wd_Data_Periph) rdata = zeroExtend (rdata_byte);
|
||||
if ((valueOf (Wd_Data_Periph) == 64) && (byte_addr [2:0] == 3'b100))
|
||||
rdata = rdata << 32;
|
||||
|
||||
// Send read-response to bus
|
||||
|
||||
Reference in New Issue
Block a user