mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Don't generate HPTW when MEM_VIRTMEM=0
This commit is contained in:
parent
e3f6758265
commit
a390736f26
@ -46,7 +46,7 @@
|
|||||||
`define MEM_DCACHE 0
|
`define MEM_DCACHE 0
|
||||||
`define MEM_DTIM 1
|
`define MEM_DTIM 1
|
||||||
`define MEM_ICACHE 0
|
`define MEM_ICACHE 0
|
||||||
`define MEM_VIRTMEM 1
|
`define MEM_VIRTMEM 0\1
|
||||||
`define VECTORED_INTERRUPTS_SUPPORTED 1
|
`define VECTORED_INTERRUPTS_SUPPORTED 1
|
||||||
|
|
||||||
`define ITLB_ENTRIES 32
|
`define ITLB_ENTRIES 32
|
||||||
|
@ -70,484 +70,495 @@ module pagetablewalker
|
|||||||
output logic WalkerStorePageFaultM
|
output logic WalkerStorePageFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
// Internal signals
|
|
||||||
// register TLBs translation miss requests
|
|
||||||
logic [`XLEN-1:0] TranslationVAdrQ;
|
|
||||||
logic ITLBMissFQ, DTLBMissMQ;
|
|
||||||
|
|
||||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
|
||||||
logic [`XLEN-1:0] TranslationVAdr;
|
|
||||||
logic [`XLEN-1:0] SavedPTE, CurrentPTE;
|
|
||||||
logic [`PA_BITS-1:0] TranslationPAdr;
|
|
||||||
logic [`PPN_BITS-1:0] CurrentPPN;
|
|
||||||
logic [`SVMODE_BITS-1:0] SvMode;
|
|
||||||
logic MemStore;
|
|
||||||
|
|
||||||
// PTE Control Bits
|
|
||||||
logic Dirty, Accessed, Global, User,
|
|
||||||
Executable, Writable, Readable, Valid;
|
|
||||||
// PTE descriptions
|
|
||||||
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
|
|
||||||
|
|
||||||
// Outputs of walker
|
|
||||||
logic [`XLEN-1:0] PageTableEntry;
|
|
||||||
logic [1:0] PageType;
|
|
||||||
logic StartWalk;
|
|
||||||
logic EndWalk;
|
|
||||||
|
|
||||||
typedef enum {LEVEL0_WDV,
|
|
||||||
LEVEL0,
|
|
||||||
LEVEL1_WDV,
|
|
||||||
LEVEL1,
|
|
||||||
LEVEL2_WDV,
|
|
||||||
LEVEL2,
|
|
||||||
LEVEL3_WDV,
|
|
||||||
LEVEL3,
|
|
||||||
LEAF,
|
|
||||||
IDLE,
|
|
||||||
START,
|
|
||||||
FAULT} statetype;
|
|
||||||
|
|
||||||
statetype WalkerState, NextWalkerState;
|
|
||||||
|
|
||||||
logic PRegEn;
|
|
||||||
logic SelDataTranslation;
|
|
||||||
|
|
||||||
|
|
||||||
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS];
|
|
||||||
|
|
||||||
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0];
|
|
||||||
|
|
||||||
assign MemStore = MemRWM[0];
|
|
||||||
|
|
||||||
// Prefer data address translations over instruction address translations
|
|
||||||
assign TranslationVAdr = (SelDataTranslation) ? MemAdrM : PCF; // *** need to register TranslationVAdr
|
|
||||||
assign SelDataTranslation = DTLBMissMQ | DTLBMissM;
|
|
||||||
|
|
||||||
flopenr #(`XLEN)
|
|
||||||
TranslationVAdrReg(.clk(clk),
|
|
||||||
.reset(reset),
|
|
||||||
.en(StartWalk),
|
|
||||||
.d(TranslationVAdr),
|
|
||||||
.q(TranslationVAdrQ));
|
|
||||||
|
|
||||||
flopenrc #(1)
|
|
||||||
DTLBMissMReg(.clk(clk),
|
|
||||||
.reset(reset),
|
|
||||||
.en(StartWalk | EndWalk),
|
|
||||||
.clear(EndWalk),
|
|
||||||
.d(DTLBMissM),
|
|
||||||
.q(DTLBMissMQ));
|
|
||||||
|
|
||||||
flopenrc #(1)
|
|
||||||
ITLBMissMReg(.clk(clk),
|
|
||||||
.reset(reset),
|
|
||||||
.en(StartWalk | EndWalk),
|
|
||||||
.clear(EndWalk),
|
|
||||||
.d(ITLBMissF),
|
|
||||||
.q(ITLBMissFQ));
|
|
||||||
|
|
||||||
|
|
||||||
assign StartWalk = WalkerState == IDLE && (DTLBMissM | ITLBMissF);
|
|
||||||
assign EndWalk = WalkerState == LEAF ||
|
|
||||||
//(WalkerState == LEVEL0 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
|
||||||
(WalkerState == LEVEL1 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
|
||||||
(WalkerState == LEVEL2 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
|
||||||
(WalkerState == LEVEL3 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
|
||||||
(WalkerState == FAULT);
|
|
||||||
|
|
||||||
assign MMUTranslate = (DTLBMissMQ | ITLBMissFQ) & ~EndWalk;
|
|
||||||
//assign MMUTranslate = DTLBMissM | ITLBMissF;
|
|
||||||
|
|
||||||
// unswizzle PTE bits
|
|
||||||
assign {Dirty, Accessed, Global, User,
|
|
||||||
Executable, Writable, Readable, Valid} = CurrentPTE[7:0];
|
|
||||||
|
|
||||||
// Assign PTE descriptors common across all XLEN values
|
|
||||||
assign LeafPTE = Executable | Writable | Readable;
|
|
||||||
assign ValidPTE = Valid && ~(Writable && ~Readable);
|
|
||||||
assign AccessAlert = ~Accessed | (MemStore & ~Dirty);
|
|
||||||
|
|
||||||
// Assign specific outputs to general outputs
|
|
||||||
assign PageTableEntryF = PageTableEntry;
|
|
||||||
assign PageTableEntryM = PageTableEntry;
|
|
||||||
assign PageTypeF = PageType;
|
|
||||||
assign PageTypeM = PageType;
|
|
||||||
|
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 32) begin
|
if (`MEM_VIRTMEM) begin
|
||||||
logic [9:0] VPN1, VPN0;
|
// Internal signals
|
||||||
|
// register TLBs translation miss requests
|
||||||
|
logic [`XLEN-1:0] TranslationVAdrQ;
|
||||||
|
logic ITLBMissFQ, DTLBMissMQ;
|
||||||
|
|
||||||
|
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||||
|
logic [`XLEN-1:0] TranslationVAdr;
|
||||||
|
logic [`XLEN-1:0] SavedPTE, CurrentPTE;
|
||||||
|
logic [`PA_BITS-1:0] TranslationPAdr;
|
||||||
|
logic [`PPN_BITS-1:0] CurrentPPN;
|
||||||
|
logic [`SVMODE_BITS-1:0] SvMode;
|
||||||
|
logic MemStore;
|
||||||
|
|
||||||
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
// PTE Control Bits
|
||||||
|
logic Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid;
|
||||||
|
// PTE descriptions
|
||||||
|
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
|
||||||
|
|
||||||
/* -----\/----- EXCLUDED -----\/-----
|
// Outputs of walker
|
||||||
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall;
|
logic [`XLEN-1:0] PageTableEntry;
|
||||||
-----/\----- EXCLUDED -----/\----- */
|
logic [1:0] PageType;
|
||||||
|
logic StartWalk;
|
||||||
|
logic EndWalk;
|
||||||
|
|
||||||
|
typedef enum {LEVEL0_WDV,
|
||||||
|
LEVEL0,
|
||||||
|
LEVEL1_WDV,
|
||||||
|
LEVEL1,
|
||||||
|
LEVEL2_WDV,
|
||||||
|
LEVEL2,
|
||||||
|
LEVEL3_WDV,
|
||||||
|
LEVEL3,
|
||||||
|
LEAF,
|
||||||
|
IDLE,
|
||||||
|
START,
|
||||||
|
FAULT} statetype;
|
||||||
|
|
||||||
// State transition logic
|
statetype WalkerState, NextWalkerState;
|
||||||
always_comb begin
|
|
||||||
PRegEn = 1'b0;
|
|
||||||
TranslationPAdr = '0;
|
|
||||||
HPTWRead = 1'b0;
|
|
||||||
PageTableEntry = '0;
|
|
||||||
PageType = '0;
|
|
||||||
DTLBWriteM = '0;
|
|
||||||
ITLBWriteF = '0;
|
|
||||||
|
|
||||||
WalkerInstrPageFaultF = 1'b0;
|
|
||||||
WalkerLoadPageFaultM = 1'b0;
|
|
||||||
WalkerStorePageFaultM = 1'b0;
|
|
||||||
|
|
||||||
case (WalkerState)
|
logic PRegEn;
|
||||||
IDLE: begin
|
logic SelDataTranslation;
|
||||||
if (MMUTranslate && SvMode == `SV32) begin // *** Added SvMode
|
|
||||||
NextWalkerState = START;
|
|
||||||
end else begin
|
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS];
|
||||||
NextWalkerState = IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
START: begin
|
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0];
|
||||||
NextWalkerState = LEVEL1_WDV;
|
|
||||||
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
|
|
||||||
HPTWRead = 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL1_WDV: begin
|
|
||||||
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
|
|
||||||
if (HPTWStall) begin
|
|
||||||
NextWalkerState = LEVEL1_WDV;
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = LEVEL1;
|
|
||||||
PRegEn = 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL1: begin
|
|
||||||
// *** <FUTURE WORK> According to the architecture, we should
|
|
||||||
// fault upon finding a superpage that is misaligned or has 0
|
|
||||||
// access bit. The following commented line of code is
|
|
||||||
// supposed to perform that check. However, it is untested.
|
|
||||||
if (ValidPTE && LeafPTE && ~BadMegapage) begin
|
|
||||||
NextWalkerState = LEAF;
|
|
||||||
PageTableEntry = CurrentPTE;
|
|
||||||
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux?
|
|
||||||
DTLBWriteM = DTLBMissMQ;
|
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
|
||||||
TranslationPAdr = {2'b00, TranslationVAdrQ[31:0]};
|
|
||||||
end
|
|
||||||
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
|
||||||
else if (ValidPTE && ~LeafPTE) begin
|
|
||||||
NextWalkerState = LEVEL0_WDV;
|
|
||||||
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
|
|
||||||
HPTWRead = 1'b1;
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = FAULT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL0_WDV: begin
|
|
||||||
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
|
|
||||||
if (HPTWStall) begin
|
|
||||||
NextWalkerState = LEVEL0_WDV;
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = LEVEL0;
|
|
||||||
PRegEn = 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL0: begin
|
assign MemStore = MemRWM[0];
|
||||||
if (ValidPTE & LeafPTE & ~AccessAlert) begin
|
|
||||||
NextWalkerState = LEAF;
|
|
||||||
PageTableEntry = CurrentPTE;
|
|
||||||
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
|
|
||||||
DTLBWriteM = DTLBMissMQ;
|
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
|
||||||
TranslationPAdr = {2'b00, TranslationVAdrQ[31:0]};
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = FAULT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEAF: begin
|
|
||||||
NextWalkerState = IDLE;
|
|
||||||
end
|
|
||||||
FAULT: begin
|
|
||||||
NextWalkerState = IDLE;
|
|
||||||
WalkerInstrPageFaultF = ~DTLBMissMQ;
|
|
||||||
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
|
|
||||||
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Default case should never happen, but is included for linter.
|
|
||||||
default: NextWalkerState = IDLE;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
// Prefer data address translations over instruction address translations
|
||||||
assign MegapageMisaligned = |(CurrentPPN[9:0]);
|
assign TranslationVAdr = (SelDataTranslation) ? MemAdrM : PCF; // *** need to register TranslationVAdr
|
||||||
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
assign SelDataTranslation = DTLBMissMQ | DTLBMissM;
|
||||||
|
|
||||||
assign VPN1 = TranslationVAdrQ[31:22];
|
flopenr #(`XLEN)
|
||||||
assign VPN0 = TranslationVAdrQ[21:12];
|
TranslationVAdrReg(.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.en(StartWalk),
|
||||||
|
.d(TranslationVAdr),
|
||||||
|
.q(TranslationVAdrQ));
|
||||||
|
|
||||||
|
flopenrc #(1)
|
||||||
|
DTLBMissMReg(.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.en(StartWalk | EndWalk),
|
||||||
|
.clear(EndWalk),
|
||||||
|
.d(DTLBMissM),
|
||||||
|
.q(DTLBMissMQ));
|
||||||
|
|
||||||
|
flopenrc #(1)
|
||||||
|
ITLBMissMReg(.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.en(StartWalk | EndWalk),
|
||||||
|
.clear(EndWalk),
|
||||||
|
.d(ITLBMissF),
|
||||||
|
.q(ITLBMissFQ));
|
||||||
|
|
||||||
|
|
||||||
// Capture page table entry from data cache
|
assign StartWalk = WalkerState == IDLE && (DTLBMissM | ITLBMissF);
|
||||||
// *** may need to delay reading this value until the next clock cycle.
|
assign EndWalk = WalkerState == LEAF ||
|
||||||
// The clk to q latency of the SRAM in the data cache will be long.
|
//(WalkerState == LEVEL0 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
||||||
// I cannot see directly using this value. This is no different than
|
(WalkerState == LEVEL1 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
||||||
// a load delay hazard. This will require rewriting the walker fsm.
|
(WalkerState == LEVEL2 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
||||||
// also need a new signal to save. Should be a mealy output of the fsm
|
(WalkerState == LEVEL3 && ValidPTE && LeafPTE && ~AccessAlert) ||
|
||||||
// request followed by ~stall.
|
(WalkerState == FAULT);
|
||||||
flopenr #(32) ptereg(clk, reset, PRegEn, MMUReadPTE, SavedPTE);
|
|
||||||
//mux2 #(32) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
|
|
||||||
assign CurrentPTE = SavedPTE;
|
|
||||||
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
|
|
||||||
|
|
||||||
// Assign outputs to ahblite
|
|
||||||
// *** Currently truncate address to 32 bits. This must be changed if
|
|
||||||
// we support larger physical address spaces
|
|
||||||
assign MMUPAdr = TranslationPAdr[31:0];
|
|
||||||
|
|
||||||
end else begin
|
|
||||||
|
|
||||||
logic [8:0] VPN3, VPN2, VPN1, VPN0;
|
assign MMUTranslate = (DTLBMissMQ | ITLBMissFQ) & ~EndWalk;
|
||||||
|
//assign MMUTranslate = DTLBMissM | ITLBMissF;
|
||||||
|
|
||||||
logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage;
|
// unswizzle PTE bits
|
||||||
|
assign {Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid} = CurrentPTE[7:0];
|
||||||
|
|
||||||
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
// Assign PTE descriptors common across all XLEN values
|
||||||
|
assign LeafPTE = Executable | Writable | Readable;
|
||||||
|
assign ValidPTE = Valid && ~(Writable && ~Readable);
|
||||||
|
assign AccessAlert = ~Accessed | (MemStore & ~Dirty);
|
||||||
|
|
||||||
/* -----\/----- EXCLUDED -----\/-----
|
// Assign specific outputs to general outputs
|
||||||
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV ||
|
assign PageTableEntryF = PageTableEntry;
|
||||||
WalkerState == LEVEL2_WDV || WalkerState == LEVEL3_WDV) && ~HPTWStall;
|
assign PageTableEntryM = PageTableEntry;
|
||||||
-----/\----- EXCLUDED -----/\----- */
|
assign PageTypeF = PageType;
|
||||||
|
assign PageTypeM = PageType;
|
||||||
|
|
||||||
//assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || WalkerState == LEVEL3 ||
|
|
||||||
// WalkerState == LEVEL2 || WalkerState == LEVEL1;
|
// generate
|
||||||
|
if (`XLEN == 32) begin
|
||||||
|
logic [9:0] VPN1, VPN0;
|
||||||
|
|
||||||
|
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||||
|
|
||||||
|
/* -----\/----- EXCLUDED -----\/-----
|
||||||
|
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall;
|
||||||
|
-----/\----- EXCLUDED -----/\----- */
|
||||||
|
|
||||||
|
// State transition logic
|
||||||
|
always_comb begin
|
||||||
|
PRegEn = 1'b0;
|
||||||
|
TranslationPAdr = '0;
|
||||||
|
HPTWRead = 1'b0;
|
||||||
|
PageTableEntry = '0;
|
||||||
|
PageType = '0;
|
||||||
|
DTLBWriteM = '0;
|
||||||
|
ITLBWriteF = '0;
|
||||||
|
|
||||||
|
WalkerInstrPageFaultF = 1'b0;
|
||||||
|
WalkerLoadPageFaultM = 1'b0;
|
||||||
|
WalkerStorePageFaultM = 1'b0;
|
||||||
|
|
||||||
always_comb begin
|
case (WalkerState)
|
||||||
PRegEn = 1'b0;
|
IDLE: begin
|
||||||
TranslationPAdr = '0;
|
if (MMUTranslate && SvMode == `SV32) begin // *** Added SvMode
|
||||||
HPTWRead = 1'b0;
|
NextWalkerState = START;
|
||||||
PageTableEntry = '0;
|
end else begin
|
||||||
PageType = '0;
|
NextWalkerState = IDLE;
|
||||||
DTLBWriteM = '0;
|
end
|
||||||
ITLBWriteF = '0;
|
end
|
||||||
|
|
||||||
WalkerInstrPageFaultF = 1'b0;
|
|
||||||
WalkerLoadPageFaultM = 1'b0;
|
|
||||||
WalkerStorePageFaultM = 1'b0;
|
|
||||||
|
|
||||||
case (WalkerState)
|
START: begin
|
||||||
IDLE: begin
|
NextWalkerState = LEVEL1_WDV;
|
||||||
if (MMUTranslate && (SvMode == `SV48 || SvMode == `SV39)) begin
|
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
|
||||||
NextWalkerState = START;
|
HPTWRead = 1'b1;
|
||||||
end else begin
|
end
|
||||||
NextWalkerState = IDLE;
|
|
||||||
end
|
LEVEL1_WDV: begin
|
||||||
end
|
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
|
||||||
|
if (HPTWStall) begin
|
||||||
START: begin
|
NextWalkerState = LEVEL1_WDV;
|
||||||
if (MMUTranslate && SvMode == `SV48) begin
|
end else begin
|
||||||
NextWalkerState = LEVEL3_WDV;
|
NextWalkerState = LEVEL1;
|
||||||
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
|
PRegEn = 1'b1;
|
||||||
HPTWRead = 1'b1;
|
end
|
||||||
end else if (MMUTranslate && SvMode == `SV39) begin
|
end
|
||||||
NextWalkerState = LEVEL2_WDV;
|
|
||||||
TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000};
|
LEVEL1: begin
|
||||||
HPTWRead = 1'b1;
|
// *** <FUTURE WORK> According to the architecture, we should
|
||||||
end else begin // *** should not get here
|
// fault upon finding a superpage that is misaligned or has 0
|
||||||
NextWalkerState = IDLE;
|
// access bit. The following commented line of code is
|
||||||
TranslationPAdr = '0;
|
// supposed to perform that check. However, it is untested.
|
||||||
end
|
if (ValidPTE && LeafPTE && ~BadMegapage) begin
|
||||||
end
|
NextWalkerState = LEAF;
|
||||||
|
PageTableEntry = CurrentPTE;
|
||||||
LEVEL3_WDV: begin
|
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux?
|
||||||
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
|
DTLBWriteM = DTLBMissMQ;
|
||||||
if (HPTWStall) begin
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
NextWalkerState = LEVEL3_WDV;
|
TranslationPAdr = {2'b00, TranslationVAdrQ[31:0]};
|
||||||
end else begin
|
end
|
||||||
NextWalkerState = LEVEL3;
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
||||||
PRegEn = 1'b1;
|
else if (ValidPTE && ~LeafPTE) begin
|
||||||
end
|
NextWalkerState = LEVEL0_WDV;
|
||||||
end
|
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
|
||||||
|
HPTWRead = 1'b1;
|
||||||
LEVEL3: begin
|
end else begin
|
||||||
// *** <FUTURE WORK> According to the architecture, we should
|
NextWalkerState = FAULT;
|
||||||
// fault upon finding a superpage that is misaligned or has 0
|
end
|
||||||
// access bit. The following commented line of code is
|
end
|
||||||
// supposed to perform that check. However, it is untested.
|
|
||||||
if (ValidPTE && LeafPTE && ~BadTerapage) begin
|
LEVEL0_WDV: begin
|
||||||
NextWalkerState = LEAF;
|
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
|
||||||
PageTableEntry = CurrentPTE;
|
if (HPTWStall) begin
|
||||||
PageType = (WalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux?
|
NextWalkerState = LEVEL0_WDV;
|
||||||
((WalkerState == LEVEL2) ? 2'b10 :
|
end else begin
|
||||||
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
NextWalkerState = LEVEL0;
|
||||||
DTLBWriteM = DTLBMissMQ;
|
PRegEn = 1'b1;
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
end
|
||||||
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
end
|
||||||
end
|
|
||||||
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
|
||||||
else if (ValidPTE && ~LeafPTE) begin
|
|
||||||
NextWalkerState = LEVEL2_WDV;
|
|
||||||
TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000};
|
|
||||||
HPTWRead = 1'b1;
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = FAULT;
|
|
||||||
end
|
|
||||||
|
|
||||||
|
LEVEL0: begin
|
||||||
|
if (ValidPTE & LeafPTE & ~AccessAlert) begin
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
PageTableEntry = CurrentPTE;
|
||||||
|
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
|
||||||
|
DTLBWriteM = DTLBMissMQ;
|
||||||
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
|
TranslationPAdr = {2'b00, TranslationVAdrQ[31:0]};
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = FAULT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LEAF: begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
end
|
||||||
|
FAULT: begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
WalkerInstrPageFaultF = ~DTLBMissMQ;
|
||||||
|
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
|
||||||
|
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Default case should never happen, but is included for linter.
|
||||||
|
default: NextWalkerState = IDLE;
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
LEVEL2_WDV: begin
|
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
||||||
TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000};
|
assign MegapageMisaligned = |(CurrentPPN[9:0]);
|
||||||
//HPTWRead = 1'b1;
|
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
if (HPTWStall) begin
|
|
||||||
NextWalkerState = LEVEL2_WDV;
|
assign VPN1 = TranslationVAdrQ[31:22];
|
||||||
end else begin
|
assign VPN0 = TranslationVAdrQ[21:12];
|
||||||
NextWalkerState = LEVEL2;
|
|
||||||
PRegEn = 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL2: begin
|
|
||||||
// *** <FUTURE WORK> According to the architecture, we should
|
|
||||||
// fault upon finding a superpage that is misaligned or has 0
|
|
||||||
// access bit. The following commented line of code is
|
|
||||||
// supposed to perform that check. However, it is untested.
|
|
||||||
if (ValidPTE && LeafPTE && ~BadGigapage) begin
|
|
||||||
NextWalkerState = LEAF;
|
|
||||||
PageTableEntry = CurrentPTE;
|
|
||||||
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
|
||||||
((WalkerState == LEVEL2) ? 2'b10 :
|
|
||||||
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
|
||||||
DTLBWriteM = DTLBMissMQ;
|
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
|
||||||
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
|
||||||
end
|
|
||||||
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
|
||||||
else if (ValidPTE && ~LeafPTE) begin
|
|
||||||
NextWalkerState = LEVEL1_WDV;
|
|
||||||
TranslationPAdr = {CurrentPPN, VPN1, 3'b000};
|
|
||||||
HPTWRead = 1'b1;
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = FAULT;
|
|
||||||
end
|
|
||||||
|
|
||||||
|
// Capture page table entry from data cache
|
||||||
|
// *** may need to delay reading this value until the next clock cycle.
|
||||||
|
// The clk to q latency of the SRAM in the data cache will be long.
|
||||||
|
// I cannot see directly using this value. This is no different than
|
||||||
|
// a load delay hazard. This will require rewriting the walker fsm.
|
||||||
|
// also need a new signal to save. Should be a mealy output of the fsm
|
||||||
|
// request followed by ~stall.
|
||||||
|
flopenr #(32) ptereg(clk, reset, PRegEn, MMUReadPTE, SavedPTE);
|
||||||
|
//mux2 #(32) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
|
||||||
|
assign CurrentPTE = SavedPTE;
|
||||||
|
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
|
||||||
|
|
||||||
|
// Assign outputs to ahblite
|
||||||
|
// *** Currently truncate address to 32 bits. This must be changed if
|
||||||
|
// we support larger physical address spaces
|
||||||
|
assign MMUPAdr = TranslationPAdr[31:0];
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
logic [8:0] VPN3, VPN2, VPN1, VPN0;
|
||||||
|
|
||||||
|
logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage;
|
||||||
|
|
||||||
|
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||||
|
|
||||||
|
/* -----\/----- EXCLUDED -----\/-----
|
||||||
|
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV ||
|
||||||
|
WalkerState == LEVEL2_WDV || WalkerState == LEVEL3_WDV) && ~HPTWStall;
|
||||||
|
-----/\----- EXCLUDED -----/\----- */
|
||||||
|
|
||||||
|
//assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || WalkerState == LEVEL3 ||
|
||||||
|
// WalkerState == LEVEL2 || WalkerState == LEVEL1;
|
||||||
|
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
PRegEn = 1'b0;
|
||||||
|
TranslationPAdr = '0;
|
||||||
|
HPTWRead = 1'b0;
|
||||||
|
PageTableEntry = '0;
|
||||||
|
PageType = '0;
|
||||||
|
DTLBWriteM = '0;
|
||||||
|
ITLBWriteF = '0;
|
||||||
|
|
||||||
|
WalkerInstrPageFaultF = 1'b0;
|
||||||
|
WalkerLoadPageFaultM = 1'b0;
|
||||||
|
WalkerStorePageFaultM = 1'b0;
|
||||||
|
|
||||||
|
case (WalkerState)
|
||||||
|
IDLE: begin
|
||||||
|
if (MMUTranslate && (SvMode == `SV48 || SvMode == `SV39)) begin
|
||||||
|
NextWalkerState = START;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
LEVEL1_WDV: begin
|
START: begin
|
||||||
TranslationPAdr = {CurrentPPN, VPN1, 3'b000};
|
if (MMUTranslate && SvMode == `SV48) begin
|
||||||
//HPTWRead = 1'b1;
|
NextWalkerState = LEVEL3_WDV;
|
||||||
if (HPTWStall) begin
|
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
|
||||||
NextWalkerState = LEVEL1_WDV;
|
HPTWRead = 1'b1;
|
||||||
end else begin
|
end else if (MMUTranslate && SvMode == `SV39) begin
|
||||||
NextWalkerState = LEVEL1;
|
NextWalkerState = LEVEL2_WDV;
|
||||||
PRegEn = 1'b1;
|
TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000};
|
||||||
end
|
HPTWRead = 1'b1;
|
||||||
|
end else begin // *** should not get here
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
TranslationPAdr = '0;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
LEVEL1: begin
|
LEVEL3_WDV: begin
|
||||||
// *** <FUTURE WORK> According to the architecture, we should
|
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
|
||||||
// fault upon finding a superpage that is misaligned or has 0
|
if (HPTWStall) begin
|
||||||
// access bit. The following commented line of code is
|
NextWalkerState = LEVEL3_WDV;
|
||||||
// supposed to perform that check. However, it is untested.
|
end else begin
|
||||||
if (ValidPTE && LeafPTE && ~BadMegapage) begin
|
NextWalkerState = LEVEL3;
|
||||||
NextWalkerState = LEAF;
|
PRegEn = 1'b1;
|
||||||
PageTableEntry = CurrentPTE;
|
end
|
||||||
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
end
|
||||||
((WalkerState == LEVEL2) ? 2'b10 :
|
|
||||||
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
LEVEL3: begin
|
||||||
DTLBWriteM = DTLBMissMQ;
|
// *** <FUTURE WORK> According to the architecture, we should
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
// fault upon finding a superpage that is misaligned or has 0
|
||||||
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
// access bit. The following commented line of code is
|
||||||
|
// supposed to perform that check. However, it is untested.
|
||||||
|
if (ValidPTE && LeafPTE && ~BadTerapage) begin
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
PageTableEntry = CurrentPTE;
|
||||||
|
PageType = (WalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux?
|
||||||
|
((WalkerState == LEVEL2) ? 2'b10 :
|
||||||
|
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
||||||
|
DTLBWriteM = DTLBMissMQ;
|
||||||
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
|
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
||||||
|
end
|
||||||
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
||||||
|
else if (ValidPTE && ~LeafPTE) begin
|
||||||
|
NextWalkerState = LEVEL2_WDV;
|
||||||
|
TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000};
|
||||||
|
HPTWRead = 1'b1;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = FAULT;
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
LEVEL2_WDV: begin
|
||||||
|
TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000};
|
||||||
|
//HPTWRead = 1'b1;
|
||||||
|
if (HPTWStall) begin
|
||||||
|
NextWalkerState = LEVEL2_WDV;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = LEVEL2;
|
||||||
|
PRegEn = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
LEVEL2: begin
|
||||||
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
// *** <FUTURE WORK> According to the architecture, we should
|
||||||
else if (ValidPTE && ~LeafPTE) begin
|
// fault upon finding a superpage that is misaligned or has 0
|
||||||
NextWalkerState = LEVEL0_WDV;
|
// access bit. The following commented line of code is
|
||||||
TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
|
// supposed to perform that check. However, it is untested.
|
||||||
HPTWRead = 1'b1;
|
if (ValidPTE && LeafPTE && ~BadGigapage) begin
|
||||||
end else begin
|
NextWalkerState = LEAF;
|
||||||
NextWalkerState = FAULT;
|
PageTableEntry = CurrentPTE;
|
||||||
end
|
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
||||||
|
((WalkerState == LEVEL2) ? 2'b10 :
|
||||||
|
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
||||||
|
DTLBWriteM = DTLBMissMQ;
|
||||||
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
|
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
||||||
|
end
|
||||||
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
||||||
|
else if (ValidPTE && ~LeafPTE) begin
|
||||||
|
NextWalkerState = LEVEL1_WDV;
|
||||||
|
TranslationPAdr = {CurrentPPN, VPN1, 3'b000};
|
||||||
|
HPTWRead = 1'b1;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = FAULT;
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
LEVEL1_WDV: begin
|
||||||
|
TranslationPAdr = {CurrentPPN, VPN1, 3'b000};
|
||||||
|
//HPTWRead = 1'b1;
|
||||||
|
if (HPTWStall) begin
|
||||||
|
NextWalkerState = LEVEL1_WDV;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = LEVEL1;
|
||||||
|
PRegEn = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LEVEL1: begin
|
||||||
|
// *** <FUTURE WORK> According to the architecture, we should
|
||||||
|
// fault upon finding a superpage that is misaligned or has 0
|
||||||
|
// access bit. The following commented line of code is
|
||||||
|
// supposed to perform that check. However, it is untested.
|
||||||
|
if (ValidPTE && LeafPTE && ~BadMegapage) begin
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
PageTableEntry = CurrentPTE;
|
||||||
|
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
||||||
|
((WalkerState == LEVEL2) ? 2'b10 :
|
||||||
|
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
||||||
|
DTLBWriteM = DTLBMissMQ;
|
||||||
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
|
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
||||||
|
|
||||||
|
end
|
||||||
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
|
||||||
|
else if (ValidPTE && ~LeafPTE) begin
|
||||||
|
NextWalkerState = LEVEL0_WDV;
|
||||||
|
TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
|
||||||
|
HPTWRead = 1'b1;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = FAULT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LEVEL0_WDV: begin
|
||||||
|
TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
|
||||||
|
if (HPTWStall) begin
|
||||||
|
NextWalkerState = LEVEL0_WDV;
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = LEVEL0;
|
||||||
|
PRegEn = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LEVEL0: begin
|
||||||
|
if (ValidPTE && LeafPTE && ~AccessAlert) begin
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
PageTableEntry = CurrentPTE;
|
||||||
|
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
||||||
|
((WalkerState == LEVEL2) ? 2'b10 :
|
||||||
|
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
||||||
|
DTLBWriteM = DTLBMissMQ;
|
||||||
|
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
||||||
|
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
||||||
|
end else begin
|
||||||
|
NextWalkerState = FAULT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LEAF: begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
FAULT: begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
WalkerInstrPageFaultF = ~DTLBMissMQ;
|
||||||
|
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
|
||||||
|
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Default case should never happen
|
||||||
|
default: begin
|
||||||
|
NextWalkerState = IDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
LEVEL0_WDV: begin
|
// A terapage is a level 3 leaf page. This page must have zero PPN[2],
|
||||||
TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
|
// zero PPN[1], and zero PPN[0]
|
||||||
if (HPTWStall) begin
|
assign TerapageMisaligned = |(CurrentPPN[26:0]);
|
||||||
NextWalkerState = LEVEL0_WDV;
|
// A gigapage is a Level 2 leaf page. This page must have zero PPN[1] and
|
||||||
end else begin
|
// zero PPN[0]
|
||||||
NextWalkerState = LEVEL0;
|
assign GigapageMisaligned = |(CurrentPPN[17:0]);
|
||||||
PRegEn = 1'b1;
|
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
||||||
end
|
assign MegapageMisaligned = |(CurrentPPN[8:0]);
|
||||||
end
|
|
||||||
|
|
||||||
LEVEL0: begin
|
assign BadTerapage = TerapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
if (ValidPTE && LeafPTE && ~AccessAlert) begin
|
assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
NextWalkerState = LEAF;
|
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
PageTableEntry = CurrentPTE;
|
|
||||||
PageType = (WalkerState == LEVEL3) ? 2'b11 :
|
|
||||||
((WalkerState == LEVEL2) ? 2'b10 :
|
|
||||||
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
|
|
||||||
DTLBWriteM = DTLBMissMQ;
|
|
||||||
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
|
|
||||||
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
|
|
||||||
end else begin
|
|
||||||
NextWalkerState = FAULT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
LEAF: begin
|
|
||||||
NextWalkerState = IDLE;
|
|
||||||
end
|
|
||||||
|
|
||||||
FAULT: begin
|
assign VPN3 = TranslationVAdrQ[47:39];
|
||||||
NextWalkerState = IDLE;
|
assign VPN2 = TranslationVAdrQ[38:30];
|
||||||
WalkerInstrPageFaultF = ~DTLBMissMQ;
|
assign VPN1 = TranslationVAdrQ[29:21];
|
||||||
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
|
assign VPN0 = TranslationVAdrQ[20:12];
|
||||||
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Default case should never happen
|
|
||||||
default: begin
|
|
||||||
NextWalkerState = IDLE;
|
|
||||||
end
|
|
||||||
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
// A terapage is a level 3 leaf page. This page must have zero PPN[2],
|
|
||||||
// zero PPN[1], and zero PPN[0]
|
|
||||||
assign TerapageMisaligned = |(CurrentPPN[26:0]);
|
|
||||||
// A gigapage is a Level 2 leaf page. This page must have zero PPN[1] and
|
|
||||||
// zero PPN[0]
|
|
||||||
assign GigapageMisaligned = |(CurrentPPN[17:0]);
|
|
||||||
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
|
||||||
assign MegapageMisaligned = |(CurrentPPN[8:0]);
|
|
||||||
|
|
||||||
assign BadTerapage = TerapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
|
||||||
assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
|
||||||
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
|
||||||
|
|
||||||
assign VPN3 = TranslationVAdrQ[47:39];
|
|
||||||
assign VPN2 = TranslationVAdrQ[38:30];
|
|
||||||
assign VPN1 = TranslationVAdrQ[29:21];
|
|
||||||
assign VPN0 = TranslationVAdrQ[20:12];
|
|
||||||
|
|
||||||
|
|
||||||
// Capture page table entry from ahblite
|
// Capture page table entry from ahblite
|
||||||
flopenr #(`XLEN) ptereg(clk, reset, PRegEn, MMUReadPTE, SavedPTE);
|
flopenr #(`XLEN) ptereg(clk, reset, PRegEn, MMUReadPTE, SavedPTE);
|
||||||
//mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
|
//mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
|
||||||
assign CurrentPTE = SavedPTE;
|
assign CurrentPTE = SavedPTE;
|
||||||
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
|
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
|
||||||
|
|
||||||
// Assign outputs to ahblite
|
// Assign outputs to ahblite
|
||||||
// *** Currently truncate address to 32 bits. This must be changed if
|
// *** Currently truncate address to 32 bits. This must be changed if
|
||||||
// we support larger physical address spaces
|
// we support larger physical address spaces
|
||||||
assign MMUPAdr = {{(`XLEN-`PA_BITS){1'b0}}, TranslationPAdr[`PA_BITS-1:0]};
|
assign MMUPAdr = {{(`XLEN-`PA_BITS){1'b0}}, TranslationPAdr[`PA_BITS-1:0]};
|
||||||
|
end
|
||||||
|
//endgenerate
|
||||||
|
end else begin
|
||||||
|
assign MMUPAdr = 0;
|
||||||
|
assign MMUTranslate = 0;
|
||||||
|
assign HPTWRead = 0;
|
||||||
|
assign WalkerInstrPageFaultF = 0;
|
||||||
|
assign WalkerLoadPageFaultM = 0;
|
||||||
|
assign WalkerStorePageFaultM = 0;
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user