Complete basic page table walker

This commit is contained in:
Thomas Fleming 2021-03-30 22:19:27 -04:00
parent 0994d03b28
commit 7126ab7864
10 changed files with 208 additions and 181 deletions

View File

@ -27,7 +27,7 @@
// RV32 or RV64: XLEN = 32 or 64
`define XLEN 32
`define MISA (32'h00000104 | 1 << 12)
`define MISA (32'h00000104 | 1 << 20 | 1 << 18 | 1 << 12)
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
@ -53,7 +53,7 @@
`define MEM_DCACHE 0
`define MEM_DTIM 1
`define MEM_ICACHE 0
`define MEM_VIRTMEM 0
`define MEM_VIRTMEM 1
// Address space
`define RESET_VECTOR 32'h80000000

View File

@ -54,7 +54,7 @@
`define MEM_DCACHE 0
`define MEM_DTIM 1
`define MEM_ICACHE 0
`define MEM_VIRTMEM 0
`define MEM_VIRTMEM 1
// Address space
`define RESET_VECTOR 64'h0000000080000000

View File

@ -54,7 +54,7 @@
`define MEM_DCACHE 0
`define MEM_DTIM 1
`define MEM_ICACHE 0
`define MEM_VIRTMEM 0
`define MEM_VIRTMEM 1
// Address space
`define RESET_VECTOR 64'h0000000080000000

View File

@ -57,13 +57,14 @@ module dmem (
output logic DTLBMissM, DTLBHitM
);
logic MemAccessM; // Whether memory needs to be accessed
logic SquashSCM;
// *** temporary hack until walker is hooked up -- Thomas F
// logic [`XLEN-1:0] PageTableEntryM = '0;
logic DTLBFlushM = '0;
// logic DTLBWriteM = '0;
tlb #(3) dtlb(clk, reset, SATP_REGW, PrivilegeModeW, MemAdrM, PageTableEntryM, DTLBWriteM,
tlb #(3) dtlb(clk, reset, SATP_REGW, PrivilegeModeW, MemAccessM, MemAdrM, PageTableEntryM, DTLBWriteM,
DTLBFlushM, MemPAdrM, DTLBMissM, DTLBHitM);
// Determine if an Unaligned access is taking place
@ -78,11 +79,12 @@ module dmem (
// Squash unaligned data accesses and failed store conditionals
// *** this is also the place to squash if the cache is hit
assign MemReadM = MemRWM[1] & ~DataMisalignedM;
assign MemWriteM = MemRWM[0] & ~DataMisalignedM && ~SquashSCM;
assign MemWriteM = MemRWM[0] & ~DataMisalignedM && ~SquashSCM;
assign MemAccessM = |MemRWM;
// Determine if address is valid
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
assign LoadAccessFaultM = DataAccessFaultM & MemRWM[0];
assign LoadAccessFaultM = DataAccessFaultM & MemRWM[1];
assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0];
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
@ -97,7 +99,7 @@ module dmem (
assign scM = MemRWM[0] && AtomicM[0];
assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`XLEN-1:2] == ReservationPAdrW) && ReservationValidW;
assign SquashSCM = scM && ~WriteAdrMatchM;
always_comb begin // ReservationValidM (next valiue of valid reservation)
always_comb begin // ReservationValidM (next value of valid reservation)
if (lrM) ReservationValidM = 1; // set valid on load reserve
else if (scM || WriteAdrMatchM) ReservationValidM = 0; // clear valid on store to same address or any sc
else ReservationValidM = ReservationValidW; // otherwise don't change valid

View File

@ -49,6 +49,7 @@ module ahblite (
// Signals from MMU
input logic [`XLEN-1:0] MMUPAdr,
input logic MMUTranslate, MMUTranslationComplete,
input logic TrapM,
output logic [`XLEN-1:0] MMUReadPTE,
output logic MMUReady,
// Return from bus
@ -104,16 +105,16 @@ module ahblite (
else if (InstrReadF) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MMUTRANSLATE: if (~HREADY) NextBusState = MMUTRANSLATE;
else NextBusState = MMUIDLE;
else NextBusState = IDLE;
// *** Could the MMUIDLE state just be the normal idle state?
// Do we trust MMUTranslate to be high exactly when we need translation?
MMUIDLE: if (~MMUTranslationComplete)
NextBusState = MMUTRANSLATE;
else if (AtomicM[1]) NextBusState = ATOMICREAD;
else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions
else if (MemWriteM) NextBusState = MEMWRITE;
else if (InstrReadF) NextBusState = INSTRREAD;
else NextBusState = IDLE;
// MMUIDLE: if (MMUTranslate)
// NextBusState = MMUTRANSLATE;
// else if (AtomicM[1]) NextBusState = ATOMICREAD;
// else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions
// else if (MemWriteM) NextBusState = MEMWRITE;
// else if (InstrReadF) NextBusState = INSTRREAD;
// else NextBusState = IDLE;
ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD;
else NextBusState = ATOMICWRITE;
ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE;
@ -133,13 +134,15 @@ module ahblite (
endcase
// stall signals
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
// Note that we need to extend both stalls when MMUTRANSLATE goes to idle,
// since translation might not be complete.
assign #2 DataStall = ~TrapM && ((NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) ||
(NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE);
(NextBusState == MMUTRANSLATE) || (BusState == MMUTRANSLATE));
// *** Could get finer grained stalling if we distinguish between MMU
// instruction address translation and data address translation
assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) ||
(NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE);
assign #1 InstrStall = ~TrapM && ((NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) ||
(NextBusState == MMUTRANSLATE) || (BusState == MMUTRANSLATE));
// bus outputs
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
@ -158,7 +161,7 @@ module ahblite (
assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
assign HMASTLOCK = 0; // no locking supported
assign HWRITE = (NextBusState == MEMWRITE) || (NextBusState == ATOMICWRITE);
// delay write data by one cycle for
// delay write data by one cycle for
flop #(`XLEN) wdreg(HCLK, WriteData, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
// delay signals for subword writes
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
@ -168,7 +171,7 @@ module ahblite (
// Route signals to Instruction and Data Caches
// *** assumes AHBW = XLEN
assign #1 MMUReady = (NextBusState == MMUIDLE);
assign MMUReady = (BusState == MMUTRANSLATE && NextBusState == IDLE);
assign InstrRData = HRDATA;
assign MMUReadPTE = HRDATA;

View File

@ -27,46 +27,71 @@
`include "wally-config.vh"
`include "wally-constants.vh"
module pagetablewalker (
input logic clk, reset,
/* ***
TO-DO:
- Faults have a timing issue and currently do not work.
- Leaf state brings HADDR down to zeros (maybe fixed?)
- Complete rv64ic case
- Implement better accessed/dirty behavior
- Implement read/write/execute checking (either here or in TLB)
*/
module pagetablewalker (
// Control signals
input logic HCLK, HRESETn,
input logic [`XLEN-1:0] SATP_REGW,
input logic MemWriteM,
input logic ITLBMissF, DTLBMissM,
// Signals from TLBs (addresses to translate)
input logic [`XLEN-1:0] PCF, MemAdrM,
input logic ITLBMissF, DTLBMissM,
input logic [1:0] MemRWM,
// Outputs to the TLBs (PTEs to write)
output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
output logic ITLBWriteF, DTLBWriteM,
// *** handshake to tlbs probably not needed, since stalls take effect
output logic MMUTranslationComplete,
// Signals from and to ahblite
// Signals from ahblite (PTEs from memory)
input logic [`XLEN-1:0] MMUReadPTE,
input logic MMUReady,
// Signals to ahblite (memory addresses to access)
output logic [`XLEN-1:0] MMUPAdr,
output logic MMUTranslate,
output logic MMUTranslationComplete,
// Faults
output logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM
);
logic SvMode;
// Internal signals
logic SvMode, TLBMiss;
logic [`PPN_BITS-1:0] BasePageTablePPN;
logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE, TranslationVAdr;
logic [`XLEN-1:0] TranslationVAdr;
logic [`XLEN-1:0] SavedPTE, CurrentPTE;
logic [`PA_BITS-1:0] TranslationPAdr;
logic [`PPN_BITS-1:0] CurrentPPN;
logic MemStore;
logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
// PTE Control Bits
logic Dirty, Accessed, Global, User,
Executable, Writable, Readable, Valid;
// PTE descriptions
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
// rv32 temp case
logic [`VPN_BITS-1:0] PCPageNumber;
logic [`VPN_BITS-1:0] MemAdrPageNumber;
// Signals for direct, fake translations. Not part of the final Wally version.
logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE;
logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
logic [`VPN_BITS-1:0] PCPageNumber, MemAdrPageNumber;
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0];
assign MemStore = MemRWM[0];
assign PCPageNumber = PCF[`VPN_BITS+11:12];
assign MemAdrPageNumber = MemAdrM[`VPN_BITS+11:12];
// Create fake page table entries for direct virtual to physical translation
generate
if (`XLEN == 32) begin
assign DirectInstrPTE = {PCPageNumber, DirectPTEFlags};
@ -77,36 +102,39 @@ module pagetablewalker (
end
endgenerate
//flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF);
//flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM);
// Direct translation flops
//flopenr #(`XLEN) instrpte(HCLK, ~HRESETn, ITLBMissF, DirectInstrPTE, PageTableEntryF);
//flopenr #(`XLEN) datapte(HCLK, ~HRESETn, DTLBMissM, DirectMemPTE, PageTableEntryM);
//flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF);
//flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM);
//flopr #(1) iwritesignal(HCLK, ~HRESETn, ITLBMissF, ITLBWriteF);
//flopr #(1) dwritesignal(HCLK, ~HRESETn, DTLBMissM, DTLBWriteM);
// Prefer data address translations over instruction address translations
assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF;
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);
generate
if (`XLEN == 32) begin
logic [9:0] VPN1, VPN0;
assign SvMode = SATP_REGW[31];
logic [9:0] VPN1 = TranslationVAdr[31:22];
logic [9:0] VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset?
logic [33:0] TranslationPAdr;
logic [21:0] CurrentPPN;
logic Dirty, Accessed, Global, User,
Executable, Writable, Readable, Valid;
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
typedef enum {IDLE, LEVEL1, LEVEL0, LEAF, FAULT} statetype;
statetype WalkerState, NextWalkerState;
typedef enum {IDLE, LEVEL1, LEVEL0, LEAF, FAULT} walker_statetype;
walker_statetype WalkerState, NextWalkerState;
// *** Do we need a synchronizer here for walker to talk to ahblite?
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
flopenl #(.TYPE(walker_statetype)) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState);
// State transition logic
always_comb begin
case (WalkerState)
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1;
@ -129,62 +157,59 @@ module pagetablewalker (
endcase
end
// unswizzle PTE bits
assign {Dirty, Accessed, Global, User,
Executable, Writable, Readable, Valid} = MMUReadPTE[7:0];
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
assign MegapageMisaligned = |(CurrentPPN[9:0]);
assign LeafPTE = Executable | Writable | Readable;
assign ValidPTE = Valid && ~(Writable && ~Readable);
assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty);
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
// *** Should translate this flop block into our flop module notation
always_ff @(posedge clk, negedge reset)
if (reset) begin
TranslationPAdr <= '0;
PageTableEntryF <= '0;
MMUTranslationComplete <= '0;
DTLBWriteM <= '0;
ITLBWriteF <= '0;
InstrPageFaultM <= '0;
LoadPageFaultM <= '0;
StorePageFaultM <= '0;
end else begin
// default values
TranslationPAdr <= '0;
PageTableEntryF <= '0;
MMUTranslationComplete <= '0;
DTLBWriteM <= '0;
ITLBWriteF <= '0;
InstrPageFaultM <= '0;
LoadPageFaultM <= '0;
StorePageFaultM <= '0;
case (NextWalkerState)
LEVEL1: begin
TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00};
end
LEVEL0: begin
TranslationPAdr <= {CurrentPPN, VPN0, 2'b00};
end
LEAF: begin
PageTableEntryF <= MMUReadPTE;
PageTableEntryM <= MMUReadPTE;
MMUTranslationComplete <= '1;
DTLBWriteM <= DTLBMissM;
ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions
end
FAULT: begin
InstrPageFaultM <= ~DTLBMissM;
LoadPageFaultM <= DTLBMissM && ~MemWriteM;
StorePageFaultM <= DTLBMissM && MemWriteM;
end
endcase
end
assign VPN1 = TranslationVAdr[31:22];
assign VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset?
// Interpret inputs from ahblite
assign CurrentPPN = MMUReadPTE[31:10];
// Assign combinational outputs
always_comb begin
// default values
assign TranslationPAdr = '0;
assign PageTableEntryF = '0;
assign PageTableEntryM = '0;
assign MMUTranslationComplete = '0;
assign DTLBWriteM = '0;
assign ITLBWriteF = '0;
assign InstrPageFaultM = '0;
assign LoadPageFaultM = '0;
assign StorePageFaultM = '0;
case (NextWalkerState)
LEVEL1: begin
assign TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
end
LEVEL0: begin
assign TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
end
LEAF: begin
// Keep physical address alive to prevent HADDR dropping to 0
assign TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
assign PageTableEntryF = CurrentPTE;
assign PageTableEntryM = CurrentPTE;
assign MMUTranslationComplete = '1;
assign DTLBWriteM = DTLBMissM;
assign ITLBWriteF = ~DTLBMissM; // Prefer data over instructions
end
FAULT: begin
assign InstrPageFaultM = ~DTLBMissM;
assign LoadPageFaultM = DTLBMissM && ~MemStore;
assign StorePageFaultM = DTLBMissM && MemStore;
end
endcase
end
// Capture page table entry from ahblite
flopenr #(32) ptereg(HCLK, ~HRESETn, MMUReady, MMUReadPTE, SavedPTE);
// *** Evil hack to get CurrentPTE a cycle early before it is saved.
// Todo: Is it evil?
mux2 #(32) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE);
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
// Assign outputs to ahblite
// *** Currently truncate address to 32 bits. This must be changed if
@ -194,27 +219,19 @@ module pagetablewalker (
end else begin
assign SvMode = SATP_REGW[63];
logic [8:0] VPN2 = TranslationVAdr[38:30];
logic [8:0] VPN1 = TranslationVAdr[29:21];
logic [8:0] VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset?
logic [8:0] VPN2, VPN1, VPN0;
logic [55:0] TranslationPAdr;
logic [43:0] CurrentPPN;
logic GigapageMisaligned, BadGigapage;
logic Dirty, Accessed, Global, User,
Executable, Writable, Readable, Valid;
logic ValidPTE, AccessAlert, GigapageMisaligned, MegapageMisaligned,
BadGigapage, BadMegapage, LeafPTE;
typedef enum {IDLE, LEVEL2, LEVEL1, LEVEL0, LEAF, FAULT} statetype;
statetype WalkerState, NextWalkerState;
typedef enum {IDLE, LEVEL2, LEVEL1, LEVEL0, LEAF, FAULT} walker_statetype;
walker_statetype WalkerState, NextWalkerState;
// *** Do we need a synchronizer here for walker to talk to ahblite?
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
flopenl #(.TYPE(walker_statetype)) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState);
always_comb begin
case (WalkerState)
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1;
IDLE: if (MMUTranslate) NextWalkerState = LEVEL2;
else NextWalkerState = IDLE;
LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2;
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1;
@ -237,67 +254,65 @@ module pagetablewalker (
endcase
end
// unswizzle PTE bits
assign {Dirty, Accessed, Global, User,
Executable, Writable, Readable, Valid} = MMUReadPTE[7:0];
// A megapage is a Level 1 leaf page. This page must have zero PPN[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 LeafPTE = Executable | Writable | Readable;
assign ValidPTE = Valid && ~(Writable && ~Readable);
assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty);
assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
// *** Should translate this flop block into our flop module notation
always_ff @(posedge clk, negedge reset)
if (reset) begin
TranslationPAdr <= '0;
PageTableEntryF <= '0;
MMUTranslationComplete <= '0;
DTLBWriteM <= '0;
ITLBWriteF <= '0;
InstrPageFaultM <= '0;
LoadPageFaultM <= '0;
StorePageFaultM <= '0;
end else begin
// default values
TranslationPAdr <= '0;
PageTableEntryF <= '0;
MMUTranslationComplete <= '0;
DTLBWriteM <= '0;
ITLBWriteF <= '0;
InstrPageFaultM <= '0;
LoadPageFaultM <= '0;
StorePageFaultM <= '0;
case (NextWalkerState)
LEVEL2: begin
TranslationPAdr <= {BasePageTablePPN, VPN2, 3'b00};
end
LEVEL1: begin
TranslationPAdr <= {CurrentPPN, VPN1, 3'b00};
end
LEVEL0: begin
TranslationPAdr <= {CurrentPPN, VPN0, 3'b00};
end
LEAF: begin
PageTableEntryF <= MMUReadPTE;
PageTableEntryM <= MMUReadPTE;
MMUTranslationComplete <= '1;
DTLBWriteM <= DTLBMissM;
ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions
end
FAULT: begin
InstrPageFaultM <= ~DTLBMissM;
LoadPageFaultM <= DTLBMissM && ~MemWriteM;
StorePageFaultM <= DTLBMissM && MemWriteM;
end
endcase
end
assign VPN2 = TranslationVAdr[38:30];
assign VPN1 = TranslationVAdr[29:21];
assign VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset?
// Interpret inputs from ahblite
assign CurrentPPN = MMUReadPTE[53:10];
// *** Should translate this flop block into our flop module notation
always_comb begin
// default values
assign TranslationPAdr = '0;
assign PageTableEntryF = '0;
assign PageTableEntryM = '0;
assign MMUTranslationComplete = '0;
assign DTLBWriteM = '0;
assign ITLBWriteF = '0;
assign InstrPageFaultM = '0;
assign LoadPageFaultM = '0;
assign StorePageFaultM = '0;
case (NextWalkerState)
LEVEL2: begin
assign TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000};
end
LEVEL1: begin
assign TranslationPAdr = {CurrentPPN, VPN1, 3'b000};
end
LEVEL0: begin
assign TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
end
LEAF: begin
// Keep physical address alive to prevent HADDR dropping to 0
assign TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
assign PageTableEntryF = CurrentPTE;
assign PageTableEntryM = CurrentPTE;
assign MMUTranslationComplete = '1;
assign DTLBWriteM = DTLBMissM;
assign ITLBWriteF = ~DTLBMissM; // Prefer data over instructions
end
FAULT: begin
assign InstrPageFaultM = ~DTLBMissM;
assign LoadPageFaultM = DTLBMissM && ~MemStore;
assign StorePageFaultM = DTLBMissM && MemStore;
end
endcase
end
// Capture page table entry from ahblite
flopenr #(`XLEN) ptereg(HCLK, ~HRESETn, MMUReady, MMUReadPTE, SavedPTE);
// *** Evil hack to get CurrentPTE a cycle early before it is saved.
// Todo: Is it evil?
mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE);
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
// Assign outputs to ahblite
// *** Currently truncate address to 32 bits. This must be changed if

View File

@ -80,7 +80,7 @@ module ifu (
// logic [`XLEN-1:0] PageTableEntryF = '0;
logic ITLBFlushF = '0;
// logic ITLBWriteF = '0;
tlb #(3) itlb(clk, reset, SATP_REGW, PrivilegeModeW, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF,
tlb #(3) itlb(clk, reset, SATP_REGW, PrivilegeModeW, 1'b1, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF,
InstrPAdrF, ITLBMissF, ITLBHitF);
// branch predictor signals
@ -96,7 +96,6 @@ module ifu (
assign PrivilegedChangePCM = RetM | TrapM;
//mux3 #(`XLEN) pcmux(PCPlus2or4F, PCCorrectE, PrivilegedNextPCM, {PrivilegedChangePCM, BPPredWrongE}, UnalignedPCNextF);
mux2 #(`XLEN) pcmux0(.d0(PCPlus2or4F),
.d1(BPPredPCF),

View File

@ -63,6 +63,9 @@ module tlb #(parameter ENTRY_BITS = 3) (
// Current privilege level of the processeor
input [1:0] PrivilegeModeW,
// High if the TLB is currently being accessed
input TLBAccess,
// Virtual address input
input [`XLEN-1:0] VirtualAddress,
@ -82,6 +85,7 @@ module tlb #(parameter ENTRY_BITS = 3) (
logic SvMode;
logic Translate;
/*
generate
if (`XLEN == 32) begin
assign SvMode = SATP_REGW[31]; // *** change to an enum somehow?
@ -89,9 +93,10 @@ module tlb #(parameter ENTRY_BITS = 3) (
assign SvMode = SATP_REGW[63]; // currently just a boolean whether translation enabled
end
endgenerate
*/
// *** Currently fake virtual memory being on for testing purposes
// *** DO NOT ENABLE UNLESS TESTING
// assign SvMode = 1;
assign SvMode = 1;
assign Translate = SvMode & (PrivilegeModeW != `M_MODE);
@ -118,6 +123,8 @@ module tlb #(parameter ENTRY_BITS = 3) (
// Page table entry matching the virtual address
logic [`XLEN-1:0] PageTableEntry;
logic CAMHit;
assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12];
assign PageOffset = VirtualAddress[11:0];
@ -149,7 +156,8 @@ module tlb #(parameter ENTRY_BITS = 3) (
end
endgenerate
assign TLBMiss = ~TLBHit & ~(TLBWrite | TLBFlush) & Translate;
assign TLBHit = CAMHit & TLBAccess;
assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess;
endmodule
module tlb_ram #(parameter ENTRY_BITS = 3) (
@ -185,7 +193,7 @@ module tlb_cam #(parameter ENTRY_BITS = 3,
input TLBWrite,
input TLBFlush,
output [ENTRY_BITS-1:0] VPNIndex,
output TLBHit
output CAMHit
);
localparam NENTRIES = 2**ENTRY_BITS;
@ -220,7 +228,7 @@ module tlb_cam #(parameter ENTRY_BITS = 3,
end
assign VPNIndex = matched_address_comb;
assign TLBHit = match_found_comb & ~(TLBWrite | TLBFlush);
assign CAMHit = match_found_comb & ~TLBFlush;
initial begin
for (int i = 0; i < NENTRIES; i++)
@ -236,6 +244,6 @@ module tlb_rand #(parameter ENTRY_BITS = 3) (
logic [31:0] data;
assign data = $urandom;
assign WriteIndex = data[ENTRY_BITS:0];
assign WriteIndex = data[ENTRY_BITS-1:0];
endmodule

View File

@ -89,7 +89,7 @@ module csr (
assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM;
assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment
assign NextCauseM = TrapM ? CauseM : CSRWriteValM;
assign NextMtvalM = TrapM? NextFaultMtvalM : CSRWriteValM;
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
assign CSRMWriteM = CSRWriteM && (PrivilegeModeW == `M_MODE);
assign CSRSWriteM = CSRWriteM && (PrivilegeModeW[0]);
assign CSRUWriteM = CSRWriteM;

View File

@ -354,7 +354,7 @@ string tests32i[] = {
else tests = {tests, tests64iNOc};
if (`M_SUPPORTED) tests = {tests, tests64m};
if (`A_SUPPORTED) tests = {tests, tests64a};
//if (`MEM_VIRTMEM) tests = {tests, tests64mmu};
if (`MEM_VIRTMEM) tests = {tests, tests64mmu};
end
// tests = {tests64a, tests};
end else begin // RV32
@ -364,7 +364,7 @@ string tests32i[] = {
else tests = {tests, tests32iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
if (`A_SUPPORTED) tests = {tests, tests32a};
//if (`MEM_VIRTMEM) tests = {tests32mmu, tests};
if (`MEM_VIRTMEM) tests = {tests32mmu, tests};
end
string signame, memfilename;