248 lines
8.8 KiB
Plaintext
248 lines
8.8 KiB
Plaintext
//-
|
|
// RVFI_DII + CHERI modifications:
|
|
// Copyright (c) 2020 Alexandre Joannou
|
|
// Copyright (c) 2020 Jonathan Woodruff
|
|
// All rights reserved.
|
|
//
|
|
// This software was developed by SRI International and the University of
|
|
// Cambridge Computer Laboratory (Department of Computer Science and
|
|
// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
|
|
// DARPA SSITH research programme.
|
|
//
|
|
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
|
|
//-
|
|
|
|
package LLC_AXI4_Adapter;
|
|
|
|
// ================================================================
|
|
// BSV lib imports
|
|
|
|
import ConfigReg :: *;
|
|
import Assert :: *;
|
|
import FIFOF :: *;
|
|
import Vector :: *;
|
|
|
|
// ----------------
|
|
// BSV additional libs
|
|
|
|
import GetPut_Aux :: *;
|
|
import Cur_Cycle :: *;
|
|
import Semi_FIFOF :: *;
|
|
import CreditCounter :: *;
|
|
|
|
// ================================================================
|
|
// Project imports
|
|
|
|
// ----------------
|
|
// From MIT RISCY-OOO
|
|
|
|
import Types :: *;
|
|
import CacheUtils :: *;
|
|
import CCTypes :: *;
|
|
|
|
// ----------------
|
|
// From Bluespec Pipes
|
|
|
|
import AXI4 :: *;
|
|
import SourceSink :: *;
|
|
import Fabric_Defs :: *;
|
|
import SoC_Map :: *;
|
|
|
|
import VnD :: *;
|
|
import Bag :: *;
|
|
import ProcTypes :: *;
|
|
|
|
// ================================================================
|
|
|
|
interface LLC_AXI4_Adapter_IFC;
|
|
method Action reset;
|
|
|
|
// Fabric master interface for memory
|
|
interface AXI4_Master #(Wd_MId, Wd_Addr, Wd_Data,
|
|
Wd_AW_User, Wd_W_User, Wd_B_User,
|
|
Wd_AR_User, Wd_R_User) mem_master;
|
|
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, 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#(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;
|
|
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (fromInteger (verbosity));
|
|
|
|
// ================================================================
|
|
// Fabric request/response
|
|
|
|
let masterPortShim <- mkAXI4ShimFF;
|
|
|
|
// For discarding write-responses
|
|
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, LLC_AXI_ID#(idT, childT) id);
|
|
action
|
|
Bit#(Wd_MId) arid = zeroExtend(pack(id));
|
|
let mem_req_rd_addr = AXI4_ARFlit {arid: arid,
|
|
araddr: addr,
|
|
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(id.tag_req)};
|
|
|
|
masterPortShim.slave.ar.put(mem_req_rd_addr);
|
|
|
|
// Debugging
|
|
if (cfg_verbosity > 1) begin
|
|
$display (" ", fshow (mem_req_rd_addr));
|
|
end
|
|
endaction
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// Handle read requests and responses
|
|
|
|
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);
|
|
$display (" ", fshow (ld));
|
|
end
|
|
|
|
Addr line_addr = {ld.addr [63:6], 6'h0 }; // Addr of containing cache line
|
|
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: ", 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
|
|
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
|
|
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
|
|
|
|
// 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;
|
|
|
|
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: pack(wb.data.data),
|
|
wstrb: pack(wb.byteEn),
|
|
wlast: True,
|
|
wuser: pack(wb.data.tag)});
|
|
endrule
|
|
|
|
// ----------------
|
|
// Discard write-responses from the fabric
|
|
|
|
rule rl_discard_write_rsp;
|
|
let wr_resp <- get(masterPortShim.slave.b);
|
|
|
|
if (ctr_wr_rsps_pending.value == 0) begin
|
|
$display ("%0d: ERROR: LLC_AXI4_Adapter.rl_discard_write_rsp: unexpected Wr response (ctr_wr_rsps_pending.value == 0)",
|
|
cur_cycle);
|
|
$display (" ", fshow (wr_resp));
|
|
$finish (1); // Assertion failure
|
|
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
|
|
$display ("%0d: LLC_AXI4_Adapter.rl_discard_write_rsp: fabric response error: exit", cur_cycle);
|
|
$display (" ", fshow (wr_resp));
|
|
$finish (1);
|
|
end
|
|
endrule
|
|
|
|
// ================================================================
|
|
// INTERFACE
|
|
|
|
method Action reset;
|
|
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
|
|
interface mem_master = masterPortShim.master;
|
|
endmodule
|
|
|
|
// ================================================================
|
|
|
|
endpackage
|