From b43a8885cd5f782f45126cd24bcc6e67dbbd3e36 Mon Sep 17 00:00:00 2001 From: bbracker Date: Tue, 22 Jun 2021 18:28:08 -0400 Subject: [PATCH 1/5] give EBU a dedicated PMA unit as just an address decoder --- wally-pipelined/src/uncore/uncore.sv | 5 ++++- wally-pipelined/src/wally/wallypipelinedhart.sv | 6 ++++-- wally-pipelined/src/wally/wallypipelinedsoc.sv | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index a100d76f9..e87ef5703 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -48,7 +48,7 @@ module uncore ( input logic [3:0] HSIZED, input logic HWRITED, // PMA checker signals - input logic [5:0] HSELRegions, + input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // bus interface // PMA checker now handles access faults. *** This can be deleted // output logic DataAccessFaultM, @@ -64,6 +64,7 @@ module uncore ( logic [`XLEN-1:0] HWDATA; logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART; + logic [5:0] HSELRegions; logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART; logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD; logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART; @@ -73,6 +74,8 @@ module uncore ( logic [1:0] MemRWboottim; logic UARTIntr,GPIOIntr; + pmachecker ebuAdrDec(.PhysicalAddress('0),.Size('0),.Cacheable(),.Idempotent(),.AtomicAllowed(),.PMASquashBusAccess(),.PMAInstrAccessFaultF(),.PMALoadAccessFaultM(),.PMAStoreAccessFaultM(),.*); + // 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 8d02978a5..9d2834fa0 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -52,7 +52,9 @@ module wallypipelinedhart ( // Delayed signals for subword write output logic [2:0] HADDRD, output logic [3:0] HSIZED, - output logic HWRITED + output logic HWRITED, + // Access signals for PMA decoder + output logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM ); // logic [1:0] ForwardAE, ForwardBE; @@ -116,7 +118,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 c85f5d4f4..cb20f806d 100644 --- a/wally-pipelined/src/wally/wallypipelinedsoc.sv +++ b/wally-pipelined/src/wally/wallypipelinedsoc.sv @@ -62,6 +62,7 @@ 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 From 6dc54acde8d9ca7e36fa028f226bb679bdceb7a5 Mon Sep 17 00:00:00 2001 From: David Harris Date: Tue, 22 Jun 2021 23:03:43 -0400 Subject: [PATCH 2/5] renamed dmem to lsu and removed adrdec module from pmpadrdec --- wally-pipelined/src/dmem/dcache.sv | 184 ---------------- wally-pipelined/src/dmem/dmem.sv | 197 ------------------ wally-pipelined/src/mmu/adrdec.sv | 44 ---- wally-pipelined/src/mmu/pmpadrdec.sv | 7 +- .../src/wally/wallypipelinedhart.sv | 2 +- 5 files changed, 6 insertions(+), 428 deletions(-) delete mode 100644 wally-pipelined/src/dmem/dcache.sv delete mode 100644 wally-pipelined/src/dmem/dmem.sv delete mode 100644 wally-pipelined/src/mmu/adrdec.sv diff --git a/wally-pipelined/src/dmem/dcache.sv b/wally-pipelined/src/dmem/dcache.sv deleted file mode 100644 index fec70ef4b..000000000 --- a/wally-pipelined/src/dmem/dcache.sv +++ /dev/null @@ -1,184 +0,0 @@ -/////////////////////////////////////////// -// 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/dmem/dmem.sv b/wally-pipelined/src/dmem/dmem.sv deleted file mode 100644 index 7f19bc78f..000000000 --- a/wally-pipelined/src/dmem/dmem.sv +++ /dev/null @@ -1,197 +0,0 @@ -/////////////////////////////////////////// -// dmem.sv -// -// Written: David_Harris@hmc.edu 9 January 2021 -// Modified: -// -// Purpose: Data memory -// 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 dmem ( - 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/adrdec.sv b/wally-pipelined/src/mmu/adrdec.sv deleted file mode 100644 index 7e4423ec1..000000000 --- a/wally-pipelined/src/mmu/adrdec.sv +++ /dev/null @@ -1,44 +0,0 @@ -/////////////////////////////////////////// -// adrdec.sv -// -// Written: David_Harris@hmc.edu 29 January 2021 -// Modified: -// -// Purpose: Address decoder -// -// 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 adrdec ( - input logic [31:0] HADDR, - input logic [31:0] Base, Range, - output logic HSEL -); - - logic [31:0] match; - - // determine if an address is in a range starting at the base - // for example, if Base = 0x04002000 and range = 0x00000FFF, - // then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1) - - assign match = (HADDR ~^ Base) | Range; - assign HSEL = &match; - -endmodule - diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index f9e86cdc7..f3e874a3d 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -65,7 +65,9 @@ module pmpadrdec ( assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; // Naturally aligned four-byte region - adrdec na4dec(HADDR, CurrentAdrFull, (2**2)-1, NA4Match); + // *** need to switch to Physical Address and extend to proper number of bits + assign NA4Match = &(HADDR[31:2] ~^ CurrentAdrFull[31:2]); // check if address matches all but bottom 2 bits; + //adrdec na4dec(HADDR, CurrentAdrFull, (2**2)-1, NA4Match); generate if (`XLEN == 32 || `XLEN == 64) begin @@ -116,7 +118,8 @@ module pmpadrdec ( // *** Range should not be truncated... but our physical address space is // currently only 32 bits wide. - adrdec napotdec(HADDR, CurrentAdrFull, Range[31:0], NAPOTMatch); + // with a bit of combining of range selection, this could be shared with NA4Match *** + assign NAPOTMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]); assign Match = (AdrMode == TOR) ? TORMatch : (AdrMode == NA4) ? NA4Match : diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index b63fbc21a..232c7a030 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -163,7 +163,7 @@ module wallypipelinedhart ( mux2 #(`XLEN) OutputInput2mux(WriteDataM, FWriteDataM, FMemRWM[0], WriteDatatmpM); - dmem dmem(.MemRWM(MemRWM|FMemRWM), .WriteDataM(WriteDatatmpM),.*); // data cache unit + lsu lsu(.MemRWM(MemRWM|FMemRWM), .WriteDataM(WriteDatatmpM),.*); // data cache unit ahblite ebu( //.InstrReadF(1'b0), From 1972d8300237f1de00f3ad0dfb33da8385f76a89 Mon Sep 17 00:00:00 2001 From: David Harris Date: Wed, 23 Jun 2021 01:41:00 -0400 Subject: [PATCH 3/5] 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 000000000..fec70ef4b --- /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 000000000..ffa79adfe --- /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 c48cdc665..e2c63731b 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 000000000..17f78d515 --- /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 d771839e8..1d8cc3ee3 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 e87ef5703..cb0a8c2ac 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 232c7a030..8e71f4452 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 cb20f806d..c85f5d4f4 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 From 4189b2d4a7bc7404a260e232872ff01388b1f265 Mon Sep 17 00:00:00 2001 From: David Harris Date: Wed, 23 Jun 2021 02:31:50 -0400 Subject: [PATCH 4/5] Reduced complexity of pmpadrdec --- wally-pipelined/src/mmu/pmpadrdec.sv | 61 ++++++++++++++++------------ 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index f3e874a3d..11c239b2f 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -30,11 +30,8 @@ `include "wally-config.vh" module pmpadrdec ( - input logic [31:0] HADDR, - + input logic [31:0] HADDR, // *** replace with PAdr input logic [1:0] AdrMode, - - // input logic [`XLEN-1:0] PreviousPMPAdr, input logic [`XLEN-1:0] CurrentPMPAdr, input logic AdrAtLeastPreviousPMP, output logic AdrAtLeastCurrentPMP, @@ -45,37 +42,48 @@ module pmpadrdec ( localparam NA4 = 2'b10; localparam NAPOT = 2'b11; - logic TORMatch, NA4Match, NAPOTMatch; - + logic TORMatch, NAMatch; logic AdrBelowCurrentPMP; + logic [`PA_BITS-1:0] CurrentAdrFull; + logic [`PA_BITS-1:0] FakePhysAdr; - logic [31:0] CurrentAdrFull; - // logic [31:0] PreviousAdrFull; - - logic [33:0] Range; - - //assign PreviousAdrFull = {PreviousPMPAdr[29:0], 2'b00}; - assign CurrentAdrFull = {CurrentPMPAdr[29:0], 2'b00}; - + // ***replace this when the true physical address from MMU is available + assign FakePhysAdr = {{(`PA_BITS-32){1'b0}}, HADDR}; + // Top-of-range (TOR) - // *** Check if this synthesizes - // if not, literally do comparison (HADDR - PreviousAdrFull == 0) - assign AdrBelowCurrentPMP = HADDR < CurrentAdrFull; + // Append two implicit trailing 0's to PMPAdr value + assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00}; + assign AdrBelowCurrentPMP = /*HADDR */FakePhysAdr < CurrentAdrFull; // *** make sure unsigned comparison works correctly assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP; assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; - // Naturally aligned four-byte region - // *** need to switch to Physical Address and extend to proper number of bits - assign NA4Match = &(HADDR[31:2] ~^ CurrentAdrFull[31:2]); // check if address matches all but bottom 2 bits; - //adrdec na4dec(HADDR, CurrentAdrFull, (2**2)-1, NA4Match); + // Naturally aligned regions + // *** should be able to optimize away bottom 2 bits + // verilator lint_off UNOPTFLAT + logic [`PA_BITS-1:0] Mask; + genvar i; + + // create a mask of which bits to ignore generate - if (`XLEN == 32 || `XLEN == 64) begin + assign Mask[1:0] = 2'b11; + assign Mask[2] = ~CurrentPMPAdr[0] & (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region + for (i=3; i < `PA_BITS; i=i+1) + assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore + endgenerate + // verilator lint_on UNOPTFLAT + + assign NAMatch = &((FakePhysAdr ~^ CurrentAdrFull) | Mask); + + /* generate + if (`XLEN == 32 || `XLEN == 64) begin // ***redo for various sizes // priority encoder to translate address to range // *** We'd like to replace this with a better priority encoder // *** We should not be truncating 64 bit physical addresses to 32 bits... + // *** there is an easy combinatinoal way to do this with a cascade of AND gates O(32) rather than O(32^2) dh always_comb - casez (CurrentPMPAdr[31:0]) + if (AdrMode == NA4) Range = (2**2) - 1; + else casez (CurrentPMPAdr[31:0]) // NAPOT regions 32'b???????????????????????????????0: Range = (2**3) - 1; 32'b??????????????????????????????01: Range = (2**4) - 1; 32'b?????????????????????????????011: Range = (2**5) - 1; @@ -114,16 +122,15 @@ module pmpadrdec ( end else begin assign Range = '0; end - endgenerate + endgenerate // *** Range should not be truncated... but our physical address space is // currently only 32 bits wide. // with a bit of combining of range selection, this could be shared with NA4Match *** - assign NAPOTMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]); + assign NAMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]);*/ assign Match = (AdrMode == TOR) ? TORMatch : - (AdrMode == NA4) ? NA4Match : - (AdrMode == NAPOT) ? NAPOTMatch : + (AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch : 0; endmodule From 718630c3789e7f4d741ebd408ea6deb433624787 Mon Sep 17 00:00:00 2001 From: David Harris Date: Wed, 23 Jun 2021 03:03:52 -0400 Subject: [PATCH 5/5] Reduced complexity of pmpadrdec --- .../regression/wave-dos/peripheral-waves.do | 22 +++++++++---------- wally-pipelined/src/mmu/pmpadrdec.sv | 2 +- wally-pipelined/src/mmu/pmpchecker.sv | 4 ++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/wally-pipelined/regression/wave-dos/peripheral-waves.do b/wally-pipelined/regression/wave-dos/peripheral-waves.do index 5c9f38703..1304b40c6 100644 --- a/wally-pipelined/regression/wave-dos/peripheral-waves.do +++ b/wally-pipelined/regression/wave-dos/peripheral-waves.do @@ -65,17 +65,17 @@ add wave -hex /testbench/dut/hart/priv/csr/genblk1/csrm/MEPC_REGW add wave -divider # peripherals -add wave -hex /testbench/dut/uncore/plic/* -add wave -hex /testbench/dut/uncore/plic/intPriority -add wave -hex /testbench/dut/uncore/plic/pendingArray -add wave -divider -add wave -hex /testbench/dut/uncore/uart/u/* -add wave -divider -add wave -hex /testbench/dut/uncore/gpio/* -add wave -divider -add wave -hex /testbench/dut/hart/ebu/* -add wave -divider -add wave -divider +#add wave -hex /testbench/dut/uncore/plic/* +#add wave -hex /testbench/dut/uncore/plic/intPriority +#add wave -hex /testbench/dut/uncore/plic/pendingArray +#add wave -divider +#add wave -hex /testbench/dut/uncore/uart/u/* +#add wave -divider +#add wave -hex /testbench/dut/uncore/gpio/* +#add wave -divider +#add wave -hex /testbench/dut/hart/ebu/* +#add wave -divider +#add wave -divider # everything else add wave -hex -r /testbench/* diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index 11c239b2f..87f5d8f1e 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -67,7 +67,7 @@ module pmpadrdec ( // create a mask of which bits to ignore generate assign Mask[1:0] = 2'b11; - assign Mask[2] = ~CurrentPMPAdr[0] & (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region + assign Mask[2] = (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region for (i=3; i < `PA_BITS; i=i+1) assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore endgenerate diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 8b33ccf3a..f88d56fa0 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -76,6 +76,8 @@ module pmpchecker ( logic L_Bit, X_Bit, W_Bit, R_Bit; logic InvalidExecute, InvalidWrite, InvalidRead; + // *** extend to optionally 64 configurations + assign {PMPCFG[15], PMPCFG[14], PMPCFG[13], PMPCFG[12], PMPCFG[11], PMPCFG[10], PMPCFG[9], PMPCFG[8]} = PMPCFG23_REGW; @@ -107,6 +109,7 @@ module pmpchecker ( // Only enforce PMP checking for S and U modes when at least one PMP is active assign EnforcePMP = |ActiveRegion; + // *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region always_comb casez (Regions) 16'b???????????????1: MatchedRegion = 0; @@ -137,6 +140,7 @@ module pmpchecker ( assign InvalidWrite = WriteAccessM && ~W_Bit; assign InvalidRead = ReadAccessM && ~R_Bit; + // *** don't cause faults when there are no PMPs assign PMPInstrAccessFaultF = (PrivilegeModeW == `M_MODE) ? Match && L_Bit && InvalidExecute : EnforcePMP && InvalidExecute;