2021-06-04 15:59:14 +00:00
///////////////////////////////////////////
// mmu.sv
//
// Written: david_harris@hmc.edu and kmacsaigoren@hmc.edu 4 June 2021
// Modified:
//
// Purpose: Memory management unit, including TLB, PMA, PMP
//
2023-01-15 02:14:38 +00:00
// Documentation: RISC-V System on Chip Design Chapter 8
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2021-06-04 15:59:14 +00:00
//
2023-01-10 19:35:20 +00:00
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-06-04 15:59:14 +00:00
//
2023-01-10 19:35:20 +00:00
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-06-04 15:59:14 +00:00
//
2023-01-10 19:35:20 +00:00
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
2021-06-04 15:59:14 +00:00
//
2023-01-10 19:35:20 +00:00
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
2022-01-07 12:58:40 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
2021-06-04 15:59:14 +00:00
`include " wally-config.vh "
2023-01-15 01:35:21 +00:00
module mmu # ( parameter TLB_ENTRIES = 8 , IMMU = 0 ) (
2023-01-15 02:14:38 +00:00
input logic clk , reset ,
input logic [ `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_SUM , // Status CSR: Supervisor access to user memory
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 ] 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 [ `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 [ `XLEN - 1 : 0 ] PTE , // page table entry
input logic [ 1 : 0 ] PageTypeWriteVal , // page type
input logic TLBWrite , // write TLB entry
input logic TLBFlush , // Invalidate all TLB entries
2023-01-15 01:35:21 +00:00
output logic [ `PA_BITS - 1 : 0 ] PhysicalAddress , // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
output logic TLBMiss , // Miss TLB
output logic Cacheable , // PMA indicates memory address is cachable
output logic Idempotent , // PMA indicates memory address is idempotent
output logic SelTIM , // Select a tightly integrated memory
2021-06-04 15:59:14 +00:00
// Faults
2023-01-15 01:35:21 +00:00
output logic InstrAccessFaultF , LoadAccessFaultM , StoreAmoAccessFaultM , // access fault sources
output logic InstrPageFaultF , LoadPageFaultM , StoreAmoPageFaultM , // page fault sources
2023-02-27 01:51:45 +00:00
output logic UpdateDA , // page fault due to setting dirty or access bit
2023-01-15 01:35:21 +00:00
output logic LoadMisalignedFaultM , StoreAmoMisalignedFaultM , // misaligned fault sources
2021-06-04 21:05:07 +00:00
// PMA checker signals
2023-01-15 02:14:38 +00:00
input logic AtomicAccessM , ExecuteAccessF , WriteAccessM , ReadAccessM , // access type
2023-01-15 01:35:21 +00:00
input var logic [ 7 : 0 ] PMPCFG_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ] , // PMP configuration
2023-03-22 11:33:14 +00:00
input var logic [ `PA_BITS - 3 : 0 ] PMPADDR_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ] // PMP addresses
2021-06-04 15:59:14 +00:00
) ;
2023-01-15 01:35:21 +00:00
logic [ `PA_BITS - 1 : 0 ] TLBPAdr ; // physical address for TLB
logic PMAInstrAccessFaultF ; // Instruction access fault from PMA
logic PMPInstrAccessFaultF ; // Instruction access fault from PMP
logic PMALoadAccessFaultM ; // Load access fault from PMA
logic PMPLoadAccessFaultM ; // Load access fault from PMP
logic PMAStoreAmoAccessFaultM ; // Store or AMO access fault from PMA
logic PMPStoreAmoAccessFaultM ; // Store or AMO access fault from PMP
logic DataMisalignedM ; // load or store misaligned
logic Translate ; // Translation occurs when virtual memory is active and DisableTranslation is off
logic TLBHit ; // Hit in TLB
logic TLBPageFault ; // Page fault from TLB
2023-02-27 02:35:10 +00:00
logic ReadNoAmoAccessM ; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
2022-01-27 23:11:27 +00:00
2021-07-06 00:35:31 +00:00
// only instantiate TLB if Virtual Memory is supported
2022-02-03 01:08:34 +00:00
if ( `VIRTMEM_SUPPORTED ) begin : tlb
2022-01-05 14:35:25 +00:00
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 WriteAccess = WriteAccessM ;
2023-01-15 01:35:21 +00:00
tlb # ( . TLB_ENTRIES ( TLB_ENTRIES ) , . ITLB ( IMMU ) ) tlb (
. clk , . reset ,
2022-01-05 14:35:25 +00:00
. SATP_MODE ( SATP_REGW [ `XLEN - 1 : `XLEN - `SVMODE_BITS ] ) ,
. SATP_ASID ( SATP_REGW [ `ASID_BASE + `ASID_BITS - 1 : `ASID_BASE ] ) ,
2022-03-25 04:47:28 +00:00
. VAdr ( VAdr [ `XLEN - 1 : 0 ] ) , . STATUS_MXR , . STATUS_SUM , . STATUS_MPRV , . STATUS_MPP ,
2022-01-05 14:35:25 +00:00
. PrivilegeModeW , . ReadAccess , . WriteAccess ,
. DisableTranslation , . PTE , . PageTypeWriteVal ,
. TLBWrite , . TLBFlush , . TLBPAdr , . TLBMiss , . TLBHit ,
2023-02-27 01:51:45 +00:00
. Translate , . TLBPageFault , . UpdateDA ) ;
2022-01-05 14:35:25 +00:00
end else begin : tlb // just pass address through as physical
assign Translate = 0 ;
assign TLBMiss = 0 ;
assign TLBHit = 1 ; // *** is this necessary
assign TLBPageFault = 0 ;
end
2021-07-06 19:29:42 +00:00
// If translation is occuring, select translated physical address from TLB
2022-01-07 05:19:09 +00:00
// the lower 12 bits are the page offset. These are never changed from the orginal
// non translated address.
2022-03-25 04:47:28 +00:00
mux2 # ( `PA_BITS - 12 ) addressmux ( VAdr [ `PA_BITS - 1 : 12 ] , TLBPAdr [ `PA_BITS - 1 : 12 ] , Translate , PhysicalAddress [ `PA_BITS - 1 : 12 ] ) ;
assign PhysicalAddress [ 11 : 0 ] = VAdr [ 11 : 0 ] ;
2022-01-07 05:19:09 +00:00
2021-06-04 15:59:14 +00:00
///////////////////////////////////////////
// Check physical memory accesses
///////////////////////////////////////////
2021-12-31 07:19:51 +00:00
pmachecker pmachecker ( . PhysicalAddress , . Size ,
2023-01-15 01:35:21 +00:00
. AtomicAccessM , . ExecuteAccessF , . WriteAccessM , . ReadAccessM ,
. Cacheable , . Idempotent , . SelTIM ,
. PMAInstrAccessFaultF , . PMALoadAccessFaultM , . PMAStoreAmoAccessFaultM ) ;
2022-08-27 04:05:20 +00:00
2023-02-19 23:31:00 +00:00
if ( `PMP_ENTRIES > 0 )
pmpchecker pmpchecker ( . PhysicalAddress , . PrivilegeModeW ,
. PMPCFG_ARRAY_REGW , . PMPADDR_ARRAY_REGW ,
. ExecuteAccessF , . WriteAccessM , . ReadAccessM ,
. PMPInstrAccessFaultF , . PMPLoadAccessFaultM , . PMPStoreAmoAccessFaultM ) ;
else begin
assign PMPInstrAccessFaultF = 0 ;
assign PMPStoreAmoAccessFaultM = 0 ;
assign PMPLoadAccessFaultM = 0 ;
end
2021-06-04 21:05:07 +00:00
2023-02-27 02:35:10 +00:00
assign ReadNoAmoAccessM = ReadAccessM & ~ WriteAccessM ; // AMO causes StoreAmo rather than Load fault
2023-01-07 12:49:25 +00:00
// Access faults
2021-07-16 17:22:13 +00:00
// If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
2023-02-26 17:58:34 +00:00
assign InstrAccessFaultF = ( PMAInstrAccessFaultF | PMPInstrAccessFaultF ) & ~ TLBMiss ;
assign LoadAccessFaultM = ( PMALoadAccessFaultM | PMPLoadAccessFaultM ) & ~ TLBMiss ;
assign StoreAmoAccessFaultM = ( PMAStoreAmoAccessFaultM | PMPStoreAmoAccessFaultM ) & ~ TLBMiss ;
2022-01-27 23:11:27 +00:00
2023-01-07 12:49:25 +00:00
// Misaligned faults
always_comb
2022-01-27 23:11:27 +00:00
case ( Size [ 1 : 0 ] )
2 'b00 : DataMisalignedM = 0 ; // lb, sb, lbu
2 'b01 : DataMisalignedM = VAdr [ 0 ] ; // lh, sh, lhu
2 'b10 : DataMisalignedM = VAdr [ 1 ] | VAdr [ 0 ] ; // lw, sw, flw, fsw, lwu
2 'b11 : DataMisalignedM = | VAdr [ 2 : 0 ] ; // ld, sd, fld, fsd
endcase
2023-02-27 02:35:10 +00:00
assign LoadMisalignedFaultM = DataMisalignedM & ReadNoAmoAccessM ;
assign StoreAmoMisalignedFaultM = DataMisalignedM & WriteAccessM ;
2023-01-07 12:49:25 +00:00
2022-01-27 23:11:27 +00:00
// Specify which type of page fault is occurring
2023-01-15 01:35:21 +00:00
assign InstrPageFaultF = TLBPageFault & ExecuteAccessF ;
2023-02-27 02:35:10 +00:00
assign LoadPageFaultM = TLBPageFault & ReadNoAmoAccessM ;
assign StoreAmoPageFaultM = TLBPageFault & WriteAccessM ;
2021-06-23 21:43:22 +00:00
endmodule