Ensure the MMIO platform issues aligned requests by changing the AXI4_Size field based on the byte enables

This commit is contained in:
Peter Rugg
2021-01-31 17:34:35 +00:00
parent 44e19afbf3
commit cedb4c279d
2 changed files with 17 additions and 4 deletions

View File

@@ -852,7 +852,10 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
// Send a load-request to the fabric adapter.
// Align addr to 8-byte boundary (FabricData-aligned)
Addr addr1 = { addr [63:3], 3'b_000 };
let req = MMIOCRq {addr:addr, func:tagged Ld, byteEn:?, data:?};
// Byte enables are used in the AXI adapter to determine the size of the req. Set 8 bits (it
// doesn't matter which) to preserve the behaviour of requesting 8 bytes).
// TODO: instead specify access size in interface
let req = MMIOCRq {addr:addr, func:tagged Ld, byteEn:unpack(16'b0000_0000_1111_1111), data:?};
mmio_fabric_adapter_core_side.request.put (req);
state <= WaitResp;
amoWaitWriteResp <= False;
@@ -927,7 +930,10 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
// Note: addr may not be FabricData-aligned; result will be Data that contains addr
// TODO: currently assumes superscalarity fits in fabric width
Addr addr1 = { addr [63:3], 3'b_000 };
let req = MMIOCRq {addr:addr1, func: tagged Ld, byteEn: ?, data: ? };
// Byte enables are used in the AXI adapter to determine the size of the req. Set 8 bits (it
// doesn't matter which) to preserve the behaviour of requesting 8 bytes).
// TODO: instead specify access size in interface
let req = MMIOCRq {addr:addr1, func: tagged Ld, byteEn: unpack(16'b0000_0000_1111_1111), data: ? };
mmio_fabric_adapter_core_side.request.put (req);
state <= WaitResp;

View File

@@ -103,6 +103,13 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
Reg #(Bit #(1)) rg_rd_rsp_beat <- mkReg (0);
Reg #(MemTaggedData) rspData <- mkReg (unpack(0));
// ================================================================
// Convert a request's byte enables to an AXI 4 size, to ensure that
// peripherals don't get confused about how large our access is.
function AXI4_Size byteEnToAxiSize (MemDataByteEn byteEn);
return toAXI4_Size(zeroExtend(pack(countIf(id, byteEn)))).Valid;
endfunction
rule rl_handle_read_req (f_reqs_from_core.first.func matches Ld
&&& (ctr_wr_rsps_pending.value == 0));
let req <- pop (f_reqs_from_core);
@@ -119,7 +126,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
// necessary; the AXI4 fabric should return a DECERR for illegal
// addrs; but not all AXI4 fabrics do the right thing.
if (soc_map.m_is_IO_addr (req.addr, False)) begin
AXI4_Size size = 8;
AXI4_Size size = byteEnToAxiSize(req.byteEn);
let mem_req_rd_addr = AXI4_ARFlit {arid: fabric_2x3_default_mid,
araddr: req.addr,
arlen: (burst) ? 1:0, // burst len = arlen+1
@@ -211,7 +218,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
// on first flit...
// ================
if (first) begin
AXI4_Size size = 8;
AXI4_Size size = byteEnToAxiSize(req.byteEn);
AXI4_AWFlit #(Wd_MId_2x3, Wd_Addr, Wd_AW_User)
mem_req_wr_addr = AXI4_AWFlit {awid: fabric_2x3_default_mid,
awaddr: req.addr,