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-11 22:03:44 +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 "
2021-08-25 17:42:05 +00:00
module mmu # ( parameter TLB_ENTRIES = 8 , // number of TLB Entries
2021-06-04 21:05:07 +00:00
parameter IMMU = 0 ) (
2022-02-17 05:37:36 +00:00
input logic clk , reset ,
2021-06-04 15:59:14 +00:00
// Current value of satp CSR (from privileged unit)
2022-02-17 05:37:36 +00:00
input logic [ `XLEN - 1 : 0 ] SATP_REGW ,
input logic STATUS_MXR , STATUS_SUM , STATUS_MPRV ,
input logic [ 1 : 0 ] STATUS_MPP ,
2021-06-04 15:59:14 +00:00
// Current privilege level of the processeor
2022-02-17 05:37:36 +00:00
input logic [ 1 : 0 ] PrivilegeModeW ,
2021-06-04 15:59:14 +00:00
// 00 - TLB is not being accessed
// 1x - TLB is accessed for a read (or an instruction)
// x1 - TLB is accessed for a write
// 11 - TLB is accessed for both read and write
2022-02-17 05:37:36 +00:00
input logic DisableTranslation ,
2021-06-04 15:59:14 +00:00
2022-03-25 04:47:28 +00:00
// VAdr is the virtual/physical address from IEU or physical address from HPTW.
2021-07-19 15:33:27 +00:00
// PhysicalAddress is selected to be PAdr when no translation or the translated VAdr (TLBPAdr)
// when there is translation.
2022-03-25 04:47:28 +00:00
input logic [ `XLEN + 1 : 0 ] VAdr ,
2022-02-17 05:37:36 +00:00
input logic [ 1 : 0 ] Size , // 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
2021-06-04 15:59:14 +00:00
// Controls for writing a new entry to the TLB
2022-02-17 05:37:36 +00:00
input logic [ `XLEN - 1 : 0 ] PTE ,
input logic [ 1 : 0 ] PageTypeWriteVal ,
input logic TLBWrite ,
2021-06-04 15:59:14 +00:00
// Invalidate all TLB entries
2022-02-17 05:37:36 +00:00
input logic TLBFlush ,
2021-06-04 15:59:14 +00:00
// Physical address outputs
2021-06-18 13:11:31 +00:00
output logic [ `PA_BITS - 1 : 0 ] PhysicalAddress ,
2022-02-17 05:37:36 +00:00
output logic TLBMiss ,
2023-01-07 13:59:56 +00:00
output logic Cacheable , Idempotent , SelTIM ,
2021-06-04 15:59:14 +00:00
// Faults
2022-02-17 05:37:36 +00:00
output logic InstrAccessFaultF , LoadAccessFaultM , StoreAmoAccessFaultM ,
output logic InstrPageFaultF , LoadPageFaultM , StoreAmoPageFaultM ,
output logic DAPageFault ,
output logic LoadMisalignedFaultM , StoreAmoMisalignedFaultM ,
2021-06-04 15:59:14 +00:00
2021-06-04 21:05:07 +00:00
// PMA checker signals
2022-02-17 05:37:36 +00:00
input logic AtomicAccessM , ExecuteAccessF , WriteAccessM , ReadAccessM ,
input var logic [ 7 : 0 ] PMPCFG_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ] ,
input var logic [ `XLEN - 1 : 0 ] PMPADDR_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ]
2021-06-04 15:59:14 +00:00
) ;
2021-07-08 20:52:06 +00:00
logic [ `PA_BITS - 1 : 0 ] TLBPAdr ;
2021-06-04 15:59:14 +00:00
// Translation lookaside buffer
2021-07-06 18:43:53 +00:00
logic PMAInstrAccessFaultF , PMPInstrAccessFaultF ;
logic PMALoadAccessFaultM , PMPLoadAccessFaultM ;
2022-01-27 23:11:27 +00:00
logic PMAStoreAmoAccessFaultM , PMPStoreAmoAccessFaultM ;
logic DataMisalignedM ;
2021-07-06 19:29:42 +00:00
logic Translate ;
2021-10-23 18:41:20 +00:00
logic TLBHit ;
2022-01-27 23:11:27 +00:00
logic TLBPageFault ;
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 ;
tlb # ( . TLB_ENTRIES ( TLB_ENTRIES ) , . ITLB ( IMMU ) )
tlb ( . clk , . reset ,
. 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 ,
2022-02-17 05:37:36 +00:00
. Translate , . TLBPageFault , . DAPageFault ) ;
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.
//mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress);
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-07-06 00:35:31 +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 ,
2022-08-28 18:50:50 +00:00
. AtomicAccessM , . ExecuteAccessF , . WriteAccessM , . ReadAccessM ,
2023-01-07 13:59:56 +00:00
. Cacheable , . Idempotent , . SelTIM ,
2022-01-27 23:11:27 +00:00
. PMAInstrAccessFaultF , . PMALoadAccessFaultM , . PMAStoreAmoAccessFaultM ) ;
2022-08-27 04:05:20 +00:00
2021-12-31 07:19:51 +00:00
pmpchecker pmpchecker ( . PhysicalAddress , . PrivilegeModeW ,
. PMPCFG_ARRAY_REGW , . PMPADDR_ARRAY_REGW ,
. ExecuteAccessF , . WriteAccessM , . ReadAccessM ,
2022-01-27 23:11:27 +00:00
. PMPInstrAccessFaultF , . PMPLoadAccessFaultM , . PMPStoreAmoAccessFaultM ) ;
2021-06-04 21:05:07 +00:00
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.
assign InstrAccessFaultF = ( PMAInstrAccessFaultF | PMPInstrAccessFaultF ) & ~ ( Translate & ~ TLBHit ) ;
assign LoadAccessFaultM = ( PMALoadAccessFaultM | PMPLoadAccessFaultM ) & ~ ( Translate & ~ TLBHit ) ;
2022-01-27 23:11:27 +00:00
assign StoreAmoAccessFaultM = ( PMAStoreAmoAccessFaultM | PMPStoreAmoAccessFaultM ) & ~ ( Translate & ~ TLBHit ) ;
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
assign LoadMisalignedFaultM = DataMisalignedM & ReadAccessM ;
assign StoreAmoMisalignedFaultM = DataMisalignedM & ( WriteAccessM | AtomicAccessM ) ;
2023-01-07 12:49:25 +00:00
2022-01-27 23:11:27 +00:00
// Specify which type of page fault is occurring
assign InstrPageFaultF = TLBPageFault & ExecuteAccessF ;
assign LoadPageFaultM = TLBPageFault & ReadAccessM ;
assign StoreAmoPageFaultM = TLBPageFault & ( WriteAccessM | AtomicAccessM ) ;
2021-06-23 21:43:22 +00:00
endmodule