cvw/src/lsu/lsu.sv

437 lines
28 KiB
Systemverilog
Raw Normal View History

2023-01-11 23:15:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// lsu.sv
//
2023-01-11 23:15:07 +00:00
// Written: David_Harris@hmc.edu, ross1728@gmail.com
// Created: 9 January 2021
// Modified: 11 January 2023
//
// Purpose: Load/Store Unit
2023-01-12 00:52:46 +00:00
// HPTW, DMMU, data cache, interface to external bus
// Atomic, Endian swap, and subword read/write logic
//
// Documentation: RISC-V System on Chip Design Chapter 9 (Figure 9.2)
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// 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
//
// 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.
2023-01-11 23:15:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////
2023-05-24 21:12:41 +00:00
module lsu import cvw::*; #(parameter cvw_t P) (
2023-06-12 20:29:18 +00:00
input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW,
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
2023-01-16 02:23:09 +00:00
// connected to cpu (controls)
input logic [1:0] MemRWE, // Read/Write control
2023-06-12 20:29:18 +00:00
input logic [1:0] MemRWM, // Read/Write control
input logic [2:0] Funct3M, // Size of memory operation
input logic [6:0] Funct7M, // Atomic memory operation function
input logic [1:0] AtomicM, // Atomic memory operation
input logic FlushDCacheM, // Flush D cache to next level of memory
input logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
input logic LSUPrefetchM, // Prefetch; presently unused
2023-06-12 20:29:18 +00:00
output logic CommittedM, // Delay interrupts while memory operation in flight
output logic SquashSCW, // Store conditional failed disable write to GPR
output logic DCacheMiss, // D cache miss for performance counters
output logic DCacheAccess, // D cache memory access for performance counters
2023-01-16 02:23:09 +00:00
// address and write data
2023-06-12 20:29:18 +00:00
input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
2023-01-16 02:23:09 +00:00
// cpu privilege
2023-06-12 20:29:18 +00:00
input logic [1:0] PrivilegeModeW, // Current privilege mode
input logic BigEndianM, // Swap byte order to big endian
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic DCacheStallM, // D$ busy with multicycle operation
2023-01-16 02:23:09 +00:00
// fpu
2023-06-12 20:29:18 +00:00
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
input logic FpLoadStoreM, // Selects FPU as store for write data
2023-01-16 02:23:09 +00:00
// faults
2023-06-12 20:29:18 +00:00
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
output logic LoadMisalignedFaultM, // Load address misaligned fault
output logic LoadAccessFaultM, // Load access fault (PMA)
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
output logic HPTWInstrPageFaultF, // HPTW generated access fault during instruction fetch
2023-01-16 02:23:09 +00:00
// cpu hazard unit (trap)
2023-06-12 20:29:18 +00:00
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
output logic StoreAmoAccessFaultM, // Store or AMO access fault
2023-01-23 23:27:39 +00:00
// connect to ahb
2023-06-12 20:29:18 +00:00
output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
input logic LSUHREADY, // Bus ready from LSU to EBU
output logic LSUHWRITE, // Bus write operation from LSU to EBU
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
2023-01-23 23:27:39 +00:00
// page table walker
2023-06-12 20:29:18 +00:00
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
input logic ENVCFG_PBMTE, // Page-based memory types enabled
2023-12-13 19:49:04 +00:00
input logic ENVCFG_ADUE, // HPTW A/D Update enable
2023-06-12 20:29:18 +00:00
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
output logic [P.XLEN-1:0] PTE, // Page table entry write to ITLB
output logic [1:0] PageType, // Type of page table entry to write to ITLB
output logic ITLBWriteF, // Write PTE to ITLB
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
2023-01-16 02:23:09 +00:00
);
localparam logic MISALIGN_SUPPORT = P.ZICCLSM_SUPPORTED & P.DCACHE_SUPPORTED;
2023-11-15 16:30:48 +00:00
localparam MLEN = MISALIGN_SUPPORT ? 2*P.LLEN : P.LLEN; // widen buffer for misaligned accessess
2023-05-24 21:12:41 +00:00
logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [P.XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
2023-01-12 00:52:46 +00:00
2023-06-12 20:29:18 +00:00
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
2023-01-12 00:52:46 +00:00
2023-06-12 20:29:18 +00:00
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
2023-03-24 22:32:25 +00:00
2023-06-12 20:29:18 +00:00
logic BusStall; // Bus interface busy with multicycle operation
logic HPTWStall; // HPTW busy with multicycle operation
logic CacheBusHPWTStall; // Cache, bus, or hptw is requesting a stall
logic SelSpillE; // Align logic detected a spill and needs to stall
2023-01-12 00:52:46 +00:00
2023-06-12 20:29:18 +00:00
logic CacheableM; // PMA indicates memory address is cacheable
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
2023-01-12 00:52:46 +00:00
2023-05-24 21:12:41 +00:00
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
/* verilator lint_off WIDTHEXPAND */
logic [MLEN-1:0] DCacheReadDataWordM; // D$ read data
logic [MLEN-1:0] LSUWriteDataSpillM; // Final write data
logic [MLEN/8-1:0] ByteMaskSpillM; // Selects which bytes within a word to write
/* verilator lint_on WIDTHEXPAND */
logic [P.LLEN-1:0] DCacheReadDataWordSpillM; // D$ read data
2023-05-24 21:12:41 +00:00
logic [P.LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data
logic [P.LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data
logic [P.LLEN-1:0] ReadDataWordM; // Read data before subword selection
logic [P.LLEN-1:0] ReadDataM; // Final read data
2023-01-12 00:52:46 +00:00
2023-05-24 21:12:41 +00:00
logic [P.XLEN-1:0] IHWriteDataM; // IEU or HPTW write data
logic [P.XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data
logic [P.LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data
logic [P.LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data
logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
logic [(P.LLEN-1)/8:0] ByteMaskExtendedM; // Selects which bytes within a word to write
logic [1:0] MemRWSpillM;
logic SpillStallM;
logic SelStoreDelay;
2023-06-12 20:29:18 +00:00
logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
logic LSULoadAccessFaultM; // Load acces fault
logic LSUStoreAmoAccessFaultM; // Store access fault
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
logic SelDTIM; // Select DTIM rather than bus or D$
2023-11-27 20:59:42 +00:00
logic [P.XLEN-1:0] WriteDataZM;
logic LSULoadPageFaultM, LSUStoreAmoPageFaultM;
2023-11-27 20:59:42 +00:00
2023-01-12 00:52:46 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// Pipeline for IEUAdr E to M
// Zero-extend address to 34 bits for XLEN=32
/////////////////////////////////////////////////////////////////////////////////////////////
2023-05-24 21:12:41 +00:00
flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
if(MISALIGN_SUPPORT) begin : ziccslm_align
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M,
2023-11-28 20:19:30 +00:00
.MemRWM,
2023-11-28 20:21:37 +00:00
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
2023-11-28 20:19:30 +00:00
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM,
.SelStoreDelay);
assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
end else begin : no_ziccslm_align
assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE};
assign SelSpillE = '0;
assign DCacheReadDataWordSpillM = DCacheReadDataWordM;
2023-10-30 19:00:49 +00:00
assign ByteMaskSpillM = ByteMaskM;
assign LSUWriteDataSpillM = LSUWriteDataM;
assign MemRWSpillM = MemRWM;
assign {SpillStallM, SelStoreDelay} = '0;
end
2022-01-31 18:11:42 +00:00
2023-11-27 20:59:42 +00:00
if(P.ZICBOZ_SUPPORTED) begin : cboz
mux2 #(P.XLEN) writedatacbozmux(WriteDataM, '0, CMOpM[3], WriteDataZM);
end else begin : cboz
assign WriteDataZM = WriteDataM;
end
2022-01-31 18:11:42 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2023-01-12 00:52:46 +00:00
// HPTW (only needed if VM supported)
2022-01-31 18:11:42 +00:00
// MMU include PMP and is needed if any privileged supported
/////////////////////////////////////////////////////////////////////////////////////////////
2022-01-05 16:25:08 +00:00
2023-05-24 21:12:41 +00:00
if(P.VIRTMEM_SUPPORTED) begin : hptw
hptw #(P) hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
2023-02-27 01:51:45 +00:00
.DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM,
2023-03-06 23:50:57 +00:00
.FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF,
2023-12-13 19:49:04 +00:00
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_ADUE, .PrivilegeModeW,
2023-05-24 21:12:41 +00:00
.ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
2023-11-27 20:59:42 +00:00
.WriteDataM(WriteDataZM), .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
2022-11-13 18:27:48 +00:00
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
2022-12-11 21:48:00 +00:00
.IHAdrM, .HPTWStall, .SelHPTW,
.IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM,
.LoadAccessFaultM, .StoreAmoAccessFaultM, .HPTWInstrAccessFaultF,
.LoadPageFaultM, .StoreAmoPageFaultM, .LSULoadPageFaultM, .LSUStoreAmoPageFaultM, .HPTWInstrPageFaultF
);
2023-01-12 00:52:46 +00:00
end else begin // No HPTW, so signals are not multiplexed
2022-12-11 21:48:00 +00:00
assign PreLSURWM = MemRWM;
2022-09-13 16:47:39 +00:00
assign IHAdrM = IEUAdrExtM;
2023-01-12 00:52:46 +00:00
assign LSUFunct3M = Funct3M;
assign LSUFunct7M = Funct7M;
assign LSUAtomicM = AtomicM;
2023-11-27 20:59:42 +00:00
assign IHWriteDataM = WriteDataZM;
assign LoadAccessFaultM = LSULoadAccessFaultM;
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
assign LoadPageFaultM = LSULoadPageFaultM;
assign StoreAmoPageFaultM = LSUStoreAmoPageFaultM;
2023-01-12 00:52:46 +00:00
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = '0;
2022-01-15 00:24:16 +00:00
end
2023-01-12 00:52:46 +00:00
// CommittedM indicates the cache, bus, or HPTW are busy with a multiple cycle operation.
// CommittedM is 1 after the first cycle and until the last cycle. Partially completed memory
// operations delay interrupts until the next instruction by suppressing pending interrupts in
// the trap module.
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
2022-12-11 21:52:51 +00:00
assign GatedStallW = StallW & ~SelHPTW;
assign CacheBusHPWTStall = DCacheStallM | HPTWStall | BusStall;
assign LSUStallM = CacheBusHPWTStall | SpillStallM;
2023-01-12 00:52:46 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// MMU and misalignment fault logic required if privileged unit exists
/////////////////////////////////////////////////////////////////////////////////////////////
2023-05-24 21:12:41 +00:00
if(P.ZICSR_SUPPORTED == 1) begin : dmmu
2023-01-12 00:52:46 +00:00
logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation
logic WriteAccessM;
2022-02-19 20:38:17 +00:00
assign DisableTranslation = SelHPTW | FlushDCacheM;
assign WriteAccessM = PreLSURWM[0];
2023-05-24 21:12:41 +00:00
mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0))
2023-12-13 19:49:04 +00:00
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE,
2023-01-12 00:52:46 +00:00
.PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
.PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM),
.PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM),
.InstrAccessFaultF(), .LoadAccessFaultM(LSULoadAccessFaultM),
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM(LSULoadPageFaultM),
.StoreAmoPageFaultM(LSUStoreAmoPageFaultM),
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
2023-12-25 13:57:41 +00:00
.UpdateDA(DataUpdateDAM), .CMOpM(CMOpM),
2022-02-19 20:38:17 +00:00
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
.WriteAccessM, .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
2022-01-05 16:25:08 +00:00
2023-01-12 00:52:46 +00:00
end else begin // No MMU, so no PMA/page faults and no address translation
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = '0;
2023-05-24 21:12:41 +00:00
assign PAdrM = IHAdrM[P.PA_BITS-1:0];
2023-01-12 00:52:46 +00:00
assign CacheableM = 1'b1;
2023-05-24 21:12:41 +00:00
assign SelDTIM = P.DTIM_SUPPORTED & ~P.BUS_SUPPORTED; // if no PMA then select dtim if there is a DTIM. If there is
// a bus then this is always 0. Cannot have both without PMA.
2022-01-05 16:25:08 +00:00
end
2022-01-31 18:11:42 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2023-01-12 00:52:46 +00:00
// Memory System (options)
// 1. DTIM
// 2. DTIM and bus
// 3. Bus
// 4. Cache and bus
2022-01-31 18:11:42 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2023-01-12 00:52:46 +00:00
// Pause IEU memory request if TLB miss. After TLB fill, replay request.
// Discard memory request on pipeline flush
assign IgnoreRequest = IgnoreRequestTLB | FlushW;
2023-05-24 21:12:41 +00:00
if (P.DTIM_SUPPORTED) begin : dtim
logic [P.PA_BITS-1:0] DTIMAdr;
2023-06-12 20:29:18 +00:00
logic [1:0] DTIMMemRWM;
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point.
2023-10-27 14:35:44 +00:00
// Add support for cboz
dtim #(P) dtim(.clk, .reset, .ce(~GatedStallW), .MemRWE(MemRWE), // *** update when you update the cache RWE
.MemRWM(DTIMMemRWM),
2023-01-19 00:44:30 +00:00
.DTIMAdr, .FlushW, .WriteDataM(LSUWriteDataM),
.ReadDataWordM(DTIMReadDataWordM[P.LLEN-1:0]), .ByteMaskM(ByteMaskM));
end
2023-05-24 21:12:41 +00:00
if (P.BUS_SUPPORTED) begin : bus
if(P.DCACHE_SUPPORTED) begin : dcache
localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
2023-06-12 20:29:18 +00:00
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
2023-05-24 21:12:41 +00:00
localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
2023-06-12 20:29:18 +00:00
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
2023-05-24 21:12:41 +00:00
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
localparam CACHEWORDLEN = P.ZICCLSM_SUPPORTED ? 2*P.LLEN : P.LLEN; // Width of the cache's input and output data buses. Misaligned doubles width for fast access
2023-01-18 22:47:40 +00:00
2023-06-12 20:29:18 +00:00
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
logic [1:0] BusRW; // Uncached bus memory access
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
logic CacheStall;
logic [1:0] CacheBusRWTemp;
logic BusCMOZero;
logic [3:0] CacheCMOpM;
logic BusAtomic;
if(P.ZICBOZ_SUPPORTED) begin
assign BusCMOZero = CMOpM[3] & ~CacheableM;
2024-01-02 18:16:20 +00:00
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : '0;
assign BusAtomic = AtomicM[1] & ~CacheableM;
end else begin
assign BusCMOZero = '0;
assign CacheCMOpM = '0;
assign BusAtomic = '0;
end
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0;
2022-10-17 17:34:14 +00:00
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0;
assign FlushDCache = FlushDCacheM & ~(SelHPTW);
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(CACHEWORDLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
2023-12-29 22:10:27 +00:00
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM),
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
2023-10-30 19:00:49 +00:00
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW,
.CacheStall, .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
.CacheCommitted(DCacheCommittedM),
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
.FetchBuffer, .CacheBusRW(CacheBusRWTemp),
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0), .CMOpM(CacheCMOpM));
assign DCacheStallM = CacheStall & ~IgnoreRequestTLB;
assign CacheBusRW = CacheBusRWTemp;
2023-01-12 01:06:03 +00:00
2023-10-27 14:35:44 +00:00
// *** add support for cboz
2023-05-24 21:12:41 +00:00
ahbcacheinterface #(.AHBW(P.AHBW), .LLEN(P.LLEN), .PA_BITS(P.PA_BITS), .BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW), .READ_ONLY_CACHE(0)) ahbcacheinterface(
.HCLK(clk), .HRESETn(~reset), .Flush(FlushW | IgnoreRequestTLB),
.HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB),
.HSIZE(LSUHSIZE), .HBURST(LSUHBURST), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HREADY(LSUHREADY),
.BeatCount, .SelBusBeat, .CacheReadDataWordM(DCacheReadDataWordM[P.LLEN-1:0]), .WriteDataM(LSUWriteDataM),
.Funct3(LSUFunct3M), .HADDR(LSUHADDR), .CacheBusAdr(DCacheBusAdr), .CacheBusRW, .BusAtomic, .BusCMOZero, .CacheableOrFlushCacheM,
2022-09-13 16:47:39 +00:00
.CacheBusAck(DCacheBusAck), .FetchBuffer, .PAdr(PAdrM),
2022-12-11 21:52:51 +00:00
.Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW),
.BusStall, .BusCommitted(BusCommittedM));
2023-03-24 22:32:25 +00:00
// Mux between the 3 sources of read data, 0: cache, 1: Bus, 2: DTIM
// Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times.
2023-01-12 01:06:03 +00:00
// *** DTIMReadDataWordM should be increased to LLEN.
// pma should generate exception for LLEN read to periph.
mux3 #(P.LLEN) UnCachedDataMux(.d0(DCacheReadDataWordSpillM), .d1({LLENPOVERAHBW{FetchBuffer[P.XLEN-1:0]}}),
2023-05-24 21:12:41 +00:00
.d2({{P.LLEN-P.XLEN{1'b0}}, DTIMReadDataWordM[P.XLEN-1:0]}),
2022-10-17 17:34:14 +00:00
.s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM));
2023-01-12 01:06:03 +00:00
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
2023-05-24 21:12:41 +00:00
logic [P.XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
2022-08-31 16:21:02 +00:00
2022-09-13 16:47:39 +00:00
assign LSUHADDR = PAdrM;
2022-08-26 03:02:38 +00:00
assign LSUHSIZE = LSUFunct3M;
2023-05-24 21:12:41 +00:00
ahbinterface #(P.XLEN, 1) ahbinterface(.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HREADY(LSUHREADY),
.HRDATA(HRDATA), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HWDATA(LSUHWDATA),
.HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM[P.XLEN-1:0]),
2022-12-11 21:52:51 +00:00
.Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer));
2023-03-24 22:32:25 +00:00
// Mux between the 2 sources of read data, 0: Bus, 1: DTIM
if(P.DTIM_SUPPORTED) mux2 #(P.XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM[P.XLEN-1:0], SelDTIM, ReadDataWordMuxM[P.XLEN-1:0]);
2023-05-24 21:12:41 +00:00
else assign ReadDataWordMuxM = FetchBuffer[P.XLEN-1:0];
2022-08-26 01:30:46 +00:00
assign LSUHBURST = 3'b0;
2023-01-20 18:29:25 +00:00
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
2022-08-27 02:58:04 +00:00
end
2023-01-12 01:06:03 +00:00
end else begin: nobus // block: bus, only DTIM
2022-08-26 01:15:59 +00:00
assign LSUHWDATA = '0;
assign ReadDataWordMuxM = DTIMReadDataWordM;
2022-08-26 01:52:42 +00:00
assign {BusStall, BusCommittedM} = '0;
assign {DCacheMiss, DCacheAccess} = '0;
2023-01-20 18:29:25 +00:00
assign {DCacheStallM, DCacheCommittedM} = '0;
end
2022-01-14 23:55:27 +00:00
2022-01-31 18:11:42 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2022-01-14 23:55:27 +00:00
// Atomic operations
2022-01-31 18:11:42 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2023-06-12 20:29:18 +00:00
2023-05-24 21:12:41 +00:00
if (P.A_SUPPORTED) begin:atomic
2023-05-26 15:47:09 +00:00
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
2022-02-10 17:27:15 +00:00
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
.IMAWriteDataM, .SquashSCW, .LSURWM);
2022-01-14 23:55:27 +00:00
end else begin:lrsc
2022-11-13 18:27:48 +00:00
assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign IMAWriteDataM = IHWriteDataM;
2022-01-14 23:55:27 +00:00
end
2022-03-11 00:44:50 +00:00
2023-05-24 21:12:41 +00:00
if (P.F_SUPPORTED)
mux2 #(P.LLEN) datamux({{{P.LLEN-P.XLEN}{1'b0}}, IMAWriteDataM}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM);
else assign IMAFWriteDataM = IMAWriteDataM;
/////////////////////////////////////////////////////////////////////////////////////////////
// Subword Accesses
/////////////////////////////////////////////////////////////////////////////////////////////
2023-06-12 20:29:18 +00:00
2023-05-26 16:22:44 +00:00
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
2023-03-24 22:32:25 +00:00
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
// Compute byte masks
swbytemask #(P.LLEN, P.ZICCLSM_SUPPORTED) swbytemask(.Size(LSUFunct3M), .Adr(PAdrM[$clog2(P.LLEN/8)-1:0]), .ByteMask(ByteMaskM), .ByteMaskExtended(ByteMaskExtendedM));
2022-06-20 22:53:13 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// MW Pipeline Register
/////////////////////////////////////////////////////////////////////////////////////////////
2023-05-24 21:12:41 +00:00
flopen #(P.LLEN) ReadDataMWReg(clk, ~StallW, ReadDataM, ReadDataW);
/////////////////////////////////////////////////////////////////////////////////////////////
// Big Endian Byte Swapper
// hart works little-endian internally
// swap the bytes when read from big-endian memory
/////////////////////////////////////////////////////////////////////////////////////////////
2023-05-24 21:12:41 +00:00
if (P.BIGENDIAN_SUPPORTED) begin:endian
endianswap #(P.LLEN) storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(LSUWriteDataM));
endianswap #(P.LLEN) loadswap(.BigEndianM, .a(ReadDataWordMuxM), .y(LittleEndianReadDataWordM));
end else begin
assign LSUWriteDataM = LittleEndianWriteDataM;
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
end
endmodule