From fa51ab9f6867512bda6d188eb9f16cd443bc5e36 Mon Sep 17 00:00:00 2001
From: David Harris <david_harris@hmc.edu>
Date: Wed, 23 Jun 2021 01:41:00 -0400
Subject: [PATCH] Refactored pmachecker to have adrdecs used in uncore

---
 wally-pipelined/src/lsu/dcache.sv             | 184 ++++++++++++++++
 wally-pipelined/src/lsu/lsu.sv                | 197 ++++++++++++++++++
 .../src/mmu/{pmaadrdec.sv => adrdec.sv}       |   4 +-
 wally-pipelined/src/mmu/adrdecs.sv            |  44 ++++
 wally-pipelined/src/mmu/pmachecker.sv         |   8 +-
 wally-pipelined/src/uncore/uncore.sv          |   6 +-
 .../src/wally/wallypipelinedhart.sv           |   6 +-
 .../src/wally/wallypipelinedsoc.sv            |   1 -
 8 files changed, 433 insertions(+), 17 deletions(-)
 create mode 100644 wally-pipelined/src/lsu/dcache.sv
 create mode 100644 wally-pipelined/src/lsu/lsu.sv
 rename wally-pipelined/src/mmu/{pmaadrdec.sv => adrdec.sv} (98%)
 create mode 100644 wally-pipelined/src/mmu/adrdecs.sv

diff --git a/wally-pipelined/src/lsu/dcache.sv b/wally-pipelined/src/lsu/dcache.sv
new file mode 100644
index 00000000..fec70ef4
--- /dev/null
+++ b/wally-pipelined/src/lsu/dcache.sv
@@ -0,0 +1,184 @@
+///////////////////////////////////////////
+// dcache.sv
+//
+// Written: jaallen@g.hmc.edu 2021-04-15
+// Modified: 
+//
+// Purpose: Cache memory for the dmem so it can access memory less often, saving cycles
+// 
+// A component of the Wally configurable RISC-V project.
+// 
+// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
+// is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
+// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
+// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+///////////////////////////////////////////
+
+`include "wally-config.vh"
+
+module dcache(
+  // Basic pipeline stuff
+  input  logic              clk, reset,
+  input  logic              StallW,
+  input  logic              FlushW,
+  // Upper bits of physical address
+  input  logic [`PA_BITS-1:12] UpperPAdrM,
+  // Lower 12 bits of virtual address, since it's faster this way
+  input  logic [11:0]       LowerVAdrM,
+  // Write to the dcache
+  input  logic [`XLEN-1:0]  DCacheWriteDataM,
+  input  logic              DCacheReadM, DCacheWriteM,
+  // Data read in from the ebu unit
+  input  logic [`XLEN-1:0]  ReadDataW,
+  input  logic              MemAckW,
+  // Access requested from the ebu unit
+  output logic [`PA_BITS-1:0]  MemPAdrM,
+  output logic              MemReadM, MemWriteM,
+  // High if the dcache is requesting a stall
+  output logic              DCacheStallW,
+  // The data that was requested from the cache
+  output logic [`XLEN-1:0]  DCacheReadW
+);
+
+    // Configuration parameters
+    // TODO Move these to a config file
+    localparam integer DCACHELINESIZE = 256;
+    localparam integer DCACHENUMLINES = 512;
+
+    // Input signals to cache memory
+    logic                       FlushMem;
+    logic [`PA_BITS-1:12]       DCacheMemUpperPAdr;
+    logic [11:0]                DCacheMemLowerAdr;
+    logic                       DCacheMemWriteEnable;
+    logic [DCACHELINESIZE-1:0]  DCacheMemWriteData;
+    logic [`XLEN-1:0]           DCacheMemWritePAdr;
+    logic                       EndFetchState;
+    // Output signals from cache memory
+    logic [`XLEN-1:0]   DCacheMemReadData;
+    logic               DCacheMemReadValid;
+
+    wtdirectmappedmem #(.LINESIZE(DCACHELINESIZE), .NUMLINES(DCACHENUMLINES), .WORDSIZE(`XLEN)) cachemem(
+        .*,
+        // Stall it if the pipeline is stalled, unless we're stalling it and we're ending our stall
+        .stall(StallW),
+        .flush(FlushMem),
+        .ReadUpperPAdr(DCacheMemUpperPAdr),
+        .ReadLowerAdr(DCacheMemLowerAdr),
+        .LoadEnable(DCacheMemWriteEnable),
+        .LoadLine(DCacheMemWriteData),
+        .LoadPAdr(DCacheMemWritePAdr),
+        .DataWord(DCacheMemReadData),
+        .DataValid(DCacheMemReadValid),
+        .WriteEnable(0),
+        .WriteWord(0),
+        .WritePAdr(0),
+        .WriteSize(2'b10)
+    );
+
+    dcachecontroller #(.LINESIZE(DCACHELINESIZE)) controller(.*);
+
+    // For now, assume no writes to executable memory
+    assign FlushMem = 1'b0;
+endmodule
+
+module dcachecontroller #(parameter LINESIZE = 256) (
+    // Inputs from pipeline
+    input  logic    clk, reset,
+    input  logic    StallW,
+    input  logic    FlushW,
+
+    // Input the address to read
+    // The upper bits of the physical pc
+    input  logic [`PA_BITS-1:12]   DCacheMemUpperPAdr,
+    // The lower bits of the virtual pc
+    input  logic [11:0]         DCacheMemLowerAdr,
+
+    // Signals to/from cache memory
+    // The read coming out of it
+    input  logic [`XLEN-1:0]    DCacheMemReadData,
+    input  logic                DCacheMemReadValid,
+    // Load data into the cache
+    output logic                DCacheMemWriteEnable,
+    output logic [LINESIZE-1:0] DCacheMemWriteData,
+    output logic [`XLEN-1:0]    DCacheMemWritePAdr,
+
+    // The read that was requested
+    output logic [31:0]     DCacheReadW,
+
+    // Outputs to pipeline control stuff
+    output logic DCacheStallW, EndFetchState,
+
+    // Signals to/from ahblite interface
+    // A read containing the requested data
+    input  logic [`XLEN-1:0] ReadDataW,
+    input  logic             MemAckW,
+    // The read we request from main memory
+    output logic [`PA_BITS-1:0] MemPAdrM,
+    output logic             MemReadM, MemWriteM
+);
+
+    // Cache fault signals
+    logic           FaultStall;
+
+    // Handle happy path (data in cache)
+
+    always_comb begin
+        DCacheReadW = DCacheMemReadData;
+    end
+
+
+    // Handle cache faults
+
+    localparam integer WORDSPERLINE = LINESIZE/`XLEN;
+    localparam integer LOGWPL = $clog2(WORDSPERLINE);
+    localparam integer OFFSETWIDTH = $clog2(LINESIZE/8);
+
+    logic               FetchState, BeginFetchState;
+    logic [LOGWPL:0]    FetchWordNum, NextFetchWordNum;
+    logic [`PA_BITS-1:0]   LineAlignedPCPF;
+
+    flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState);
+    flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum);
+
+    genvar i;
+    generate
+        for (i=0; i < WORDSPERLINE; i++) begin
+            flopenr #(`XLEN) flop(clk, reset, FetchState & (i == FetchWordNum), ReadDataW, DCacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]);
+        end
+    endgenerate
+
+    // Enter the fetch state when we hit a cache fault
+    always_comb begin
+        BeginFetchState = ~DCacheMemReadValid & ~FetchState & (FetchWordNum == 0);
+    end
+    // Exit the fetch state once the cache line has been loaded
+    flopr #(1) EndFetchStateFlop(clk, reset, DCacheMemWriteEnable, EndFetchState);
+
+    // Machinery to request the correct addresses from main memory
+    always_comb begin
+        MemReadM = FetchState & ~EndFetchState & ~DCacheMemWriteEnable;
+        LineAlignedPCPF = {DCacheMemUpperPAdr, DCacheMemLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}};
+        MemPAdrM = LineAlignedPCPF + FetchWordNum*(`XLEN/8);
+        NextFetchWordNum = FetchState ? FetchWordNum+MemAckW : {LOGWPL+1{1'b0}}; 
+    end
+
+    // Write to cache memory when we have the line here
+    always_comb begin
+        DCacheMemWritePAdr = LineAlignedPCPF;
+        DCacheMemWriteEnable = FetchWordNum == {1'b1, {LOGWPL{1'b0}}} & FetchState & ~EndFetchState;
+    end
+
+    // Stall the pipeline while loading a new line from memory
+    always_comb begin
+        DCacheStallW = FetchState | ~DCacheMemReadValid;
+    end
+endmodule
diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv
new file mode 100644
index 00000000..ffa79adf
--- /dev/null
+++ b/wally-pipelined/src/lsu/lsu.sv
@@ -0,0 +1,197 @@
+///////////////////////////////////////////
+// lsu.sv
+//
+// Written: David_Harris@hmc.edu 9 January 2021
+// Modified: 
+//
+// Purpose: Load/Store Unit 
+//          Top level of the memory-stage hart logic
+//          Contains data cache, DTLB, subword read/write datapath, interface to external bus
+// 
+// A component of the Wally configurable RISC-V project.
+// 
+// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
+// is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
+// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
+// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+///////////////////////////////////////////
+
+`include "wally-config.vh"
+
+// *** Ross Thompson amo misalignment check?
+module lsu (
+  input  logic             clk, reset,
+  input  logic             StallM, FlushM, StallW, FlushW,
+  //output logic             DataStall,
+  // Memory Stage
+  input  logic [1:0]       MemRWM,
+  input  logic [`XLEN-1:0] MemAdrM,
+  input  logic [2:0]       Funct3M,
+  //input  logic [`XLEN-1:0] ReadDataW,
+  input  logic [`XLEN-1:0] WriteDataM, 
+  input  logic [1:0]       AtomicM,
+  input  logic             CommitM,
+  output logic [`PA_BITS-1:0] MemPAdrM,
+  output logic             MemReadM, MemWriteM,
+  output logic [1:0]       AtomicMaskedM,
+  output logic             DataMisalignedM,
+  output logic             CommittedM,
+  // Writeback Stage
+  input  logic             MemAckW,
+  input  logic [`XLEN-1:0] ReadDataW,
+  output logic             SquashSCW,
+  // faults
+  input  logic             NonBusTrapM,
+  input  logic             DataAccessFaultM,
+  output logic             DTLBLoadPageFaultM, DTLBStorePageFaultM,
+  output logic             LoadMisalignedFaultM, LoadAccessFaultM,
+  output logic             StoreMisalignedFaultM, StoreAccessFaultM,
+  
+  // mmu management
+  input logic  [1:0]       PrivilegeModeW,
+  input logic  [`XLEN-1:0] PageTableEntryM,
+  input logic  [1:0]       PageTypeM,
+  input logic  [`XLEN-1:0] SATP_REGW,
+  input logic              STATUS_MXR, STATUS_SUM,
+  input logic              DTLBWriteM, DTLBFlushM,
+  output logic             DTLBMissM, DTLBHitM,
+  
+  // PMA/PMP (inside mmu) signals
+  input  logic [31:0]      HADDR, // *** replace all of these H inputs with physical adress once pma checkers have been edited to use paddr as well.
+  input  logic [2:0]       HSIZE, HBURST,
+  input  logic             HWRITE,
+  input  logic             AtomicAccessM, WriteAccessM, ReadAccessM, // execute access is hardwired to zero in this mmu because we're only working with data in the M stage.
+  input  logic [63:0]      PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so thwyre gonna have to come over into ifu and dmem
+  input  var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker.
+
+  output  logic            PMALoadAccessFaultM, PMAStoreAccessFaultM,
+  output  logic            PMPLoadAccessFaultM, PMPStoreAccessFaultM, // *** can these be parameterized? we dont need the m stage ones for the immu and vice versa.
+  
+  output logic             DSquashBusAccessM,
+  output logic [5:0]       DHSELRegionsM
+  
+);
+
+  logic SquashSCM;
+  logic DTLBPageFaultM;
+  logic MemAccessM;
+  logic [1:0] CurrState, NextState;
+  logic preCommittedM;
+
+  localparam STATE_READY = 0;
+  localparam STATE_FETCH = 1;
+  localparam STATE_FETCH_AMO = 2;
+  localparam STATE_STALLED = 3;
+
+  logic PMPInstrAccessFaultF, PMAInstrAccessFaultF; // *** these are just so that the mmu has somewhere to put these outputs since they aren't used in dmem
+  // *** if you're allowed to parameterize outputs/ inputs existence, these are an easy delete.
+  
+  mmu #(.ENTRY_BITS(`DTLB_ENTRY_BITS), .IMMU(0)) dmmu(.TLBAccessType(MemRWM), .VirtualAddress(MemAdrM), .Size(Funct3M[1:0]),
+                .PTEWriteVal(PageTableEntryM), .PageTypeWriteVal(PageTypeM),
+                .TLBWrite(DTLBWriteM), .TLBFlush(DTLBFlushM),
+                .PhysicalAddress(MemPAdrM), .TLBMiss(DTLBMissM),
+                .TLBHit(DTLBHitM), .TLBPageFault(DTLBPageFaultM),
+
+                .ExecuteAccessF(1'b0),
+                .SquashBusAccess(DSquashBusAccessM), .HSELRegions(DHSELRegionsM),
+                .*); // *** the pma/pmp instruction acess faults don't really matter here. is it possible to parameterize which outputs exist?
+
+  // Specify which type of page fault is occurring
+  assign DTLBLoadPageFaultM = DTLBPageFaultM & MemRWM[1];
+  assign DTLBStorePageFaultM = DTLBPageFaultM & MemRWM[0];
+
+	// Determine if an Unaligned access is taking place
+	always_comb
+		case(Funct3M[1:0]) 
+		  2'b00:  DataMisalignedM = 0;                       // lb, sb, lbu
+		  2'b01:  DataMisalignedM = MemAdrM[0];              // lh, sh, lhu
+		  2'b10:  DataMisalignedM = MemAdrM[1] | MemAdrM[0]; // lw, sw, flw, fsw, lwu
+		  2'b11:  DataMisalignedM = |MemAdrM[2:0];           // ld, sd, fld, fsd
+		endcase 
+
+  // Squash unaligned data accesses and failed store conditionals
+  // *** this is also the place to squash if the cache is hit
+  // Changed DataMisalignedM to a larger combination of trap sources
+  // NonBusTrapM is anything that the bus doesn't contribute to producing 
+  // By contrast, using TrapM results in circular logic errors
+  assign MemReadM = MemRWM[1] & ~NonBusTrapM & CurrState != STATE_STALLED;
+  assign MemWriteM = MemRWM[0] & ~NonBusTrapM && ~SquashSCM & CurrState != STATE_STALLED;
+  assign AtomicMaskedM = CurrState != STATE_STALLED ? AtomicM : 2'b00 ;
+  assign MemAccessM = |MemRWM;
+
+  // Determine if M stage committed
+  // Reset whenever unstalled. Set when access successfully occurs
+  flopr #(1) committedMreg(clk,reset,(CommittedM | CommitM) & StallM,preCommittedM);
+  assign CommittedM = preCommittedM | CommitM;
+
+  // Determine if address is valid
+  assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
+  assign LoadAccessFaultM = DataAccessFaultM & MemRWM[1];
+  assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0];
+  assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
+
+  // Handle atomic load reserved / store conditional
+  generate
+    if (`A_SUPPORTED) begin // atomic instructions supported
+      logic [`PA_BITS-1:2] ReservationPAdrW;
+      logic             ReservationValidM, ReservationValidW; 
+      logic             lrM, scM, WriteAdrMatchM;
+
+      assign lrM = MemReadM && AtomicM[0];
+      assign scM = MemRWM[0] && AtomicM[0]; 
+      assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`PA_BITS-1:2] == ReservationPAdrW) && ReservationValidW;
+      assign SquashSCM = scM && ~WriteAdrMatchM;
+      always_comb begin // ReservationValidM (next value of valid reservation)
+        if (lrM) ReservationValidM = 1;  // set valid on load reserve
+        else if (scM || WriteAdrMatchM) ReservationValidM = 0; // clear valid on store to same address or any sc
+        else ReservationValidM = ReservationValidW; // otherwise don't change valid
+      end
+      flopenrc #(`PA_BITS-2) resadrreg(clk, reset, FlushW, lrM, MemPAdrM[`PA_BITS-1:2], ReservationPAdrW); // could drop clear on this one but not valid
+      flopenrc #(1) resvldreg(clk, reset, FlushW, lrM, ReservationValidM, ReservationValidW);
+      flopenrc #(1) squashreg(clk, reset, FlushW, ~StallW, SquashSCM, SquashSCW);
+    end else begin // Atomic operations not supported
+      assign SquashSCM = 0;
+      assign SquashSCW = 0; 
+    end
+  endgenerate
+
+  // Data stall
+  //assign DataStall = 0;
+
+  // Ross Thompson April 22, 2021
+  // for now we need to handle the issue where the data memory interface repeately
+  // requests data from memory rather than issuing a single request.
+
+
+  flopr #(2) stateReg(.clk(clk),
+		      .reset(reset),
+		      .d(NextState),
+		      .q(CurrState));
+
+  always_comb begin
+    case (CurrState)
+      STATE_READY: if (MemRWM[1] & MemRWM[0]) NextState = STATE_FETCH_AMO; // *** should be some misalign check
+                   else if (MemAccessM & ~DataMisalignedM) NextState = STATE_FETCH;
+                   else                                    NextState = STATE_READY;
+      STATE_FETCH_AMO: if (MemAckW)                        NextState = STATE_FETCH;
+                       else                                NextState = STATE_FETCH_AMO;
+      STATE_FETCH: if (MemAckW & ~StallW)     NextState = STATE_READY;
+                   else if (MemAckW & StallW) NextState = STATE_STALLED;
+		   else                       NextState = STATE_FETCH;
+      STATE_STALLED: if (~StallW)             NextState = STATE_READY;
+                     else                     NextState = STATE_STALLED;
+      default: NextState = STATE_READY;
+    endcase // case (CurrState)
+  end
+
+endmodule
+
diff --git a/wally-pipelined/src/mmu/pmaadrdec.sv b/wally-pipelined/src/mmu/adrdec.sv
similarity index 98%
rename from wally-pipelined/src/mmu/pmaadrdec.sv
rename to wally-pipelined/src/mmu/adrdec.sv
index c48cdc66..e2c63731 100644
--- a/wally-pipelined/src/mmu/pmaadrdec.sv
+++ b/wally-pipelined/src/mmu/adrdec.sv
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////
-// pmaadrdec.sv
+// adrdec.sv
 //
 // Written: David_Harris@hmc.edu 29 January 2021
 // Modified: 
@@ -25,7 +25,7 @@
 
 `include "wally-config.vh"
 
-module pmaadrdec (
+module adrdec (
   input  logic [31:0] HADDR,
   input  logic [31:0] Base, Range,
   input  logic        Supported,
diff --git a/wally-pipelined/src/mmu/adrdecs.sv b/wally-pipelined/src/mmu/adrdecs.sv
new file mode 100644
index 00000000..17f78d51
--- /dev/null
+++ b/wally-pipelined/src/mmu/adrdecs.sv
@@ -0,0 +1,44 @@
+///////////////////////////////////////////
+// adrdecs.sv
+//
+// Written: David_Harris@hmc.edu 22 June 2021
+// Modified: 
+//
+// Purpose: All the address decoders for peripherals
+// 
+// A component of the Wally configurable RISC-V project.
+// 
+// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
+// is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
+// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
+// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+///////////////////////////////////////////
+
+`include "wally-config.vh"
+
+module adrdecs (
+  input  logic [31:0] HADDR, // *** will need to use PAdr in mmu, stick with HADDR in uncore
+  input  logic        AccessRW, AccessRX, AccessRWX,
+  input  logic [2:0]  HSIZE,
+  output logic [5:0]  HSELRegions
+);
+
+ // Determine which region of physical memory (if any) is being accessed
+ // *** eventually uncomment Access signals
+  adrdec boottimdec(HADDR, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, 1'b1/*AccessRX*/, HSIZE, 4'b1111, HSELRegions[5]);
+  adrdec timdec(HADDR, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, 1'b1/*AccessRWX*/, HSIZE, 4'b1111, HSELRegions[4]);
+  adrdec clintdec(HADDR, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, HSIZE, 4'b1111, HSELRegions[3]);
+  adrdec gpiodec(HADDR, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[2]);
+  adrdec uartdec(HADDR, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, HSIZE, 4'b0001, HSELRegions[1]);
+  adrdec plicdec(HADDR, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[0]);
+endmodule
+
diff --git a/wally-pipelined/src/mmu/pmachecker.sv b/wally-pipelined/src/mmu/pmachecker.sv
index d771839e..1d8cc3ee 100644
--- a/wally-pipelined/src/mmu/pmachecker.sv
+++ b/wally-pipelined/src/mmu/pmachecker.sv
@@ -58,13 +58,7 @@ module pmachecker (
   assign AccessRX = ReadAccessM | ExecuteAccessF;
 
   // Determine which region of physical memory (if any) is being accessed
-  // *** linux tests fail early when Access is anything other than 1b1
-  pmaadrdec boottimdec(HADDR, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, 1'b1/*AccessRX*/, HSIZE, 4'b1111, HSELRegions[5]);
-  pmaadrdec timdec(HADDR, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, 1'b1/*AccessRWX*/, HSIZE, 4'b1111, HSELRegions[4]);
-  pmaadrdec clintdec(HADDR, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, HSIZE, 4'b1111, HSELRegions[3]);
-  pmaadrdec gpiodec(HADDR, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[2]);
-  pmaadrdec uartdec(HADDR, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, HSIZE, 4'b0001, HSELRegions[1]);
-  pmaadrdec plicdec(HADDR, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[0]);
+  adrdecs adrdecs(HADDR, AccessRW, AccessRX, AccessRWX, HSIZE, HSELRegions);
 
   // Only RAM memory regions are cacheable
   assign Cacheable = HSELRegions[5] | HSELRegions[4];
diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv
index e87ef570..cb0a8c2a 100644
--- a/wally-pipelined/src/uncore/uncore.sv
+++ b/wally-pipelined/src/uncore/uncore.sv
@@ -47,8 +47,6 @@ module uncore (
   input  logic [2:0]       HADDRD,
   input  logic [3:0]       HSIZED,
   input  logic             HWRITED,
-  // PMA checker signals
-  input  logic             AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,
   // bus interface
   // PMA checker now handles access faults. *** This can be deleted
   // output logic             DataAccessFaultM,
@@ -74,7 +72,9 @@ module uncore (
   logic [1:0]      MemRWboottim;
   logic            UARTIntr,GPIOIntr;
 
-  pmachecker ebuAdrDec(.PhysicalAddress('0),.Size('0),.Cacheable(),.Idempotent(),.AtomicAllowed(),.PMASquashBusAccess(),.PMAInstrAccessFaultF(),.PMALoadAccessFaultM(),.PMAStoreAccessFaultM(),.*);
+  // Determine which region of physical memory (if any) is being accessed
+  // Use a trimmed down portion of the PMA checker - only the address decoders
+  adrdecs adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE, HSELRegions);
 
   // unswizzle HSEL signals
   assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions;
diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv
index 232c7a03..8e71f445 100644
--- a/wally-pipelined/src/wally/wallypipelinedhart.sv
+++ b/wally-pipelined/src/wally/wallypipelinedhart.sv
@@ -52,9 +52,7 @@ module wallypipelinedhart (
   // Delayed signals for subword write
   output logic [2:0]       HADDRD,
   output logic [3:0]       HSIZED,
-  output logic             HWRITED,
-  // Access signals for PMA decoder
-  output logic             AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM
+  output logic             HWRITED
 );
 
    //  logic [1:0]  ForwardAE, ForwardBE;
@@ -117,7 +115,7 @@ module wallypipelinedhart (
   logic [1:0]       PageTypeF, PageTypeM;
 
   // PMA checker signals
-  //logic             AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM;
+  logic             AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM;
   logic             PMPInstrAccessFaultF, PMPLoadAccessFaultM, PMPStoreAccessFaultM;
   logic             PMAInstrAccessFaultF, PMALoadAccessFaultM, PMAStoreAccessFaultM;
   logic             DSquashBusAccessM, ISquashBusAccessF;
diff --git a/wally-pipelined/src/wally/wallypipelinedsoc.sv b/wally-pipelined/src/wally/wallypipelinedsoc.sv
index cb20f806..c85f5d4f 100644
--- a/wally-pipelined/src/wally/wallypipelinedsoc.sv
+++ b/wally-pipelined/src/wally/wallypipelinedsoc.sv
@@ -62,7 +62,6 @@ module wallypipelinedsoc (
   logic             HREADY, HRESP;
   logic [5:0]       HSELRegions;
   logic             InstrAccessFaultF, DataAccessFaultM;
-  logic             AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM; // to uncore PMA decoder
   logic             TimerIntM, SwIntM; // from CLINT
   logic [63:0]      MTIME_CLINT, MTIMECMP_CLINT; // from CLINT to CSRs
   logic             ExtIntM; // from PLIC