Partial parameterization into mmu.

This commit is contained in:
Ross Thompson 2023-05-24 16:12:41 -05:00
parent 5f5f33787d
commit fcb1c63f5f
5 changed files with 130 additions and 135 deletions

View File

@ -170,7 +170,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
flopr #(1) StallMReg(.clk, .reset, .d(StallM), .q(StallMQ)); flopr #(1) StallMReg(.clk, .reset, .d(StallM), .q(StallMQ));
assign TLBFlush = sfencevmaM & ~StallMQ; assign TLBFlush = sfencevmaM & ~StallMQ;
mmu #(.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,
.PrivilegeModeW, .DisableTranslation(1'b0), .PrivilegeModeW, .DisableTranslation(1'b0),
.VAdr(PCFExt), .VAdr(PCFExt),

View File

@ -29,9 +29,7 @@
// and limitations under the License. // and limitations under the License.
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module lsu import cvw::*; #(parameter cvw_t P) (
module lsu (
input logic clk, reset, input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW, input logic StallM, FlushM, StallW, FlushW,
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
@ -46,17 +44,17 @@ module lsu (
output logic DCacheMiss, // D cache miss for performance counters output logic DCacheMiss, // D cache miss for performance counters
output logic DCacheAccess, // D cache memory access for performance counters output logic DCacheAccess, // D cache memory access for performance counters
// address and write data // address and write data
input logic [`XLEN-1:0] IEUAdrE, // Execution stage memory address input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
output logic [`XLEN-1:0] IEUAdrM, // Memory stage memory address output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
input logic [`XLEN-1:0] WriteDataM, // Write data from IEU input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
output logic [`LLEN-1:0] ReadDataW, // Read data to IEU or FPU output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
// cpu privilege // cpu privilege
input logic [1:0] PrivilegeModeW, // Current privilege mode input logic [1:0] PrivilegeModeW, // Current privilege mode
input logic BigEndianM, // Swap byte order to big endian input logic BigEndianM, // Swap byte order to big endian
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic DCacheStallM, // D$ busy with multicycle operation output logic DCacheStallM, // D$ busy with multicycle operation
// fpu // fpu
input logic [`FLEN-1:0] FWriteDataM, // Write data from FPU input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
input logic FpLoadStoreM, // Selects FPU as store for write data input logic FpLoadStoreM, // Selects FPU as store for write data
// faults // faults
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
@ -67,34 +65,34 @@ module lsu (
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
output logic StoreAmoAccessFaultM, // Store or AMO access fault output logic StoreAmoAccessFaultM, // Store or AMO access fault
// connect to ahb // connect to ahb
output logic [`PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
input logic [`XLEN-1:0] HRDATA, // Bus read data from LSU to EBU input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
output logic [`XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
input logic LSUHREADY, // Bus ready from LSU to EBU input logic LSUHREADY, // Bus ready from LSU to EBU
output logic LSUHWRITE, // Bus write operation from LSU to EBU output logic LSUHWRITE, // Bus write operation from LSU to EBU
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
output logic [`XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
// page table walker // page table walker
input logic [`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 [`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
output logic [`XLEN-1:0] PTE, // Page table entry write to ITLB output logic [P.XLEN-1:0] PTE, // Page table entry write to ITLB
output logic [1:0] PageType, // Type of page table entry to write to ITLB output logic [1:0] PageType, // Type of page table entry to write to ITLB
output logic ITLBWriteF, // Write PTE to ITLB output logic ITLBWriteF, // Write PTE to ITLB
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // PMP address from privileged unit input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
); );
logic [`XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer logic [P.XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`PA_BITS-1:0] PAdrM; // Physical memory address logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
logic [`XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
@ -111,19 +109,19 @@ module lsu (
logic BusCommittedM; // Bus memory operation in flight, delay interrupts logic BusCommittedM; // Bus memory operation in flight, delay interrupts
logic DCacheCommittedM; // D$ memory operation started, delay interrupts logic DCacheCommittedM; // D$ memory operation started, delay interrupts
logic [`LLEN-1:0] DTIMReadDataWordM; // DTIM read data logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
logic [`LLEN-1:0] DCacheReadDataWordM; // D$ read data logic [P.LLEN-1:0] DCacheReadDataWordM; // D$ read data
logic [`LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data logic [P.LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data
logic [`LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data logic [P.LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data
logic [`LLEN-1:0] ReadDataWordM; // Read data before subword selection logic [P.LLEN-1:0] ReadDataWordM; // Read data before subword selection
logic [`LLEN-1:0] ReadDataM; // Final read data logic [P.LLEN-1:0] ReadDataM; // Final read data
logic [`XLEN-1:0] IHWriteDataM; // IEU or HPTW write data logic [P.XLEN-1:0] IHWriteDataM; // IEU or HPTW write data
logic [`XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data logic [P.XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data
logic [`LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data logic [P.LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data
logic [`LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data logic [P.LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data
logic [`LLEN-1:0] LSUWriteDataM; // Final write data logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
logic [(`LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
logic DTLBMissM; // DTLB miss causes HPTW walk logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB logic DTLBWriteM; // Writes PTE and PageType to DTLB
@ -140,7 +138,7 @@ module lsu (
// Zero-extend address to 34 bits for XLEN=32 // Zero-extend address to 34 bits for XLEN=32
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM); flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
assign IEUAdrExtM = {2'b00, IEUAdrM}; assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE}; assign IEUAdrExtE = {2'b00, IEUAdrE};
@ -149,12 +147,12 @@ module lsu (
// MMU include PMP and is needed if any privileged supported // MMU include PMP and is needed if any privileged supported
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
if(`VIRTMEM_SUPPORTED) begin : hptw if(P.VIRTMEM_SUPPORTED) begin : hptw
hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, hptw #(P) hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM, .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM,
.FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF, .FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN .ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
.WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M, .WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
.IHAdrM, .HPTWStall, .SelHPTW, .IHAdrM, .HPTWStall, .SelHPTW,
@ -184,10 +182,10 @@ module lsu (
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// MMU and misalignment fault logic required if privileged unit exists // MMU and misalignment fault logic required if privileged unit exists
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
if(`ZICSR_SUPPORTED == 1) begin : dmmu if(P.ZICSR_SUPPORTED == 1) begin : dmmu
logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation
assign DisableTranslation = SelHPTW | FlushDCacheM; assign DisableTranslation = SelHPTW | FlushDCacheM;
mmu #(.TLB_ENTRIES(`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,
.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),
@ -204,9 +202,9 @@ module lsu (
end else begin // No MMU, so no PMA/page faults and no address translation end else begin // No MMU, so no PMA/page faults and no address translation
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0; assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
assign {LoadPageFaultM, StoreAmoPageFaultM} = '0; assign {LoadPageFaultM, StoreAmoPageFaultM} = '0;
assign PAdrM = IHAdrM[`PA_BITS-1:0]; assign PAdrM = IHAdrM[P.PA_BITS-1:0];
assign CacheableM = 1'b1; assign CacheableM = 1'b1;
assign SelDTIM = `DTIM_SUPPORTED & ~`BUS_SUPPORTED; // if no PMA then select dtim if there is a DTIM. If there is assign SelDTIM = P.DTIM_SUPPORTED & ~P.BUS_SUPPORTED; // if no PMA then select dtim if there is a DTIM. If there is
// a bus then this is always 0. Cannot have both without PMA. // a bus then this is always 0. Cannot have both without PMA.
end end
@ -222,31 +220,31 @@ module lsu (
// Discard memory request on pipeline flush // Discard memory request on pipeline flush
assign IgnoreRequest = IgnoreRequestTLB | FlushW; assign IgnoreRequest = IgnoreRequestTLB | FlushW;
if (`DTIM_SUPPORTED) begin : dtim if (P.DTIM_SUPPORTED) begin : dtim
logic [`PA_BITS-1:0] DTIMAdr; logic [P.PA_BITS-1:0] DTIMAdr;
logic [1:0] DTIMMemRWM; logic [1:0] DTIMMemRWM;
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory. // The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
mux2 #(`PA_BITS) DTIMAdrMux(IEUAdrExtE[`PA_BITS-1:0], IEUAdrExtM[`PA_BITS-1:0], MemRWM[0], DTIMAdr); mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0; assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length. // **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point. // **** create config to support DTIM with floating point.
dtim dtim(.clk, .ce(~GatedStallW), .MemRWM(DTIMMemRWM), dtim dtim(.clk, .ce(~GatedStallW), .MemRWM(DTIMMemRWM),
.DTIMAdr, .FlushW, .WriteDataM(LSUWriteDataM), .DTIMAdr, .FlushW, .WriteDataM(LSUWriteDataM),
.ReadDataWordM(DTIMReadDataWordM[`XLEN-1:0]), .ByteMaskM(ByteMaskM[`XLEN/8-1:0])); .ReadDataWordM(DTIMReadDataWordM[P.XLEN-1:0]), .ByteMaskM(ByteMaskM[P.XLEN/8-1:0]));
end else begin end else begin
end end
if (`BUS_SUPPORTED) begin : bus if (P.BUS_SUPPORTED) begin : bus
if(`DCACHE_SUPPORTED) begin : dcache if(P.DCACHE_SUPPORTED) begin : dcache
localparam LLENWORDSPERLINE = `DCACHE_LINELENINBITS/`LLEN; // Number of LLEN words in cacheline localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^ localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
localparam BEATSPERLINE = `DCACHE_LINELENINBITS/`AHBW; // Number of AHBW words (beats) in cacheline localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^ localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
localparam LINELEN = `DCACHE_LINELENINBITS; // Number of bits in cacheline localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
localparam LLENPOVERAHBW = `LLEN / `AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation) localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
logic [`PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback. logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
@ -263,8 +261,8 @@ module lsu (
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0; assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0;
assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW); assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW);
cache #(.PA_BITS(`PA_BITS), .XLEN(`XLEN), .LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN), cache #(.PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`LLEN), .READ_ONLY_CACHE(0)) dcache( .NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(P.LLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
.clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM), .clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM),
.FlushCache(FlushDCache), .NextSet(IEUAdrE[11:0]), .PAdr(PAdrM), .FlushCache(FlushDCache), .NextSet(IEUAdrE[11:0]), .PAdr(PAdrM),
.ByteMask(ByteMaskM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]), .ByteMask(ByteMaskM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
@ -275,7 +273,7 @@ module lsu (
.FetchBuffer, .CacheBusRW, .FetchBuffer, .CacheBusRW,
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0)); .CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0));
ahbcacheinterface #(.AHBW(`AHBW), .LLEN(`LLEN), .PA_BITS(`PA_BITS), .BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW), .READ_ONLY_CACHE(0)) ahbcacheinterface( ahbcacheinterface #(.AHBW(P.AHBW), .LLEN(P.LLEN), .PA_BITS(P.PA_BITS), .BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW), .READ_ONLY_CACHE(0)) ahbcacheinterface(
.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HCLK(clk), .HRESETn(~reset), .Flush(FlushW),
.HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB), .HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB),
.HSIZE(LSUHSIZE), .HBURST(LSUHBURST), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HREADY(LSUHREADY), .HSIZE(LSUHSIZE), .HBURST(LSUHBURST), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HREADY(LSUHREADY),
@ -289,25 +287,25 @@ module lsu (
// Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times. // Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times.
// *** DTIMReadDataWordM should be increased to LLEN. // *** DTIMReadDataWordM should be increased to LLEN.
// pma should generate exception for LLEN read to periph. // pma should generate exception for LLEN read to periph.
mux3 #(`LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[`XLEN-1:0]}}), mux3 #(P.LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[P.XLEN-1:0]}}),
.d2({{`LLEN-`XLEN{1'b0}}, DTIMReadDataWordM[`XLEN-1:0]}), .d2({{P.LLEN-P.XLEN{1'b0}}, DTIMReadDataWordM[P.XLEN-1:0]}),
.s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM)); .s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM));
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
logic [`XLEN-1:0] FetchBuffer; logic [P.XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign LSUHADDR = PAdrM; assign LSUHADDR = PAdrM;
assign LSUHSIZE = LSUFunct3M; assign LSUHSIZE = LSUFunct3M;
ahbinterface #(`XLEN, 1) ahbinterface(.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HREADY(LSUHREADY), ahbinterface #(P.XLEN, 1) ahbinterface(.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HREADY(LSUHREADY),
.HRDATA(HRDATA), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HWDATA(LSUHWDATA), .HRDATA(HRDATA), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HWDATA(LSUHWDATA),
.HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM), .HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM),
.Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer)); .Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer));
// Mux between the 2 sources of read data, 0: Bus, 1: DTIM // Mux between the 2 sources of read data, 0: Bus, 1: DTIM
if(`DTIM_SUPPORTED) mux2 #(`XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM, SelDTIM, ReadDataWordMuxM); if(P.DTIM_SUPPORTED) mux2 #(P.XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM, SelDTIM, ReadDataWordMuxM);
else assign ReadDataWordMuxM = FetchBuffer[`XLEN-1:0]; else assign ReadDataWordMuxM = FetchBuffer[P.XLEN-1:0];
assign LSUHBURST = 3'b0; assign LSUHBURST = 3'b0;
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0; assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
end end
@ -322,16 +320,16 @@ module lsu (
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Atomic operations // Atomic operations
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
if (`A_SUPPORTED) begin:atomic if (P.A_SUPPORTED) begin:atomic
atomic atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[`XLEN-1:0]), .IHWriteDataM, .PAdrM, atomic atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest, .LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
.IMAWriteDataM, .SquashSCW, .LSURWM); .IMAWriteDataM, .SquashSCW, .LSURWM);
end else begin:lrsc end else begin:lrsc
assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign IMAWriteDataM = IHWriteDataM; assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign IMAWriteDataM = IHWriteDataM;
end end
if (`F_SUPPORTED) if (P.F_SUPPORTED)
mux2 #(`LLEN) datamux({{{`LLEN-`XLEN}{1'b0}}, IMAWriteDataM}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM); mux2 #(P.LLEN) datamux({{{P.LLEN-P.XLEN}{1'b0}}, IMAWriteDataM}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM);
else assign IMAFWriteDataM = IMAWriteDataM; else assign IMAFWriteDataM = IMAWriteDataM;
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
@ -342,13 +340,13 @@ module lsu (
subwordwrite subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM); subwordwrite subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
// Compute byte masks // Compute byte masks
swbytemask #(`LLEN) swbytemask(.Size(LSUFunct3M), .Adr(PAdrM[$clog2(`LLEN/8)-1:0]), .ByteMask(ByteMaskM)); swbytemask #(P.LLEN) swbytemask(.Size(LSUFunct3M), .Adr(PAdrM[$clog2(P.LLEN/8)-1:0]), .ByteMask(ByteMaskM));
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// MW Pipeline Register // MW Pipeline Register
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
flopen #(`LLEN) ReadDataMWReg(clk, ~StallW, ReadDataM, ReadDataW); flopen #(P.LLEN) ReadDataMWReg(clk, ~StallW, ReadDataM, ReadDataW);
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Big Endian Byte Swapper // Big Endian Byte Swapper
@ -356,9 +354,9 @@ module lsu (
// swap the bytes when read from big-endian memory // swap the bytes when read from big-endian memory
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
if (`BIGENDIAN_SUPPORTED) begin:endian if (P.BIGENDIAN_SUPPORTED) begin:endian
endianswap #(`LLEN) storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(LSUWriteDataM)); endianswap #(P.LLEN) storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(LSUWriteDataM));
endianswap #(`LLEN) loadswap(.BigEndianM, .a(ReadDataWordMuxM), .y(LittleEndianReadDataWordM)); endianswap #(P.LLEN) loadswap(.BigEndianM, .a(ReadDataWordMuxM), .y(LittleEndianReadDataWordM));
end else begin end else begin
assign LSUWriteDataM = LittleEndianWriteDataM; assign LSUWriteDataM = LittleEndianWriteDataM;
assign LittleEndianReadDataWordM = ReadDataWordMuxM; assign LittleEndianReadDataWordM = ReadDataWordMuxM;

View File

@ -29,20 +29,18 @@
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/////////////////////////////////////////// ///////////////////////////////////////////
`include "wally-config.vh" module hptw import cvw::*; #(parameter cvw_t P) (
module hptw (
input logic clk, reset, input logic clk, reset,
input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table input logic [P.XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
input logic [`XLEN-1:0] PCSpillF, // addresses to translate input logic [P.XLEN-1:0] PCSpillF, // addresses to translate
input logic [`XLEN+1:0] IEUAdrExtM, // addresses to translate input logic [P.XLEN+1:0] IEUAdrExtM, // addresses to translate
input logic [1:0] MemRWM, AtomicM, input logic [1:0] MemRWM, AtomicM,
// system status // system status
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, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] ReadDataM, // page table entry from LSU input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
input logic [`XLEN-1:0] WriteDataM, input logic [P.XLEN-1:0] WriteDataM,
input logic DCacheStallM, // stall from LSU input logic DCacheStallM, // stall from LSU
input logic [2:0] Funct3M, input logic [2:0] Funct3M,
input logic [6:0] Funct7M, input logic [6:0] Funct7M,
@ -51,12 +49,12 @@ module hptw (
input logic FlushW, input logic FlushW,
input logic InstrUpdateDAF, input logic InstrUpdateDAF,
input logic DataUpdateDAM, input logic DataUpdateDAM,
output logic [`XLEN-1:0] PTE, // page table entry to TLBs output logic [P.XLEN-1:0] PTE, // page table entry to TLBs
output logic [1:0] PageType, // page type to TLBs output logic [1:0] PageType, // page type to TLBs
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
output logic [1:0] PreLSURWM, output logic [1:0] PreLSURWM,
output logic [`XLEN+1:0] IHAdrM, output logic [P.XLEN+1:0] IHAdrM,
output logic [`XLEN-1:0] IHWriteDataM, output logic [P.XLEN-1:0] IHWriteDataM,
output logic [1:0] LSUAtomicM, output logic [1:0] LSUAtomicM,
output logic [2:0] LSUFunct3M, output logic [2:0] LSUFunct3M,
output logic [6:0] LSUFunct7M, output logic [6:0] LSUFunct7M,
@ -74,8 +72,8 @@ module hptw (
LEAF, IDLE, UPDATE_PTE} statetype; LEAF, IDLE, UPDATE_PTE} statetype;
logic DTLBWalk; // register TLBs translation miss requests logic DTLBWalk; // register TLBs translation miss requests
logic [`PPN_BITS-1:0] BasePageTablePPN; logic [P.PPN_BITS-1:0] BasePageTablePPN;
logic [`PPN_BITS-1:0] CurrentPPN; logic [P.PPN_BITS-1:0] CurrentPPN;
logic Executable, Writable, Readable, Valid, PTE_U; logic Executable, Writable, Readable, Valid, PTE_U;
logic Misaligned, MegapageMisaligned; logic Misaligned, MegapageMisaligned;
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE; logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
@ -83,18 +81,18 @@ module hptw (
logic TLBMiss; logic TLBMiss;
logic PRegEn; logic PRegEn;
logic [1:0] NextPageType; logic [1:0] NextPageType;
logic [`SVMODE_BITS-1:0] SvMode; logic [P.SVMODE_BITS-1:0] SvMode;
logic [`XLEN-1:0] TranslationVAdr; logic [P.XLEN-1:0] TranslationVAdr;
logic [`XLEN-1:0] NextPTE; logic [P.XLEN-1:0] NextPTE;
logic UpdatePTE; logic UpdatePTE;
logic HPTWUpdateDA; logic HPTWUpdateDA;
logic [`PA_BITS-1:0] HPTWReadAdr; logic [P.PA_BITS-1:0] HPTWReadAdr;
logic SelHPTWAdr; logic SelHPTWAdr;
logic [`XLEN+1:0] HPTWAdrExt; logic [P.XLEN+1:0] HPTWAdrExt;
logic ITLBMissOrUpdateDAF; logic ITLBMissOrUpdateDAF;
logic DTLBMissOrUpdateDAM; logic DTLBMissOrUpdateDAM;
logic LSUAccessFaultM; logic LSUAccessFaultM;
logic [`PA_BITS-1:0] HPTWAdr; logic [P.PA_BITS-1:0] HPTWAdr;
logic [1:0] HPTWRW; logic [1:0] HPTWRW;
logic [2:0] HPTWSize; // 32 or 64 bit access logic [2:0] HPTWSize; // 32 or 64 bit access
statetype WalkerState, NextWalkerState, InitialWalkerState; statetype WalkerState, NextWalkerState, InitialWalkerState;
@ -119,18 +117,18 @@ module hptw (
assign HPTWInstrAccessFaultF = TakeHPTWFaultDelay ? HPTWInstrAccessFaultDelay : 1'b0; assign HPTWInstrAccessFaultF = TakeHPTWFaultDelay ? HPTWInstrAccessFaultDelay : 1'b0;
// Extract bits from CSRs and inputs // Extract bits from CSRs and inputs
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; assign SvMode = SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS];
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0]; assign BasePageTablePPN = SATP_REGW[P.PPN_BITS-1:0];
assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissOrUpdateDAF); assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissOrUpdateDAF);
// Determine which address to translate // Determine which address to translate
mux2 #(`XLEN) vadrmux(PCSpillF, IEUAdrExtM[`XLEN-1:0], DTLBWalk, TranslationVAdr); mux2 #(P.XLEN) vadrmux(PCSpillF, IEUAdrExtM[P.XLEN-1:0], DTLBWalk, TranslationVAdr);
assign CurrentPPN = PTE[`PPN_BITS+9:10]; assign CurrentPPN = PTE[P.PPN_BITS+9:10];
// State flops // State flops
flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB) flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB)
assign PRegEn = HPTWRW[1] & ~DCacheStallM | UpdatePTE; assign PRegEn = HPTWRW[1] & ~DCacheStallM | UpdatePTE;
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache flopenr #(P.XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache
// Assign PTE descriptors common across all XLEN values // Assign PTE descriptors common across all XLEN values
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table // For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
@ -140,7 +138,7 @@ module hptw (
assign ValidLeafPTE = ValidPTE & LeafPTE; assign ValidLeafPTE = ValidPTE & LeafPTE;
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE; assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
if(`SVADU_SUPPORTED) begin : hptwwrites if(P.SVADU_SUPPORTED) begin : hptwwrites
logic ReadAccess, WriteAccess; logic ReadAccess, WriteAccess;
logic InvalidRead, InvalidWrite, InvalidOp; logic InvalidRead, InvalidWrite, InvalidOp;
logic UpperBitsUnequal; logic UpperBitsUnequal;
@ -148,18 +146,18 @@ module hptw (
logic [1:0] EffectivePrivilegeMode; logic [1:0] EffectivePrivilegeMode;
logic ImproperPrivilege; logic ImproperPrivilege;
logic SaveHPTWAdr, SelHPTWWriteAdr; logic SaveHPTWAdr, SelHPTWWriteAdr;
logic [`PA_BITS-1:0] HPTWWriteAdr; logic [P.PA_BITS-1:0] HPTWWriteAdr;
logic SetDirty; logic SetDirty;
logic Dirty, Accessed; logic Dirty, Accessed;
logic [`XLEN-1:0] AccessedPTE; logic [P.XLEN-1:0] AccessedPTE;
assign AccessedPTE = {PTE[`XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
mux2 #(`XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE); mux2 #(P.XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE);
flopenr #(`PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr); flopenr #(P.PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
assign SaveHPTWAdr = WalkerState == L0_ADR; assign SaveHPTWAdr = WalkerState == L0_ADR;
assign SelHPTWWriteAdr = UpdatePTE | HPTWRW[0]; assign SelHPTWWriteAdr = UpdatePTE | HPTWRW[0];
mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr); mux2 #(P.PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);
assign {Dirty, Accessed} = PTE[7:6]; assign {Dirty, Accessed} = PTE[7:6];
assign WriteAccess = MemRWM[0]; // implies | (|AtomicM); assign WriteAccess = MemRWM[0]; // implies | (|AtomicM);
@ -167,11 +165,11 @@ module hptw (
assign ReadAccess = MemRWM[1]; assign ReadAccess = MemRWM[1];
assign EffectivePrivilegeMode = DTLBWalk ? (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW) : PrivilegeModeW; // DTLB uses MPP mode when MPRV is 1 assign EffectivePrivilegeMode = DTLBWalk ? (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW) : PrivilegeModeW; // DTLB uses MPP mode when MPRV is 1
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk)); ((EffectivePrivilegeMode == P.S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk));
// Check for page faults // Check for page faults
vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr), vm64check vm64check(.SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]), .VAdr(TranslationVAdr),
.SV39Mode(), .UpperBitsUnequal); .SV39Mode(), .UpperBitsUnequal);
assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable);
assign InvalidWrite = WriteAccess & ~Writable; assign InvalidWrite = WriteAccess & ~Writable;
@ -212,16 +210,16 @@ module hptw (
endcase endcase
// HPTWAdr muxing // HPTWAdr muxing
if (`XLEN==32) begin // RV32 if (P.XLEN==32) begin // RV32
logic [9:0] VPN; logic [9:0] VPN;
logic [`PPN_BITS-1:0] PPN; logic [P.PPN_BITS-1:0] PPN;
assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state
assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN; assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN;
assign HPTWReadAdr = {PPN, VPN, 2'b00}; assign HPTWReadAdr = {PPN, VPN, 2'b00};
assign HPTWSize = 3'b010; assign HPTWSize = 3'b010;
end else begin // RV64 end else begin // RV64
logic [8:0] VPN; logic [8:0] VPN;
logic [`PPN_BITS-1:0] PPN; logic [P.PPN_BITS-1:0] PPN;
always_comb always_comb
case (WalkerState) // select VPN field based on HPTW state case (WalkerState) // select VPN field based on HPTW state
L3_ADR, L3_RD: VPN = TranslationVAdr[47:39]; L3_ADR, L3_RD: VPN = TranslationVAdr[47:39];
@ -230,19 +228,19 @@ module hptw (
default: VPN = TranslationVAdr[20:12]; default: VPN = TranslationVAdr[20:12];
endcase endcase
assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) | assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) |
(SvMode != `SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN; (SvMode != P.SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN;
assign HPTWReadAdr = {PPN, VPN, 3'b000}; assign HPTWReadAdr = {PPN, VPN, 3'b000};
assign HPTWSize = 3'b011; assign HPTWSize = 3'b011;
end end
// Initial state and misalignment for RV32/64 // Initial state and misalignment for RV32/64
if (`XLEN == 32) begin if (P.XLEN == 32) begin
assign InitialWalkerState = L1_ADR; assign InitialWalkerState = L1_ADR;
assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0 assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0
assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned); assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned);
end else begin end else begin
logic GigapageMisaligned, TerapageMisaligned; logic GigapageMisaligned, TerapageMisaligned;
assign InitialWalkerState = (SvMode == `SV48) ? L3_ADR : L2_ADR; assign InitialWalkerState = (SvMode == P.SV48) ? L3_ADR : L2_ADR;
assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0 assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0
assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0 assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0
assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0 assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0
@ -281,7 +279,7 @@ module hptw (
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD; L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
else if(LSUAccessFaultM) NextWalkerState = IDLE; else if(LSUAccessFaultM) NextWalkerState = IDLE;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
LEAF: if (`SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE; LEAF: if (P.SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE;
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE; UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
@ -293,8 +291,8 @@ module hptw (
assign HPTWAccessFaultDelay = HPTWLoadAccessFaultDelay | HPTWStoreAmoAccessFaultDelay | HPTWInstrAccessFaultDelay; assign HPTWAccessFaultDelay = HPTWLoadAccessFaultDelay | HPTWStoreAmoAccessFaultDelay | HPTWInstrAccessFaultDelay;
assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss & ~(HPTWAccessFaultDelay)); assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss & ~(HPTWAccessFaultDelay));
assign ITLBMissOrUpdateDAF = ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF); assign ITLBMissOrUpdateDAF = ITLBMissF | (P.SVADU_SUPPORTED & InstrUpdateDAF);
assign DTLBMissOrUpdateDAM = DTLBMissM | (`SVADU_SUPPORTED & DataUpdateDAM); assign DTLBMissOrUpdateDAM = DTLBMissM | (P.SVADU_SUPPORTED & DataUpdateDAM);
// HTPW address/data/control muxing // HTPW address/data/control muxing
@ -304,15 +302,15 @@ module hptw (
// always block interrupts when using the hardware page table walker. // always block interrupts when using the hardware page table walker.
// multiplex the outputs to LSU // multiplex the outputs to LSU
if(`XLEN == 64) assign HPTWAdrExt = {{(`XLEN+2-`PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits if(P.XLEN == 64) assign HPTWAdrExt = {{(P.XLEN+2-P.PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits
else assign HPTWAdrExt = HPTWAdr; else assign HPTWAdrExt = HPTWAdr;
mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM); mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M); mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M); mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM); mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
mux2 #(`XLEN+2) lsupadrmux(IEUAdrExtM, HPTWAdrExt, SelHPTWAdr, IHAdrM); mux2 #(P.XLEN+2) lsupadrmux(IEUAdrExtM, HPTWAdrExt, SelHPTWAdr, IHAdrM);
if(`SVADU_SUPPORTED) if(P.SVADU_SUPPORTED)
mux2 #(`XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, IHWriteDataM); mux2 #(P.XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, IHWriteDataM);
else assign IHWriteDataM = WriteDataM; else assign IHWriteDataM = WriteDataM;
endmodule endmodule

View File

@ -26,24 +26,23 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module mmu import cvw::*; #(parameter cvw_t P,
parameter TLB_ENTRIES = 8, IMMU = 0) (
module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
input logic clk, reset, input logic clk, reset,
input logic [`XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit) input logic [P.XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit)
input logic STATUS_MXR, // Status CSR: make executable page readable input logic STATUS_MXR, // Status CSR: make executable page readable
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 [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 [`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
input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
input logic [`XLEN-1:0] PTE, // page table entry input logic [P.XLEN-1:0] PTE, // page table entry
input logic [1:0] PageTypeWriteVal, // page type input logic [1:0] PageTypeWriteVal, // page type
input logic TLBWrite, // write TLB entry input logic TLBWrite, // write TLB entry
input logic TLBFlush, // Invalidate all TLB entries input logic TLBFlush, // Invalidate all TLB entries
output logic [`PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
output logic TLBMiss, // Miss TLB output logic TLBMiss, // Miss TLB
output logic Cacheable, // PMA indicates memory address is cachable output logic Cacheable, // PMA indicates memory address is cachable
output logic Idempotent, // PMA indicates memory address is idempotent output logic Idempotent, // PMA indicates memory address is idempotent
@ -55,11 +54,11 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
// PMA checker signals // PMA checker signals
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // PMP addresses input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
); );
logic [`PA_BITS-1:0] TLBPAdr; // physical address for TLB logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
logic PMAInstrAccessFaultF; // Instruction access fault from PMA logic PMAInstrAccessFaultF; // Instruction access fault from PMA
logic PMPInstrAccessFaultF; // Instruction access fault from PMP logic PMPInstrAccessFaultF; // Instruction access fault from PMP
logic PMALoadAccessFaultM; // Load access fault from PMA logic PMALoadAccessFaultM; // Load access fault from PMA
@ -73,15 +72,15 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
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
// only instantiate TLB if Virtual Memory is supported // only instantiate TLB if Virtual Memory is supported
if (`VIRTMEM_SUPPORTED) begin:tlb if (P.VIRTMEM_SUPPORTED) begin:tlb
logic ReadAccess, WriteAccess; logic ReadAccess, WriteAccess;
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
assign WriteAccess = WriteAccessM; assign WriteAccess = WriteAccessM;
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb( tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(
.clk, .reset, .clk, .reset,
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]),
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]), .SATP_ASID(SATP_REGW[P.ASID_BASE+P.ASID_BITS-1:P.ASID_BASE]),
.VAdr(VAdr[`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,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal, .DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
@ -96,7 +95,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
// If translation is occuring, select translated physical address from TLB // If translation is occuring, select translated physical address from TLB
// the lower 12 bits are the page offset. These are never changed from the orginal // the lower 12 bits are the page offset. These are never changed from the orginal
// non translated address. // non translated address.
mux2 #(`PA_BITS-12) addressmux(VAdr[`PA_BITS-1:12], TLBPAdr[`PA_BITS-1:12], Translate, PhysicalAddress[`PA_BITS-1:12]); mux2 #(P.PA_BITS-12) addressmux(VAdr[P.PA_BITS-1:12], TLBPAdr[P.PA_BITS-1:12], Translate, PhysicalAddress[P.PA_BITS-1:12]);
assign PhysicalAddress[11:0] = VAdr[11:0]; assign PhysicalAddress[11:0] = VAdr[11:0];
/////////////////////////////////////////// ///////////////////////////////////////////
@ -108,7 +107,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
.Cacheable, .Idempotent, .SelTIM, .Cacheable, .Idempotent, .SelTIM,
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM); .PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
if (`PMP_ENTRIES > 0) begin : pmp if (P.PMP_ENTRIES > 0) begin : pmp
pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW, pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.ExecuteAccessF, .WriteAccessM, .ReadAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM,

View File

@ -208,7 +208,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE, .FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE,
.CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD); .CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD);
lsu lsu( lsu #(P) lsu(
.clk, .reset, .StallM, .FlushM, .StallW, .FlushW, .clk, .reset, .StallM, .FlushM, .StallW, .FlushW,
// CPU interface // CPU interface
.MemRWM, .Funct3M, .Funct7M(InstrM[31:25]), .AtomicM, .MemRWM, .Funct3M, .Funct7M(InstrM[31:25]), .AtomicM,