Initial implementation of SVNAPOT and SVPBMT does not break regression

This commit is contained in:
David Harris 2023-08-25 18:33:08 -07:00
parent 9f44241d0f
commit c07ad03f9d
14 changed files with 148 additions and 63 deletions

View File

@ -85,6 +85,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
input logic STATUS_MPRV, // Status CSR: modify machine privilege input logic STATUS_MPRV, // Status CSR: modify machine privilege
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
@ -170,7 +171,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign TLBFlush = sfencevmaM & ~StallMQ; assign TLBFlush = sfencevmaM & ~StallMQ;
mmu #(.P(P), .TLB_ENTRIES(P.ITLB_ENTRIES), .IMMU(1)) mmu #(.P(P), .TLB_ENTRIES(P.ITLB_ENTRIES), .IMMU(1))
immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
.PrivilegeModeW, .DisableTranslation(1'b0), .PrivilegeModeW, .DisableTranslation(1'b0),
.VAdr(PCFExt), .VAdr(PCFExt),
.Size(2'b10), .Size(2'b10),

View File

@ -80,6 +80,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
input logic [1:0] STATUS_MPP, // Machine previous privilege mode input logic [1:0] STATUS_MPP, // Machine previous privilege mode
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
@ -189,7 +190,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
assign DisableTranslation = SelHPTW | FlushDCacheM; assign DisableTranslation = SelHPTW | FlushDCacheM;
assign WriteAccessM = PreLSURWM[0] | (|CMOpM); assign WriteAccessM = PreLSURWM[0] | (|CMOpM);
mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0)) mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
.PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]), .PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
.PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM), .PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM),
.PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM), .PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM),

View File

@ -34,6 +34,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
input logic STATUS_MPRV, // Status CSR: modify machine privilege input logic STATUS_MPRV, // Status CSR: modify machine privilege
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
@ -70,6 +71,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
logic TLBHit; // Hit in TLB logic TLBHit; // Hit in TLB
logic TLBPageFault; // Page fault from TLB logic TLBPageFault; // Page fault from TLB
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
logic [1:0] PBMemoryType; // PBMT field of PTE during TLB hit, or 00 otherwise
// only instantiate TLB if Virtual Memory is supported // only instantiate TLB if Virtual Memory is supported
if (P.VIRTMEM_SUPPORTED) begin:tlb if (P.VIRTMEM_SUPPORTED) begin:tlb
@ -80,16 +82,17 @@ module mmu import cvw::*; #(parameter cvw_t P,
.clk, .reset, .clk, .reset,
.SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]), .SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]),
.SATP_ASID(SATP_REGW[P.ASID_BASE+P.ASID_BITS-1:P.ASID_BASE]), .SATP_ASID(SATP_REGW[P.ASID_BASE+P.ASID_BITS-1:P.ASID_BASE]),
.VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal, .DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.Translate, .TLBPageFault, .UpdateDA); .Translate, .TLBPageFault, .UpdateDA, .PBMemoryType);
end else begin:tlb // just pass address through as physical end else begin:tlb // just pass address through as physical
assign Translate = 0; assign Translate = 0;
assign TLBMiss = 0; assign TLBMiss = 0;
assign TLBHit = 1; // *** is this necessary assign TLBHit = 1; // *** is this necessary
assign TLBPageFault = 0; assign TLBPageFault = 0;
assign PBMemoryType = 2'b00;
end end
// If translation is occuring, select translated physical address from TLB // If translation is occuring, select translated physical address from TLB
@ -103,7 +106,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
/////////////////////////////////////////// ///////////////////////////////////////////
pmachecker #(P) pmachecker(.PhysicalAddress, .Size, pmachecker #(P) pmachecker(.PhysicalAddress, .Size,
.AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType,
.Cacheable, .Idempotent, .SelTIM, .Cacheable, .Idempotent, .SelTIM,
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM); .PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);

View File

@ -35,6 +35,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
input logic ExecuteAccessF, // Execute access input logic ExecuteAccessF, // Execute access
input logic WriteAccessM, // Write access input logic WriteAccessM, // Write access
input logic ReadAccessM, // Read access input logic ReadAccessM, // Read access
input logic [1:0] PBMemoryType, // PBMT field of PTE during TLB hit, or 00 otherwise
output logic Cacheable, Idempotent, SelTIM, output logic Cacheable, Idempotent, SelTIM,
output logic PMAInstrAccessFaultF, output logic PMAInstrAccessFaultF,
output logic PMALoadAccessFaultM, output logic PMALoadAccessFaultM,
@ -45,6 +46,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
logic AccessRW, AccessRWX, AccessRX; logic AccessRW, AccessRWX, AccessRX;
logic [10:0] SelRegions; logic [10:0] SelRegions;
logic AtomicAllowed; logic AtomicAllowed;
logic CacheableRegion, IdempotentRegion;
// Determine what type of access is being made // Determine what type of access is being made
assign AccessRW = ReadAccessM | WriteAccessM; assign AccessRW = ReadAccessM | WriteAccessM;
@ -54,11 +56,15 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
// Determine which region of physical memory (if any) is being accessed // Determine which region of physical memory (if any) is being accessed
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions); adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
// Only non-core RAM/ROM memory regions are cacheable // Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
assign Cacheable = SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-cachable assign CacheableRegion = SelRegions[8] | SelRegions[7] | SelRegions[6];
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0; // exclusion-tag: unused-cachable
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly // Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
// I/O is nonidempotent. // I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent
assign Idempotent = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-idempotent assign IdempotentRegion = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6];
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01); // exclusion-tag: unused-idempotent
// Atomic operations are only allowed on RAM // Atomic operations are only allowed on RAM
assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6]; // exclusion-tag: unused-atomic assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6]; // exclusion-tag: unused-atomic
// Check if tightly integrated memories are selected // Check if tightly integrated memories are selected

View File

@ -57,12 +57,13 @@ module tlb import cvw::*; #(parameter cvw_t P,
input logic [P.ASID_BITS-1:0] SATP_ASID, input logic [P.ASID_BITS-1:0] SATP_ASID,
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 ENVCFG_PBMTE, // Page-based memory types enabled
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic ReadAccess, input logic ReadAccess,
input logic WriteAccess, input logic WriteAccess,
input logic DisableTranslation, input logic DisableTranslation,
input logic [P.XLEN-1:0] VAdr, // address input before translation (could be physical or virtual) input logic [P.XLEN-1:0] VAdr, // address input before translation (could be physical or virtual)
input logic [P.XLEN-1:0] PTE, input logic [P.XLEN-1:0] PTE, // page table entry to write
input logic [1:0] PageTypeWriteVal, input logic [1:0] PageTypeWriteVal,
input logic TLBWrite, input logic TLBWrite,
input logic TLBFlush, input logic TLBFlush,
@ -71,10 +72,11 @@ module tlb import cvw::*; #(parameter cvw_t P,
output logic TLBHit, output logic TLBHit,
output logic Translate, output logic Translate,
output logic TLBPageFault, output logic TLBPageFault,
output logic UpdateDA output logic UpdateDA,
output logic [1:0] PBMemoryType // PBMT field of PTE during TLB hit, or 00 otherwise
); );
logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs, PTE_NAPOTs; // used as the one-hot encoding of WriteIndex
// Sections of the virtual and physical addresses // Sections of the virtual and physical addresses
logic [P.VPN_BITS-1:0] VPN; logic [P.VPN_BITS-1:0] VPN;
logic [P.PPN_BITS-1:0] PPN; logic [P.PPN_BITS-1:0] PPN;
@ -84,7 +86,9 @@ module tlb import cvw::*; #(parameter cvw_t P,
logic CAMHit; logic CAMHit;
logic SV39Mode; logic SV39Mode;
logic Misaligned; logic Misaligned;
logic BadPTEWrite; // trying to write malformed PTE
logic MegapageMisaligned; logic MegapageMisaligned;
logic PTE_N; // NAPOT page table entry
if(P.XLEN == 32) begin if(P.XLEN == 32) begin
assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0 assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0
@ -101,20 +105,28 @@ module tlb import cvw::*; #(parameter cvw_t P,
assign VPN = VAdr[P.VPN_BITS+11:12]; assign VPN = VAdr[P.VPN_BITS+11:12];
tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, // check if reserved, N, or PBMT bits are malformed when PTE is written in RV64
assign BadPTEWrite = (P.XLEN == 64) & TLBWrite & (
PTE[P.XLEN-1] & ~P.SVNAPOT_SUPPORTED | // N must be 0 if SVNAPOT is not supported
PTE[P.XLEN-2:P.XLEN-3] != 0 & ~P.SVPBMT_SUPPORTED | // PBMT must be 0 if SVBPMT is not supported
PTE[P.XLEN-2:P.XLEN-3] == 3 | // PBMT of 3 is reserved and never legal
PTE[P.XLEN-4:P.XLEN-10] != 0 ); // Reserved bits must be 0
tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush,
.PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault, .PTEAccessBits, .CAMHit, .Misaligned, .BadPTEWrite,
.UpdateDA, .SV39Mode, .Translate); .TLBMiss, .TLBHit, .TLBPageFault,
.UpdateDA, .SV39Mode, .Translate, .PTE_N, .PBMemoryType);
tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables);
tlbcam #(P, TLB_ENTRIES, P.VPN_BITS + P.ASID_BITS, P.VPN_SEGMENT_BITS) tlbcam #(P, TLB_ENTRIES, P.VPN_BITS + P.ASID_BITS, P.VPN_SEGMENT_BITS)
tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, .PTE_NAPOTs,
.SATP_ASID, .Matches, .HitPageType, .CAMHit); .SATP_ASID, .Matches, .HitPageType, .CAMHit);
tlbram #(P, TLB_ENTRIES) tlbram(.clk, .reset, .PTE, .Matches, .WriteEnables, .PPN, .PTEAccessBits, .PTE_Gs); tlbram #(P, TLB_ENTRIES) tlbram(.clk, .reset, .PTE, .Matches, .WriteEnables, .PPN, .PTEAccessBits, .PTE_Gs, .PTE_NAPOTs);
// Replace segments of the virtual page number with segments of the physical // Replace segments of the virtual page number with segments of the physical
// page number. For 4 KB pages, the entire virtual page number is replaced. // page number. For 4 KB pages, the entire virtual page number is replaced.
// For superpages, some segments are considered offsets into a larger page. // For superpages, some segments are considered offsets into a larger page.
tlbmixer #(P) Mixer(.VPN, .PPN, .HitPageType, .Offset(VAdr[11:0]), .TLBHit, .TLBPAdr); tlbmixer #(P) Mixer(.VPN, .PPN, .HitPageType, .Offset(VAdr[11:0]), .TLBHit, .PTE_N, .TLBPAdr);
endmodule endmodule

View File

@ -38,6 +38,7 @@ module tlbcam import cvw::*; #(parameter cvw_t P,
input logic TLBFlush, input logic TLBFlush,
input logic [TLB_ENTRIES-1:0] WriteEnables, input logic [TLB_ENTRIES-1:0] WriteEnables,
input logic [TLB_ENTRIES-1:0] PTE_Gs, input logic [TLB_ENTRIES-1:0] PTE_Gs,
input logic [TLB_ENTRIES-1:0] PTE_NAPOTs, // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000)
input logic [P.ASID_BITS-1:0] SATP_ASID, input logic [P.ASID_BITS-1:0] SATP_ASID,
output logic [TLB_ENTRIES-1:0] Matches, output logic [TLB_ENTRIES-1:0] Matches,
output logic [1:0] HitPageType, output logic [1:0] HitPageType,
@ -53,7 +54,7 @@ module tlbcam import cvw::*; #(parameter cvw_t P,
// page number segments. // page number segments.
tlbcamline #(P, KEY_BITS, SEGMENT_BITS) camlines[TLB_ENTRIES-1:0]( tlbcamline #(P, KEY_BITS, SEGMENT_BITS) camlines[TLB_ENTRIES-1:0](
.clk, .reset, .VPN, .SATP_ASID, .SV39Mode, .PTE_G(PTE_Gs), .PageTypeWriteVal, .TLBFlush, .clk, .reset, .VPN, .SATP_ASID, .SV39Mode, .PTE_G(PTE_Gs), .PTE_NAPOT(PTE_NAPOTs), .PageTypeWriteVal, .TLBFlush,
.WriteEnable(WriteEnables), .PageTypeRead, .Match(Matches)); .WriteEnable(WriteEnables), .PageTypeRead, .Match(Matches));
assign CAMHit = |Matches & ~TLBFlush; assign CAMHit = |Matches & ~TLBFlush;
or_rows #(TLB_ENTRIES,2) PageTypeOr(PageTypeRead, HitPageType); or_rows #(TLB_ENTRIES,2) PageTypeOr(PageTypeRead, HitPageType);

View File

@ -37,6 +37,7 @@ module tlbcamline import cvw::*; #(parameter cvw_t P,
input logic SV39Mode, input logic SV39Mode,
input logic WriteEnable, // Write a new entry to this line input logic WriteEnable, // Write a new entry to this line
input logic PTE_G, input logic PTE_G,
input logic PTE_NAPOT, // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000)
input logic [1:0] PageTypeWriteVal, input logic [1:0] PageTypeWriteVal,
input logic TLBFlush, // Flush this line (set valid to 0) input logic TLBFlush, // Flush this line (set valid to 0)
output logic [1:0] PageTypeRead, // *** should this be the stored version or the always updated one? output logic [1:0] PageTypeRead, // *** should this be the stored version or the always updated one?
@ -76,7 +77,7 @@ module tlbcamline import cvw::*; #(parameter cvw_t P,
end else begin: match end else begin: match
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3; logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
logic Match2, Match3; logic Match2, Match3, MatchNAPOT;
assign {Query3, Query2, Query1, Query0} = VPN; assign {Query3, Query2, Query1, Query0} = VPN;
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key; assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
@ -84,7 +85,9 @@ module tlbcamline import cvw::*; #(parameter cvw_t P,
// Calculate the actual match value based on the input vpn and the page type. // Calculate the actual match value based on the input vpn and the page type.
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
// should automatically match. // should automatically match.
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section // In Svnapot, if N bit is set and bottom 4 bits of PPN = 1000, then these bits don't need to match
assign MatchNAPOT = P.SVNAPOT_SUPPORTED & PTE_NAPOT & (Query0[SEGMENT_BITS-1:4] == Key0[SEGMENT_BITS-1:4]);
assign Match0 = (Query0 == Key0) | (PageType > 2'd0) | MatchNAPOT; // least significant section
assign Match1 = (Query1 == Key1) | (PageType > 2'd1); assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
assign Match2 = (Query2 == Key2) | (PageType > 2'd2); assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used

View File

@ -31,6 +31,7 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
input logic [P.XLEN-1:0] VAdr, input logic [P.XLEN-1:0] VAdr,
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 ENVCFG_PBMTE, // Page-based memory types enabled
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic ReadAccess, WriteAccess, input logic ReadAccess, WriteAccess,
input logic DisableTranslation, input logic DisableTranslation,
@ -38,22 +39,27 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
input logic [10:0] PTEAccessBits, input logic [10:0] PTEAccessBits,
input logic CAMHit, input logic CAMHit,
input logic Misaligned, input logic Misaligned,
input logic BadPTEWrite, // trying to write malformed PTE
output logic TLBMiss, output logic TLBMiss,
output logic TLBHit, output logic TLBHit,
output logic TLBPageFault, output logic TLBPageFault,
output logic UpdateDA, output logic UpdateDA,
output logic SV39Mode, output logic SV39Mode,
output logic Translate output logic Translate,
output logic PTE_N, // NAPOT page table entry
output logic [1:0] PBMemoryType // PBMT field of PTE during TLB hit, or 00 otherwise
); );
// Sections of the page table entry // Sections of the page table entry
logic [1:0] EffectivePrivilegeMode; logic [1:0] EffectivePrivilegeMode;
logic PTE_N, PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits
logic [1:0] PTE_PBMT; logic [1:0] PTE_PBMT;
logic UpperBitsUnequal; logic UpperBitsUnequal;
logic TLBAccess; logic TLBAccess;
logic ImproperPrivilege; logic ImproperPrivilege;
logic BadPBMT;
logic CausePageFault;
// Grab the sv mode from SATP and determine whether translation should occur // Grab the sv mode from SATP and determine whether translation should occur
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
@ -66,25 +72,28 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
vm64check #(P) vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal); vm64check #(P) vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal);
// unswizzle useful PTE bits // unswizzle useful PTE bits
assign PTE_N = PTEAccessBits[10] & P.SVNAPOT_SUPPORTED; assign PTE_N = PTEAccessBits[10];
assign PTE_PBMT = PTEAccessBits[9:8] & {2{P.SVPBMT_SUPPORTED}}; assign PTE_PBMT = PTEAccessBits[9:8];
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, PTE_V} = PTEAccessBits[4:0]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0];
// Page fault if PBMT is nonzero when SVPBMT is not supported and enabled
assign BadPBMT = PTE_PBMT != 0 & ~(P.SVPBMT_SUPPORTED & ENVCFG_PBMTE);
// Send PMA a 2-bit MemoryType that is PBMT during leaf page table accesses and 0 otherwise
assign PBMemoryType = PTE_PBMT & {2{Translate & TLBHit & P.SVPBMT_SUPPORTED}};
// Check whether the access is allowed, page faulting if not. // Check whether the access is allowed, page faulting if not.
if (ITLB == 1) begin:itlb // Instruction TLB fault checking if (ITLB == 1) begin:itlb // Instruction TLB fault checking
// User mode may only execute user mode pages, and supervisor mode may // User mode may only execute user mode pages, and supervisor mode may
// only execute non-user mode pages. // only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) | assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == P.S_MODE) & PTE_U); ((EffectivePrivilegeMode == P.S_MODE) & PTE_U);
if(P.SVADU_SUPPORTED) begin : hptwwrites assign CausePageFault = ImproperPrivilege | ~PTE_X | UpperBitsUnequal | BadPTEWrite | BadPBMT | Misaligned | ~PTE_V | (~PTE_A & P.SVADU_SUPPORTED);
assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault; assign TLBPageFault = Translate & TLBHit & CausePageFault;
assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequal | Misaligned | ~PTE_V); // Determine wheter to update DA bits
end else begin if(P.SVADU_SUPPORTED) assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault;
// fault for software handling if access bit is off else assign UpdateDA = ~PTE_A;
assign UpdateDA = ~PTE_A;
assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V);
end
end else begin:dtlb // Data TLB fault checking end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite; logic InvalidRead, InvalidWrite;

View File

@ -35,13 +35,14 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
input logic [1:0] HitPageType, input logic [1:0] HitPageType,
input logic [11:0] Offset, input logic [11:0] Offset,
input logic TLBHit, input logic TLBHit,
input logic PTE_N, // NAPOT page table entry
output logic [P.PA_BITS-1:0] TLBPAdr output logic [P.PA_BITS-1:0] TLBPAdr
); );
localparam EXTRA_BITS = P.PPN_BITS - P.VPN_BITS; localparam EXTRA_BITS = P.PPN_BITS - P.VPN_BITS;
logic [P.PPN_BITS-1:0] ZeroExtendedVPN; logic [P.PPN_BITS-1:0] ZeroExtendedVPN;
logic [P.PPN_BITS-1:0] PageNumberMask; logic [P.PPN_BITS-1:0] PageNumberMask;
logic [P.PPN_BITS-1:0] PPNMixed; logic [P.PPN_BITS-1:0] PPNMixed, PPNMixed2;
// produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages // produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages
if (P.XLEN == 32) if (P.XLEN == 32)
@ -57,11 +58,45 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
// merge low segments of VPN with high segments of PPN decided by the pagetype. // merge low segments of VPN with high segments of PPN decided by the pagetype.
assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN.
assign PPNMixed = PPN | ZeroExtendedVPN & PageNumberMask; // assign PPNMixed = PPN | ZeroExtendedVPN & PageNumberMask; // low bits of PPN are already zero
//mux2 #(1) mixmux[P.PPN_BITS-1:0](ZeroExtendedVPN, PPN, PageNumberMask, PPNMixed);
//assign PPNMixed = (ZeroExtendedVPN & ~PageNumberMask) | (PPN & PageNumberMask); // In Svnapot, when N=1, use bottom bits of VPN for contiugous translations
if (P.SVNAPOT_SUPPORTED) begin
// 64 KiB contiguous NAPOT translations suported
logic [3:0] PPNMixedBot;
mux2 #(4) napotmux(PPNMixed[3:0], VPN, PTE_N, PPNMixedBot);
assign PPNMixed2 = {PPNMixed[P.PPN_BITS-1:4], PPNMixedBot};
/* // Generalized NAPOT implementation supporting various sized contiguous regions
// This would also require a priority encoder in the tlbcam
// Not yet tested
logic [8:0] NAPOTMask, NAPOTPN, PPNMixedBot;
always_comb begin
casez(PPN[8:0])
9'b100000000: NAPOTMask = 9'b111111111;
9'b?10000000: NAPOTMask = 9'b011111111;
9'b??1000000: NAPOTMask = 9'b001111111;
9'b???100000: NAPOTMask = 9'b000111111;
9'b????10000: NAPOTMask = 9'b000011111;
9'b?????1000: NAPOTMask = 9'b000001111;
9'b??????100: NAPOTMask = 9'b000000111;
9'b???????10: NAPOTMask = 9'b000000011;
9'b????????1: NAPOTMask = 9'b000000001;
default: NAPOTMask = 9'b000000000;
endcase
end
// check malformed NAPOT PPN, which should cause page fault
// Replace PPN with VPN in lower bits of page number based on mask
assign NAPOTPN = VPN & NAPOTMask | PPN & ~NAPOTMask;
mux2 #(9) napotmux(PPNMixed[8:0], NAPOTPN, PTE_N, PPNMixedBot);
assign PPNMixed2 = {PPNMixed[PPN_BITS-1:9], PPNMixedBot}; */
end else begin // no Svnapot
assign PPNMixed2 = PPNMixed;
end
// 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
mux2 #(P.PA_BITS) hitmux('0, {PPNMixed, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system mux2 #(P.PA_BITS) hitmux('0, {PPNMixed2, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
endmodule endmodule

View File

@ -36,19 +36,20 @@ module tlbram import cvw::*; #(parameter cvw_t P,
input logic [TLB_ENTRIES-1:0] Matches, WriteEnables, input logic [TLB_ENTRIES-1:0] Matches, WriteEnables,
output logic [P.PPN_BITS-1:0] PPN, output logic [P.PPN_BITS-1:0] PPN,
output logic [10:0] PTEAccessBits, output logic [10:0] PTEAccessBits,
output logic [TLB_ENTRIES-1:0] PTE_Gs output logic [TLB_ENTRIES-1:0] PTE_Gs,
output logic [TLB_ENTRIES-1:0] PTE_NAPOTs // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000)
); );
logic [P.XLEN-1:0] RamRead[TLB_ENTRIES-1:0]; // stores the page table entries logic [P.XLEN-1:0] RamRead[TLB_ENTRIES-1:0]; // stores the page table entries
logic [P.XLEN-1:0] PageTableEntry; logic [P.XLEN-1:0] PageTableEntry;
// RAM implemented with array of flops and AND/OR read logic // RAM implemented with array of flops and AND/OR read logic
tlbramline #(P.XLEN) tlbramline[TLB_ENTRIES-1:0] tlbramline #(P) tlbramline[TLB_ENTRIES-1:0]
(.clk, .reset, .re(Matches), .we(WriteEnables), (.clk, .reset, .re(Matches), .we(WriteEnables),
.d(PTE), .q(RamRead), .PTE_G(PTE_Gs)); .d(PTE), .q(RamRead), .PTE_G(PTE_Gs), .PTE_NAPOT(PTE_NAPOTs));
or_rows #(TLB_ENTRIES, P.XLEN) PTEOr(RamRead, PageTableEntry); or_rows #(TLB_ENTRIES, P.XLEN) PTEOr(RamRead, PageTableEntry);
// Rename the bits read from the TLB RAM // Rename the bits read from the TLB RAM
assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3], PageTableEntry[7:0]}; // include N and PBMT bits assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3] & {3{P.XLEN == 64}}, PageTableEntry[7:0]}; // include N and PBMT bits
assign PPN = PageTableEntry[P.PPN_BITS+9:10]; assign PPN = PageTableEntry[P.PPN_BITS+9:10];
endmodule endmodule

View File

@ -26,16 +26,26 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module tlbramline #(parameter WIDTH = 22) module tlbramline import cvw::*; #(parameter cvw_t P)
(input logic clk, reset, (input logic clk, reset,
input logic re, we, input logic re, we,
input logic [WIDTH-1:0] d, input logic [P.XLEN-1:0] d,
output logic [WIDTH-1:0] q, output logic [P.XLEN-1:0] q,
output logic PTE_G); output logic PTE_G,
output logic PTE_NAPOT // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000)
);
logic [WIDTH-1:0] line; logic [P.XLEN-1:0] line;
if (P.XLEN == 64) begin // save 7 reserved bits
// could optimize out N and PBMT from d[63:61] if they aren't supported
logic [56:0] ptereg;
flopenr #(57) pteflop(clk, reset, we, {d[63:61], d[53:0]}, ptereg);
assign line = {ptereg[56:54], 7'b0, ptereg[53:0]};
end else // rv32
flopenr #(P.XLEN) pteflop(clk, reset, we, d, line);
flopenr #(WIDTH) pteflop(clk, reset, we, d, line);
assign q = re ? line : 0; assign q = re ? line : 0;
assign PTE_G = line[5]; // send global bit to CAM as part of ASID matching assign PTE_G = line[5]; // send global bit to CAM as part of ASID matching
assign PTE_NAPOT = P.SVNAPOT_SUPPORTED & line[P.XLEN-1] & (line[13:10] == 4'b1000); // send NAPOT bit to CAM as part of matching lsbs of VPN
endmodule endmodule

View File

@ -85,6 +85,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output logic [2:0] FRM_REGW, output logic [2:0] FRM_REGW,
output logic [3:0] ENVCFG_CBE, output logic [3:0] ENVCFG_CBE,
output logic ENVCFG_PBMTE, // Page-based memory type enable
// //
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
@ -127,7 +128,6 @@ module csr import cvw::*; #(parameter cvw_t P) (
logic [63:0] MENVCFG_REGW; logic [63:0] MENVCFG_REGW;
logic [P.XLEN-1:0] SENVCFG_REGW; logic [P.XLEN-1:0] SENVCFG_REGW;
logic ENVCFG_STCE; // supervisor timer counter enable logic ENVCFG_STCE; // supervisor timer counter enable
logic ENVCFG_PBMTE; // page-based memory types enable
logic ENVCFG_FIOM; // fence implies io (presently not used) logic ENVCFG_FIOM; // fence implies io (presently not used)
// only valid unflushed instructions can access CSRs // only valid unflushed instructions can access CSRs

View File

@ -83,6 +83,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
output logic [2:0] FRM_REGW, // FPU rounding mode output logic [2:0] FRM_REGW, // FPU rounding mode
output logic [3:0] ENVCFG_CBE, // Cache block operation enables output logic [3:0] ENVCFG_CBE, // Cache block operation enables
output logic ENVCFG_PBMTE, // Page-based memory type enable
// PC logic output in privileged unit // PC logic output in privileged unit
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
// control outputs // control outputs
@ -137,7 +138,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS, .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS,
.MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW,
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE,
.CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM); .CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM);
// pipeline early-arriving trap sources // pipeline early-arriving trap sources

View File

@ -78,6 +78,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD; logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW; logic SquashSCW;
logic MDUActiveE; // Mul/Div instruction being executed logic MDUActiveE; // Mul/Div instruction being executed
logic ENVCFG_PBMTE; // Page-based memory type enable
logic [3:0] ENVCFG_CBE; // Cache Block operation enables logic [3:0] ENVCFG_CBE; // Cache Block operation enables
logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
logic IFUPrefetchE, LSUPrefetchM; // instruction / data prefetch hints logic IFUPrefetchE, LSUPrefetchM; // instruction / data prefetch hints
@ -184,7 +185,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM, .IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM,
// mmu management // mmu management
.PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV,
.STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF, .STATUS_MPP, .ENVCFG_PBMTE, .ITLBWriteF, .sfencevmaM, .ITLBMissF,
// pmp/pma (inside mmu) signals. // pmp/pma (inside mmu) signals.
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF);
@ -232,6 +233,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.STATUS_SUM, // from csr .STATUS_SUM, // from csr
.STATUS_MPRV, // from csr .STATUS_MPRV, // from csr
.STATUS_MPP, // from csr .STATUS_MPP, // from csr
.ENVCFG_PBMTE, // from csr
.sfencevmaM, // connects to privilege .sfencevmaM, // connects to privilege
.DCacheStallM, // connects to privilege .DCacheStallM, // connects to privilege
.LoadPageFaultM, // connects to privilege .LoadPageFaultM, // connects to privilege
@ -294,7 +296,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.PrivilegeModeW, .SATP_REGW, .PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW, .ENVCFG_CBE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
end else begin end else begin
assign CSRReadValW = 0; assign CSRReadValW = 0;
assign UnalignedPCNextF = PC2NextF; assign UnalignedPCNextF = PC2NextF;