mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
MMU produces page fault when upper bits aren't equal. Renamed input to MMU to be 'Address' and moved translation mux into MMU out of TLB
This commit is contained in:
parent
412691df2d
commit
032c38b7e7
@ -120,7 +120,7 @@ module ifu (
|
||||
endgenerate
|
||||
|
||||
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
|
||||
immu(.VirtualAddress(PCF),
|
||||
immu(.Address(PCF),
|
||||
.Size(2'b10),
|
||||
.PTE(PageTableEntryF),
|
||||
.PageTypeWriteVal(PageTypeF),
|
||||
|
@ -115,10 +115,6 @@ module lsu
|
||||
STATE_PTW_DONE} statetype;
|
||||
statetype CurrState, NextState;
|
||||
|
||||
|
||||
logic PMPInstrAccessFaultF, PMAInstrAccessFaultF; // *** these are just so that the mmu has somewhere to put these outputs since they aren't used in dmem
|
||||
// *** if you're allowed to parameterize outputs/ inputs existence, these are an easy delete.
|
||||
|
||||
logic DTLBMissM;
|
||||
logic [`XLEN-1:0] PageTableEntryM;
|
||||
logic [1:0] PageTypeM;
|
||||
@ -216,7 +212,7 @@ module lsu
|
||||
|
||||
|
||||
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
|
||||
dmmu(.VirtualAddress(MemAdrMtoLSU),
|
||||
dmmu(.Address(MemAdrMtoLSU),
|
||||
.Size(SizeToLSU[1:0]),
|
||||
.PTE(PageTableEntryM),
|
||||
.PageTypeWriteVal(PageTypeM),
|
||||
|
@ -44,8 +44,8 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries
|
||||
// 11 - TLB is accessed for both read and write
|
||||
input logic DisableTranslation,
|
||||
|
||||
// Virtual address input
|
||||
input logic [`XLEN-1:0] VirtualAddress,
|
||||
// address input (could be virtual or physical)
|
||||
input logic [`XLEN-1:0] Address,
|
||||
input logic [1:0] Size, // 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
@ -75,6 +75,8 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries
|
||||
|
||||
);
|
||||
|
||||
logic [`PA_BITS-1:0] TLBPhysicalAddress;
|
||||
logic [`XLEN+1:0] AddressExt;
|
||||
logic PMPSquashBusAccess, PMASquashBusAccess;
|
||||
logic Cacheable, Idempotent, AtomicAllowed; // *** here so that the pmachecker has somewhere to put these outputs. *** I'm leaving them as outputs to pma checker, but I'm stopping them here.
|
||||
// Translation lookaside buffer
|
||||
@ -82,6 +84,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries
|
||||
logic PMAInstrAccessFaultF, PMPInstrAccessFaultF;
|
||||
logic PMALoadAccessFaultM, PMPLoadAccessFaultM;
|
||||
logic PMAStoreAccessFaultM, PMPStoreAccessFaultM;
|
||||
logic Translate;
|
||||
|
||||
|
||||
// only instantiate TLB if Virtual Memory is supported
|
||||
@ -92,14 +95,16 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries
|
||||
assign WriteAccess = WriteAccessM;
|
||||
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.*);
|
||||
end else begin // just pass address through as physical
|
||||
logic [`XLEN+1:0] VAExt;
|
||||
assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32
|
||||
assign PhysicalAddress = VAExt[`PA_BITS-1:0];
|
||||
assign Translate = 0;
|
||||
assign TLBMiss = 0;
|
||||
assign TLBHit = 1;
|
||||
assign TLBHit = 1; // *** is this necessary
|
||||
assign TLBPageFault = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// If translation is occuring, select translated physical address from TLB
|
||||
assign AddressExt = {2'b00, Address}; // extend length of virtual address if necessary for RV32
|
||||
mux2 #(`PA_BITS) addressmux(AddressExt[`PA_BITS-1:0], TLBPhysicalAddress, Translate, PhysicalAddress);
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Check physical memory accesses
|
||||
|
@ -68,8 +68,8 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
input logic ReadAccess, WriteAccess,
|
||||
input logic DisableTranslation,
|
||||
|
||||
// Virtual address input
|
||||
input logic [`XLEN-1:0] VirtualAddress,
|
||||
// address input before translation (could be physical or virtual)
|
||||
input logic [`XLEN-1:0] Address,
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
input logic [`XLEN-1:0] PTE,
|
||||
@ -80,16 +80,15 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
input logic TLBFlush,
|
||||
|
||||
// Physical address outputs
|
||||
output logic [`PA_BITS-1:0] PhysicalAddress,
|
||||
output logic [`PA_BITS-1:0] TLBPhysicalAddress,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
output logic Translate,
|
||||
|
||||
// Faults
|
||||
output logic TLBPageFault
|
||||
);
|
||||
|
||||
logic Translate;
|
||||
|
||||
// Store current virtual memory mode (SV32, SV39, SV48, ect...)
|
||||
//logic [`SVMODE_BITS-1:0] SvMode;
|
||||
logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV
|
||||
@ -99,8 +98,7 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
// Sections of the virtual and physical addresses
|
||||
logic [`VPN_BITS-1:0] VirtualPageNumber;
|
||||
logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed;
|
||||
logic [`PA_BITS-1:0] PhysicalAddressFull;
|
||||
logic [`XLEN+1:0] VAExt;
|
||||
logic [`XLEN+1:0] AddressExt;
|
||||
|
||||
// Sections of the page table entry
|
||||
logic [7:0] PTEAccessBits;
|
||||
@ -116,7 +114,7 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
assign ASID = SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE];
|
||||
|
||||
// Determine whether to write TLB
|
||||
assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12];
|
||||
assign VirtualPageNumber = Address[`VPN_BITS+11:12];
|
||||
|
||||
tlbcontrol tlbcontrol(.*);
|
||||
|
||||
@ -134,7 +132,5 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
|
||||
// Output the hit physical address if translation is currently on.
|
||||
// Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal
|
||||
assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32
|
||||
mux2 #(`PA_BITS) hitmux('0, {PhysicalPageNumberMixed, VirtualAddress[11:0]}, TLBHit, PhysicalAddressFull); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
|
||||
mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress);
|
||||
mux2 #(`PA_BITS) hitmux('0, {PhysicalPageNumberMixed, Address[11:0]}, TLBHit, TLBPhysicalAddress); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
|
||||
endmodule
|
||||
|
@ -32,6 +32,7 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
||||
|
||||
// Current value of satp CSR (from privileged unit)
|
||||
input logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic [`XLEN-1:0] Address,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
||||
@ -58,7 +59,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
||||
logic [`SVMODE_BITS-1:0] SVMode;
|
||||
|
||||
logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R; // Useful PTE Control Bits
|
||||
logic DAFault;
|
||||
logic UpperBitsUnequalPageFault;
|
||||
logic DAPageFault;
|
||||
logic TLBAccess;
|
||||
|
||||
// Grab the sv mode from SATP and determine whether translation should occur
|
||||
@ -66,13 +68,27 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
||||
assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
|
||||
assign Translate = (SVMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation;
|
||||
generate
|
||||
if (`XLEN==64) assign SV39Mode = (SVMode == `SV39);
|
||||
else assign SV39Mode = 0;
|
||||
if (`XLEN==64) begin
|
||||
assign SV39Mode = (SVMode == `SV39);
|
||||
// generate page fault if upper bits aren't all the same
|
||||
logic UpperOnes39, UpperZeros39, UpperOnes48, UpperZeros48;
|
||||
assign UpperOnes39 = &(Address[63:39]);
|
||||
assign UpperZeros39 = ~|(Address[63:39]);
|
||||
assign UpperOnes48 = &(Address[63:48]);
|
||||
assign UpperZeros48 = ~|(Address[63:48]);
|
||||
assign UpperBitsUnequalPageFault = SV39Mode ? (Address[38] ? UpperOnes39 : UpperZeros39) : (Address[47] ? UpperOnes48 : UpperZeros48);
|
||||
end else begin
|
||||
assign SV39Mode = 0;
|
||||
assign UpperBitsUnequalPageFault = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Determine whether TLB is being used
|
||||
assign TLBAccess = ReadAccess || WriteAccess;
|
||||
|
||||
// Check whether upper bits of virtual addresss are all equal
|
||||
|
||||
|
||||
// unswizzle useful PTE bits
|
||||
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
||||
assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1];
|
||||
@ -87,8 +103,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) ||
|
||||
((EffectivePrivilegeMode == `S_MODE) && PTE_U);
|
||||
// fault for software handling if access bit is off
|
||||
assign DAFault = ~PTE_A;
|
||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAFault);
|
||||
assign DAPageFault = ~PTE_A;
|
||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAPageFault || UpperBitsUnequalPageFault);
|
||||
end else begin
|
||||
logic ImproperPrivilege, InvalidRead, InvalidWrite;
|
||||
|
||||
@ -104,8 +120,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
||||
// low.
|
||||
assign InvalidWrite = WriteAccess && ~PTE_W;
|
||||
// Fault for software handling if access bit is off or writing a page with dirty bit off
|
||||
assign DAFault = ~PTE_A | WriteAccess & ~PTE_D;
|
||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAFault);
|
||||
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
|
||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAPageFault || UpperBitsUnequalPageFault);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
@ -125,7 +125,8 @@ module csrsr (
|
||||
STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
||||
STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
||||
end else if (~StallW) begin
|
||||
if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else
|
||||
if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else;
|
||||
// *** also, FS_INT needs to be set when any bits of the fcsr are written
|
||||
if (TrapM) begin
|
||||
// Update interrupt enables per Privileged Spec p. 21
|
||||
// y = PrivilegeModeW
|
||||
|
Loading…
Reference in New Issue
Block a user