forked from Github_Repos/cvw
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
|
endgenerate
|
||||||
|
|
||||||
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
|
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
|
||||||
immu(.VirtualAddress(PCF),
|
immu(.Address(PCF),
|
||||||
.Size(2'b10),
|
.Size(2'b10),
|
||||||
.PTE(PageTableEntryF),
|
.PTE(PageTableEntryF),
|
||||||
.PageTypeWriteVal(PageTypeF),
|
.PageTypeWriteVal(PageTypeF),
|
||||||
|
@ -115,10 +115,6 @@ module lsu
|
|||||||
STATE_PTW_DONE} statetype;
|
STATE_PTW_DONE} statetype;
|
||||||
statetype CurrState, NextState;
|
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 DTLBMissM;
|
||||||
logic [`XLEN-1:0] PageTableEntryM;
|
logic [`XLEN-1:0] PageTableEntryM;
|
||||||
logic [1:0] PageTypeM;
|
logic [1:0] PageTypeM;
|
||||||
@ -216,7 +212,7 @@ module lsu
|
|||||||
|
|
||||||
|
|
||||||
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
|
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
|
||||||
dmmu(.VirtualAddress(MemAdrMtoLSU),
|
dmmu(.Address(MemAdrMtoLSU),
|
||||||
.Size(SizeToLSU[1:0]),
|
.Size(SizeToLSU[1:0]),
|
||||||
.PTE(PageTableEntryM),
|
.PTE(PageTableEntryM),
|
||||||
.PageTypeWriteVal(PageTypeM),
|
.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
|
// 11 - TLB is accessed for both read and write
|
||||||
input logic DisableTranslation,
|
input logic DisableTranslation,
|
||||||
|
|
||||||
// Virtual address input
|
// address input (could be virtual or physical)
|
||||||
input logic [`XLEN-1:0] VirtualAddress,
|
input logic [`XLEN-1:0] Address,
|
||||||
input logic [1:0] Size, // 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
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
|
// 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 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.
|
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
|
// Translation lookaside buffer
|
||||||
@ -82,6 +84,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries
|
|||||||
logic PMAInstrAccessFaultF, PMPInstrAccessFaultF;
|
logic PMAInstrAccessFaultF, PMPInstrAccessFaultF;
|
||||||
logic PMALoadAccessFaultM, PMPLoadAccessFaultM;
|
logic PMALoadAccessFaultM, PMPLoadAccessFaultM;
|
||||||
logic PMAStoreAccessFaultM, PMPStoreAccessFaultM;
|
logic PMAStoreAccessFaultM, PMPStoreAccessFaultM;
|
||||||
|
logic Translate;
|
||||||
|
|
||||||
|
|
||||||
// only instantiate TLB if Virtual Memory is supported
|
// 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;
|
assign WriteAccess = WriteAccessM;
|
||||||
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.*);
|
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.*);
|
||||||
end else begin // just pass address through as physical
|
end else begin // just pass address through as physical
|
||||||
logic [`XLEN+1:0] VAExt;
|
assign Translate = 0;
|
||||||
assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32
|
|
||||||
assign PhysicalAddress = VAExt[`PA_BITS-1:0];
|
|
||||||
assign TLBMiss = 0;
|
assign TLBMiss = 0;
|
||||||
assign TLBHit = 1;
|
assign TLBHit = 1; // *** is this necessary
|
||||||
assign TLBPageFault = 0;
|
assign TLBPageFault = 0;
|
||||||
end
|
end
|
||||||
endgenerate
|
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
|
// Check physical memory accesses
|
||||||
|
@ -68,8 +68,8 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
|||||||
input logic ReadAccess, WriteAccess,
|
input logic ReadAccess, WriteAccess,
|
||||||
input logic DisableTranslation,
|
input logic DisableTranslation,
|
||||||
|
|
||||||
// Virtual address input
|
// address input before translation (could be physical or virtual)
|
||||||
input logic [`XLEN-1:0] VirtualAddress,
|
input logic [`XLEN-1:0] Address,
|
||||||
|
|
||||||
// Controls for writing a new entry to the TLB
|
// Controls for writing a new entry to the TLB
|
||||||
input logic [`XLEN-1:0] PTE,
|
input logic [`XLEN-1:0] PTE,
|
||||||
@ -80,16 +80,15 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
|||||||
input logic TLBFlush,
|
input logic TLBFlush,
|
||||||
|
|
||||||
// Physical address outputs
|
// Physical address outputs
|
||||||
output logic [`PA_BITS-1:0] PhysicalAddress,
|
output logic [`PA_BITS-1:0] TLBPhysicalAddress,
|
||||||
output logic TLBMiss,
|
output logic TLBMiss,
|
||||||
output logic TLBHit,
|
output logic TLBHit,
|
||||||
|
output logic Translate,
|
||||||
|
|
||||||
// Faults
|
// Faults
|
||||||
output logic TLBPageFault
|
output logic TLBPageFault
|
||||||
);
|
);
|
||||||
|
|
||||||
logic Translate;
|
|
||||||
|
|
||||||
// Store current virtual memory mode (SV32, SV39, SV48, ect...)
|
// Store current virtual memory mode (SV32, SV39, SV48, ect...)
|
||||||
//logic [`SVMODE_BITS-1:0] SvMode;
|
//logic [`SVMODE_BITS-1:0] SvMode;
|
||||||
logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV
|
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
|
// Sections of the virtual and physical addresses
|
||||||
logic [`VPN_BITS-1:0] VirtualPageNumber;
|
logic [`VPN_BITS-1:0] VirtualPageNumber;
|
||||||
logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed;
|
logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed;
|
||||||
logic [`PA_BITS-1:0] PhysicalAddressFull;
|
logic [`XLEN+1:0] AddressExt;
|
||||||
logic [`XLEN+1:0] VAExt;
|
|
||||||
|
|
||||||
// Sections of the page table entry
|
// Sections of the page table entry
|
||||||
logic [7:0] PTEAccessBits;
|
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];
|
assign ASID = SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE];
|
||||||
|
|
||||||
// Determine whether to write TLB
|
// Determine whether to write TLB
|
||||||
assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12];
|
assign VirtualPageNumber = Address[`VPN_BITS+11:12];
|
||||||
|
|
||||||
tlbcontrol tlbcontrol(.*);
|
tlbcontrol tlbcontrol(.*);
|
||||||
|
|
||||||
@ -134,7 +132,5 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
|||||||
|
|
||||||
// Output the hit physical address if translation is currently on.
|
// 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
|
// 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, Address[11:0]}, TLBHit, TLBPhysicalAddress); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
|
||||||
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);
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -32,6 +32,7 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
|||||||
|
|
||||||
// Current value of satp CSR (from privileged unit)
|
// Current value of satp CSR (from privileged unit)
|
||||||
input logic [`XLEN-1:0] SATP_REGW,
|
input logic [`XLEN-1:0] SATP_REGW,
|
||||||
|
input logic [`XLEN-1:0] Address,
|
||||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
input logic [1:0] STATUS_MPP,
|
input logic [1:0] STATUS_MPP,
|
||||||
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
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 [`SVMODE_BITS-1:0] SVMode;
|
||||||
|
|
||||||
logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R; // Useful PTE Control Bits
|
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;
|
logic TLBAccess;
|
||||||
|
|
||||||
// Grab the sv mode from SATP and determine whether translation should occur
|
// 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 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;
|
assign Translate = (SVMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation;
|
||||||
generate
|
generate
|
||||||
if (`XLEN==64) assign SV39Mode = (SVMode == `SV39);
|
if (`XLEN==64) begin
|
||||||
else assign SV39Mode = 0;
|
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
|
endgenerate
|
||||||
|
|
||||||
// Determine whether TLB is being used
|
// Determine whether TLB is being used
|
||||||
assign TLBAccess = ReadAccess || WriteAccess;
|
assign TLBAccess = ReadAccess || WriteAccess;
|
||||||
|
|
||||||
|
// Check whether upper bits of virtual addresss are all equal
|
||||||
|
|
||||||
|
|
||||||
// unswizzle useful PTE bits
|
// unswizzle useful PTE bits
|
||||||
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
||||||
assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1];
|
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) ||
|
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) ||
|
||||||
((EffectivePrivilegeMode == `S_MODE) && PTE_U);
|
((EffectivePrivilegeMode == `S_MODE) && PTE_U);
|
||||||
// fault for software handling if access bit is off
|
// fault for software handling if access bit is off
|
||||||
assign DAFault = ~PTE_A;
|
assign DAPageFault = ~PTE_A;
|
||||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAFault);
|
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAPageFault || UpperBitsUnequalPageFault);
|
||||||
end else begin
|
end else begin
|
||||||
logic ImproperPrivilege, InvalidRead, InvalidWrite;
|
logic ImproperPrivilege, InvalidRead, InvalidWrite;
|
||||||
|
|
||||||
@ -104,8 +120,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8,
|
|||||||
// low.
|
// low.
|
||||||
assign InvalidWrite = WriteAccess && ~PTE_W;
|
assign InvalidWrite = WriteAccess && ~PTE_W;
|
||||||
// Fault for software handling if access bit is off or writing a page with dirty bit off
|
// 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 DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
|
||||||
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAFault);
|
assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAPageFault || UpperBitsUnequalPageFault);
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
@ -125,7 +125,8 @@ module csrsr (
|
|||||||
STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
||||||
STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
||||||
end else if (~StallW) begin
|
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
|
if (TrapM) begin
|
||||||
// Update interrupt enables per Privileged Spec p. 21
|
// Update interrupt enables per Privileged Spec p. 21
|
||||||
// y = PrivilegeModeW
|
// y = PrivilegeModeW
|
||||||
|
Loading…
Reference in New Issue
Block a user