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
277 lines
8.7 KiB
Plaintext
277 lines
8.7 KiB
Plaintext
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_Types :: *;
|
|
import Fabric_Defs :: *;
|
|
|
|
// ================================================================
|
|
|
|
interface LLC_AXI4_Adapter_IFC;
|
|
method Action reset;
|
|
|
|
// Fabric master interface for memory
|
|
interface AXI4_Master_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) mem_master;
|
|
endinterface
|
|
|
|
// ================================================================
|
|
|
|
module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
|
|
(LLC_AXI4_Adapter_IFC)
|
|
provisos(Bits#(idT, a__),
|
|
Bits#(childT, b__),
|
|
FShow#(ToMemMsg#(idT, childT)),
|
|
FShow#(MemRsMsg#(idT, childT)),
|
|
Add#(SizeOf#(Line), 0, 512)); // assert Line sz = 512
|
|
|
|
// Verbosity: 0: quiet; 1: LLC transactions; 2: loop detail
|
|
Integer verbosity = 0;
|
|
Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (fromInteger (verbosity));
|
|
|
|
// ================================================================
|
|
// Fabric request/response
|
|
|
|
AXI4_Master_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) master_xactor <- mkAXI4_Master_Xactor_2;
|
|
|
|
// For discarding write-responses
|
|
CreditCounter_IFC #(4) ctr_wr_rsps_pending <- mkCreditCounter; // Max 15 writes outstanding
|
|
|
|
// ================================================================
|
|
// Functions to interact with the fabric
|
|
|
|
// Send a read-request into the fabric
|
|
function Action fa_fabric_send_read_req (Fabric_Addr addr);
|
|
action
|
|
AXI4_Size size = axsize_8;
|
|
let mem_req_rd_addr = AXI4_Rd_Addr {arid: fabric_default_id,
|
|
araddr: addr,
|
|
arlen: 0, // burst len = arlen+1
|
|
arsize: size,
|
|
arburst: fabric_default_burst,
|
|
arlock: fabric_default_lock,
|
|
arcache: fabric_default_arcache,
|
|
arprot: fabric_default_prot,
|
|
arqos: fabric_default_qos,
|
|
arregion: fabric_default_region,
|
|
aruser: fabric_default_user};
|
|
|
|
master_xactor.i_rd_addr.enq (mem_req_rd_addr);
|
|
|
|
// Debugging
|
|
if (cfg_verbosity > 1) begin
|
|
$display (" ", fshow (mem_req_rd_addr));
|
|
end
|
|
endaction
|
|
endfunction
|
|
|
|
// Send a write-request into the fabric
|
|
function Action fa_fabric_send_write_req (Fabric_Addr addr, Fabric_Strb strb, Bit #(64) st_val);
|
|
action
|
|
AXI4_Size size = axsize_8;
|
|
let mem_req_wr_addr = AXI4_Wr_Addr {awid: fabric_default_id,
|
|
awaddr: addr,
|
|
awlen: 0, // burst len = awlen+1
|
|
awsize: size,
|
|
awburst: fabric_default_burst,
|
|
awlock: fabric_default_lock,
|
|
awcache: fabric_default_awcache,
|
|
awprot: fabric_default_prot,
|
|
awqos: fabric_default_qos,
|
|
awregion: fabric_default_region,
|
|
awuser: fabric_default_user};
|
|
|
|
let mem_req_wr_data = AXI4_Wr_Data {wdata: st_val,
|
|
wstrb: strb,
|
|
wlast: True,
|
|
wuser: fabric_default_user};
|
|
|
|
master_xactor.i_wr_addr.enq (mem_req_wr_addr);
|
|
master_xactor.i_wr_data.enq (mem_req_wr_data);
|
|
|
|
// Expect a fabric response
|
|
ctr_wr_rsps_pending.incr;
|
|
|
|
// Debugging
|
|
if (cfg_verbosity > 1) begin
|
|
$display (" To fabric: ", fshow (mem_req_wr_addr));
|
|
$display (" ", fshow (mem_req_wr_data));
|
|
end
|
|
endaction
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// 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_req_beat <- mkReg (0);
|
|
Reg #(Bit #(3)) rg_rd_rsp_beat <- mkReg (0);
|
|
|
|
FIFOF #(LdMemRq #(idT, childT)) f_pending_reads <- mkFIFOF;
|
|
Reg #(Bit #(512)) rg_cline <- mkRegU;
|
|
|
|
rule rl_handle_read_req (llc.toM.first matches tagged Ld .ld
|
|
&&& (ctr_wr_rsps_pending.value == 0));
|
|
if ((cfg_verbosity > 0) && (rg_rd_req_beat == 0)) begin
|
|
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_req: Ld request from LLC to memory: beat %0d",
|
|
cur_cycle, rg_rd_req_beat);
|
|
$display (" ", fshow (ld));
|
|
end
|
|
|
|
Addr line_addr = { ld.addr [63:6], 6'h0 }; // Addr of containing cache line
|
|
Addr offset = zeroExtend ( { rg_rd_req_beat, 3'b_000 } ); // Addr offset of 64b word for this beat
|
|
fa_fabric_send_read_req (line_addr | offset);
|
|
|
|
if (rg_rd_req_beat == 0)
|
|
f_pending_reads.enq (ld);
|
|
|
|
if (rg_rd_req_beat == 7)
|
|
llc.toM.deq;
|
|
|
|
rg_rd_req_beat <= rg_rd_req_beat + 1;
|
|
endrule
|
|
|
|
rule rl_handle_read_rsps;
|
|
let mem_rsp <- pop_o (master_xactor.o_rd_data);
|
|
|
|
if (cfg_verbosity > 1) begin
|
|
$display ("%0d: LLC_AXI4_Adapter.rl_handle_read_rsps: beat %0d ", cur_cycle, rg_rd_rsp_beat);
|
|
$display (" ", fshow (mem_rsp));
|
|
end
|
|
|
|
if (mem_rsp.rresp != axi4_resp_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 = { mem_rsp.rdata, rg_cline [511:64] };
|
|
|
|
if (rg_rd_rsp_beat == 7) begin
|
|
let ldreq <- pop (f_pending_reads);
|
|
MemRsMsg #(idT, childT) resp = MemRsMsg {data: unpack (new_cline),
|
|
child: ldreq.child,
|
|
id: ldreq.id};
|
|
|
|
llc.rsFromM.enq (resp);
|
|
|
|
if (cfg_verbosity > 1)
|
|
$display (" Response to LLC: ", fshow (resp));
|
|
end
|
|
|
|
rg_cline <= new_cline;
|
|
rg_rd_rsp_beat <= rg_rd_rsp_beat + 1;
|
|
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);
|
|
Reg #(Bit #(3)) rg_wr_rsp_beat <- mkReg (0);
|
|
|
|
FIFOF #(WbMemRs) f_pending_writes <- mkFIFOF;
|
|
|
|
rule rl_handle_write_req (llc.toM.first matches tagged Wb .wb);
|
|
if ((cfg_verbosity > 0) && (rg_wr_req_beat == 0)) begin
|
|
$display ("%d: LLC_AXI4_Adapter.rl_handle_write_req: Wb request from LLC to memory:", cur_cycle);
|
|
$display (" ", fshow (wb));
|
|
end
|
|
|
|
Addr line_addr = { wb.addr [63:6], 6'h0 }; // Addr of containing cache line
|
|
Line line_data = wb.data;
|
|
Vector #(8, Bit #(8)) line_bes = unpack (pack (wb.byteEn));
|
|
|
|
Addr offset = zeroExtend ( { rg_wr_req_beat, 3'b_000 } ); // Addr offset of 64b word for this beat
|
|
Bit #(64) data64 = line_data [rg_wr_req_beat];
|
|
Bit #(8) strb8 = line_bes [rg_wr_req_beat];
|
|
fa_fabric_send_write_req (line_addr | offset, strb8, data64);
|
|
|
|
if (rg_wr_req_beat == 0)
|
|
f_pending_writes.enq (wb);
|
|
|
|
if (rg_wr_req_beat == 7)
|
|
llc.toM.deq;
|
|
|
|
rg_wr_req_beat <= rg_wr_req_beat + 1;
|
|
endrule
|
|
|
|
// ----------------
|
|
// Discard write-responses from the fabric
|
|
|
|
rule rl_discard_write_rsp;
|
|
let wr_resp <- pop_o (master_xactor.o_wr_resp);
|
|
|
|
if (cfg_verbosity > 1) begin
|
|
$display ("%0d: LLC_AXI4_Adapter.rl_discard_write_rsp: beat %0d ", cur_cycle, rg_wr_rsp_beat);
|
|
$display (" ", fshow (wr_resp));
|
|
end
|
|
|
|
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;
|
|
|
|
if (wr_resp.bresp != axi4_resp_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
|
|
|
|
if (rg_wr_rsp_beat == 7) begin
|
|
let wrreq <- pop (f_pending_writes);
|
|
// LLC does not expect any response for writes
|
|
end
|
|
|
|
rg_wr_rsp_beat <= rg_wr_rsp_beat + 1;
|
|
endrule
|
|
|
|
// ================================================================
|
|
// INTERFACE
|
|
|
|
method Action reset;
|
|
ctr_wr_rsps_pending.clear;
|
|
endmethod
|
|
|
|
// Fabric interface for memory
|
|
interface mem_master = master_xactor.axi_side;
|
|
endmodule
|
|
|
|
// ================================================================
|
|
|
|
endpackage
|