feat: implement privileged mode support
This commit is contained in:
@@ -10,6 +10,10 @@ module LSU(
|
||||
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,
|
||||
@@ -21,7 +25,10 @@ module LSU(
|
||||
input [63:0] io_dmemRespData,
|
||||
output io_respValid,
|
||||
output [63:0] io_respData,
|
||||
output io_pageFault
|
||||
output io_pageFault,
|
||||
io_misaligned,
|
||||
output [63:0] io_faultCause,
|
||||
io_faultAddr
|
||||
);
|
||||
|
||||
wire _dcache_io_reqReady;
|
||||
@@ -37,26 +44,96 @@ module LSU(
|
||||
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
|
||||
if (reset)
|
||||
automatic logic latchPending;
|
||||
automatic logic clearPending;
|
||||
latchPending = acceptCurrent & ~dcacheDispatch & ~newFault;
|
||||
clearPending = pendingValid & (dcacheDispatch | checkOnlyDispatch | newFault);
|
||||
if (reset) begin
|
||||
pendingValid <= 1'h0;
|
||||
ptwOutstanding <= 1'h0;
|
||||
else
|
||||
ptwOutstanding <=
|
||||
_mmu_io_ptwMemReq_valid | ~(io_dmemRespValid & ptwOutstanding) & ptwOutstanding;
|
||||
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 (io_reqValid & (|(io_satp[63:60]))),
|
||||
.io_req_vaddr (io_req_addr),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.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),
|
||||
@@ -64,56 +141,68 @@ module LSU(
|
||||
.io_refill_valid (_mmu_io_refill_valid),
|
||||
.io_refill_vpn (_mmu_io_refill_vpn),
|
||||
.io_refill_ppn (_mmu_io_refill_ppn),
|
||||
.io_refill_flags (_mmu_io_refill_flags)
|
||||
.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 (io_satp),
|
||||
.io_req_valid (io_reqValid & (|(io_satp[63:60])) & _dtlb_io_resp_miss),
|
||||
.io_req_vaddr (io_req_addr),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.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 (io_dmemRespValid & ptwOutstanding),
|
||||
.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
|
||||
(io_reqValid & (~(|(io_satp[63:60])) | _dtlb_io_resp_hit) & ~translationFault),
|
||||
.io_req_addr ((|(io_satp[63:60])) ? _dtlb_io_resp_paddr : io_req_addr),
|
||||
.io_req_data (io_req_data),
|
||||
.io_req_isStore (io_req_isStore),
|
||||
.io_req_isSigned (io_req_isSigned),
|
||||
.io_req_isAmo (io_req_isAmo),
|
||||
.io_req_amoOp (io_req_amoOp),
|
||||
.io_req_size (io_req_size),
|
||||
.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),
|
||||
.io_memRespValid (io_dmemRespValid & ~ptwOutstanding & ~ptwReqFire),
|
||||
.io_memRespData (io_dmemRespData),
|
||||
.io_respValid (_dcache_io_respValid),
|
||||
.io_respData (io_respData)
|
||||
);
|
||||
assign io_reqReady = _dcache_io_reqReady & ~ptwOutstanding;
|
||||
assign io_dmemReqValid = _mmu_io_ptwMemReq_valid | _dcache_io_memReqValid;
|
||||
assign io_dmemReq_addr =
|
||||
_mmu_io_ptwMemReq_valid ? _mmu_io_ptwMemReq_addr : _dcache_io_memReq_addr;
|
||||
assign io_dmemReq_data = _mmu_io_ptwMemReq_valid ? 64'h0 : _dcache_io_memReq_data;
|
||||
assign io_dmemReq_isStore = ~_mmu_io_ptwMemReq_valid & _dcache_io_memReq_isStore;
|
||||
assign io_dmemReq_size = _mmu_io_ptwMemReq_valid ? 3'h3 : _dcache_io_memReq_size;
|
||||
assign io_respValid = _dcache_io_respValid | translationFault;
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user