Vastly simplified DMA Connect that does not buffer data at all.

This has not been tested yet, but it builds.
This commit is contained in:
Jonathan Woodruff
2023-02-28 13:28:29 +00:00
parent a38610869d
commit f255193841

View File

@@ -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,8 +126,6 @@ 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_Periph
, Wd_AW_User_Periph, Wd_W_User_Periph, Wd_B_User_Periph
@@ -139,68 +135,60 @@ module mkLLCDmaConnect #( DmaServer#(LLCDmaReqId) llc
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)));
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
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);
// 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)));
rule rl_client_ld_req;
let line_addr = fn_align_addr_to_line (slavePortShim.master.ar.peek.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 (slavePortShim.master.ar);
let dword = getDataAt( rg_cacheline_cache_data
let dword = getDataAt( resp.data
, getCLineDataSel(rd_addr.araddr));
// Send response to external client
@@ -213,145 +201,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 +238,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;