209 lines
8.4 KiB
Systemverilog
209 lines
8.4 KiB
Systemverilog
// Generated by CIRCT firtool-1.139.0
|
|
module LSU(
|
|
input clock,
|
|
reset,
|
|
io_reqValid,
|
|
input [63:0] io_req_addr,
|
|
io_req_data,
|
|
input io_req_isStore,
|
|
io_req_isSigned,
|
|
io_req_isAmo,
|
|
input [4:0] io_req_amoOp,
|
|
input [2:0] io_req_size,
|
|
input io_checkOnly,
|
|
io_sfenceVma,
|
|
input [1:0] io_currentPriv,
|
|
input [63:0] io_mstatus,
|
|
output io_reqReady,
|
|
input [63:0] io_satp,
|
|
output io_dmemReqValid,
|
|
output [63:0] io_dmemReq_addr,
|
|
io_dmemReq_data,
|
|
output io_dmemReq_isStore,
|
|
output [2:0] io_dmemReq_size,
|
|
input io_dmemRespValid,
|
|
input [63:0] io_dmemRespData,
|
|
output io_respValid,
|
|
output [63:0] io_respData,
|
|
output io_pageFault,
|
|
io_misaligned,
|
|
output [63:0] io_faultCause,
|
|
io_faultAddr
|
|
);
|
|
|
|
wire _dcache_io_reqReady;
|
|
wire _dcache_io_memReqValid;
|
|
wire [63:0] _dcache_io_memReq_addr;
|
|
wire [63:0] _dcache_io_memReq_data;
|
|
wire _dcache_io_memReq_isStore;
|
|
wire [2:0] _dcache_io_memReq_size;
|
|
wire _dcache_io_respValid;
|
|
wire _mmu_io_resp_pageFault;
|
|
wire _mmu_io_ptwMemReq_valid;
|
|
wire [63:0] _mmu_io_ptwMemReq_addr;
|
|
wire _mmu_io_refill_valid;
|
|
wire [26:0] _mmu_io_refill_vpn;
|
|
wire [43:0] _mmu_io_refill_ppn;
|
|
wire [1:0] _mmu_io_refill_level;
|
|
wire [7:0] _mmu_io_refill_flags;
|
|
wire _dtlb_io_resp_hit;
|
|
wire _dtlb_io_resp_miss;
|
|
wire [63:0] _dtlb_io_resp_paddr;
|
|
wire _dtlb_io_resp_pageFault;
|
|
wire [1:0] effectivePriv =
|
|
(&io_currentPriv) & io_mstatus[17] ? io_mstatus[12:11] : io_currentPriv;
|
|
reg pendingValid;
|
|
reg [63:0] pendingReq_addr;
|
|
reg [63:0] pendingReq_data;
|
|
reg pendingReq_isStore;
|
|
reg pendingReq_isSigned;
|
|
reg pendingReq_isAmo;
|
|
reg [4:0] pendingReq_amoOp;
|
|
reg [2:0] pendingReq_size;
|
|
reg pendingCheckOnly;
|
|
reg [1:0] pendingPriv;
|
|
reg [63:0] pendingMstatus;
|
|
reg [63:0] pendingSatp;
|
|
wire io_reqReady_0 = _dcache_io_reqReady & ~pendingValid;
|
|
wire acceptCurrent = io_reqValid & io_reqReady_0;
|
|
wire activeValid = pendingValid | acceptCurrent;
|
|
wire [2:0] activeReq_size = pendingValid ? pendingReq_size : io_req_size;
|
|
wire activeReq_isStore = pendingValid ? pendingReq_isStore : io_req_isStore;
|
|
wire [63:0] io_faultAddr_0 = pendingValid ? pendingReq_addr : io_req_addr;
|
|
wire activeCheckOnly = pendingValid ? pendingCheckOnly : io_checkOnly;
|
|
wire [1:0] activePriv = pendingValid ? pendingPriv : effectivePriv;
|
|
wire [1:0] activeMstatus = pendingValid ? pendingMstatus[19:18] : io_mstatus[19:18];
|
|
wire [63:0] activeSatp = pendingValid ? pendingSatp : io_satp;
|
|
wire translate = (|(activeSatp[63:60])) & activePriv != 2'h3;
|
|
wire dtlb_io_req_valid = activeValid & translate;
|
|
reg ptwOutstanding;
|
|
wire ptwReqFire = _mmu_io_ptwMemReq_valid & ~ptwOutstanding;
|
|
wire ptwRespFire = io_dmemRespValid & (ptwOutstanding | ptwReqFire);
|
|
wire translationReady = ~translate | _dtlb_io_resp_hit;
|
|
wire translationFault = _dtlb_io_resp_pageFault | _mmu_io_resp_pageFault;
|
|
wire misaligned =
|
|
activeValid
|
|
& (|((activeReq_size == 3'h3
|
|
? 3'h0
|
|
: activeReq_size == 3'h2
|
|
? 3'h4
|
|
: activeReq_size == 3'h1 ? 3'h2 : {2'h0, activeReq_size == 3'h0}) - 3'h1
|
|
& io_faultAddr_0[2:0]));
|
|
wire newFault = activeValid & (translationFault | misaligned);
|
|
wire checkOnlyDispatch =
|
|
activeValid & activeCheckOnly & translationReady & ~translationFault & ~misaligned;
|
|
wire dcacheDispatch =
|
|
activeValid & ~activeCheckOnly & translationReady & ~translationFault & ~misaligned
|
|
& _dcache_io_reqReady;
|
|
wire storeComplete = dcacheDispatch & activeReq_isStore | checkOnlyDispatch;
|
|
always @(posedge clock) begin
|
|
automatic logic latchPending;
|
|
automatic logic clearPending;
|
|
latchPending = acceptCurrent & ~dcacheDispatch & ~newFault;
|
|
clearPending = pendingValid & (dcacheDispatch | checkOnlyDispatch | newFault);
|
|
if (reset) begin
|
|
pendingValid <= 1'h0;
|
|
ptwOutstanding <= 1'h0;
|
|
end
|
|
else begin
|
|
pendingValid <= ~clearPending & (latchPending | pendingValid);
|
|
ptwOutstanding <= ~ptwRespFire & (ptwReqFire | ptwOutstanding);
|
|
end
|
|
if (clearPending | ~latchPending) begin
|
|
end
|
|
else begin
|
|
pendingReq_addr <= io_req_addr;
|
|
pendingReq_data <= io_req_data;
|
|
pendingReq_isStore <= io_req_isStore;
|
|
pendingReq_isSigned <= io_req_isSigned;
|
|
pendingReq_isAmo <= io_req_isAmo;
|
|
pendingReq_amoOp <= io_req_amoOp;
|
|
pendingReq_size <= io_req_size;
|
|
pendingCheckOnly <= io_checkOnly;
|
|
pendingPriv <= effectivePriv;
|
|
pendingMstatus <= io_mstatus;
|
|
pendingSatp <= io_satp;
|
|
end
|
|
end // always @(posedge)
|
|
DTLB dtlb (
|
|
.clock (clock),
|
|
.reset (reset),
|
|
.io_req_valid (dtlb_io_req_valid),
|
|
.io_req_vaddr (io_faultAddr_0),
|
|
.io_req_isStore (activeReq_isStore),
|
|
.io_req_priv (activePriv),
|
|
.io_req_sum (activeMstatus[0]),
|
|
.io_req_mxr (activeMstatus[1]),
|
|
.io_resp_hit (_dtlb_io_resp_hit),
|
|
.io_resp_miss (_dtlb_io_resp_miss),
|
|
.io_resp_paddr (_dtlb_io_resp_paddr),
|
|
.io_resp_pageFault (_dtlb_io_resp_pageFault),
|
|
.io_refill_valid (_mmu_io_refill_valid),
|
|
.io_refill_vpn (_mmu_io_refill_vpn),
|
|
.io_refill_ppn (_mmu_io_refill_ppn),
|
|
.io_refill_level (_mmu_io_refill_level),
|
|
.io_refill_flags (_mmu_io_refill_flags),
|
|
.io_flush (io_sfenceVma)
|
|
);
|
|
MMU mmu (
|
|
.clock (clock),
|
|
.reset (reset),
|
|
.io_satp (activeSatp),
|
|
.io_req_valid (dtlb_io_req_valid & _dtlb_io_resp_miss),
|
|
.io_req_vaddr (io_faultAddr_0),
|
|
.io_req_isStore (activeReq_isStore),
|
|
.io_req_isFetch (1'h0),
|
|
.io_req_priv (activePriv),
|
|
.io_req_sum (activeMstatus[0]),
|
|
.io_req_mxr (activeMstatus[1]),
|
|
.io_resp_pageFault (_mmu_io_resp_pageFault),
|
|
.io_ptwMemReq_valid (_mmu_io_ptwMemReq_valid),
|
|
.io_ptwMemReq_addr (_mmu_io_ptwMemReq_addr),
|
|
.io_ptwMemResp_valid (ptwRespFire),
|
|
.io_ptwMemResp_data (io_dmemRespData),
|
|
.io_refill_valid (_mmu_io_refill_valid),
|
|
.io_refill_vpn (_mmu_io_refill_vpn),
|
|
.io_refill_ppn (_mmu_io_refill_ppn),
|
|
.io_refill_level (_mmu_io_refill_level),
|
|
.io_refill_flags (_mmu_io_refill_flags)
|
|
);
|
|
DCache dcache (
|
|
.clock (clock),
|
|
.reset (reset),
|
|
.io_reqValid (dcacheDispatch),
|
|
.io_req_addr (translate ? _dtlb_io_resp_paddr : io_faultAddr_0),
|
|
.io_req_data (pendingValid ? pendingReq_data : io_req_data),
|
|
.io_req_isStore (activeReq_isStore),
|
|
.io_req_isSigned (pendingValid ? pendingReq_isSigned : io_req_isSigned),
|
|
.io_req_isAmo (pendingValid ? pendingReq_isAmo : io_req_isAmo),
|
|
.io_req_amoOp (pendingValid ? pendingReq_amoOp : io_req_amoOp),
|
|
.io_req_size (activeReq_size),
|
|
.io_reqReady (_dcache_io_reqReady),
|
|
.io_memReqValid (_dcache_io_memReqValid),
|
|
.io_memReq_addr (_dcache_io_memReq_addr),
|
|
.io_memReq_data (_dcache_io_memReq_data),
|
|
.io_memReq_isStore (_dcache_io_memReq_isStore),
|
|
.io_memReq_size (_dcache_io_memReq_size),
|
|
.io_memRespValid (io_dmemRespValid & ~ptwOutstanding & ~ptwReqFire),
|
|
.io_memRespData (io_dmemRespData),
|
|
.io_respValid (_dcache_io_respValid),
|
|
.io_respData (io_respData)
|
|
);
|
|
assign io_reqReady = io_reqReady_0;
|
|
assign io_dmemReqValid = ptwReqFire | _dcache_io_memReqValid;
|
|
assign io_dmemReq_addr = ptwReqFire ? _mmu_io_ptwMemReq_addr : _dcache_io_memReq_addr;
|
|
assign io_dmemReq_data = ptwReqFire ? 64'h0 : _dcache_io_memReq_data;
|
|
assign io_dmemReq_isStore = ~ptwReqFire & _dcache_io_memReq_isStore;
|
|
assign io_dmemReq_size = ptwReqFire ? 3'h3 : _dcache_io_memReq_size;
|
|
assign io_respValid = _dcache_io_respValid | newFault | storeComplete;
|
|
assign io_pageFault = translationFault;
|
|
assign io_misaligned = misaligned;
|
|
assign io_faultCause =
|
|
{56'h0,
|
|
misaligned
|
|
? {6'h1, activeReq_isStore, 1'h0}
|
|
: {4'h0, translationFault, 1'h1, activeReq_isStore, 1'h1}};
|
|
assign io_faultAddr = io_faultAddr_0;
|
|
endmodule
|
|
|