This commit is contained in:
David Harris 2023-01-11 19:48:37 -08:00
commit 49575dfb90
3 changed files with 174 additions and 152 deletions

View File

@ -1,10 +1,13 @@
///////////////////////////////////////////
// alu.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
// Created: 9 January 2021
// Modified:
//
// Purpose: RISC-V Arithmetic/Logic Unit
//
// Documentation: RISC-V System on Chip Design Chapter 4 (Figure 4.4)
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//

View File

@ -178,7 +178,7 @@ module ifu (
////////////////////////////////////////////////////////////////////////////////////////////////
// Memory
////////////////////////////////////////////////////////////////////////////////////////////////
// CommittedM tells the CPU's privilege unit the current instruction
// CommittedM tells the CPU's privileged unit the current instruction
// in the memory stage is a memory operaton and that memory operation is either completed
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
// There is not a clean way to restore back to a partial executed instruction. CommiteedM will

View File

@ -1,13 +1,16 @@
///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// lsu.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
// Written: David_Harris@hmc.edu, ross1728@gmail.com
// Created: 9 January 2021
// Modified: 11 January 2023
//
// Purpose: Load/Store Unit
// Top level of the memory-stage core logic
// Contains data cache, DTLB, subword read/write datapath, interface to external bus
//
// 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)
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
@ -24,102 +27,125 @@
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
// committed means the memory operation in flight cannot be interrupted.
// chap 5 handling faults to memory by delaying writes to memory stage.
// chap 6 combing bus with dtim
// chap 9 complete lsu.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module lsu (
input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW,
output logic LSUStallM,
input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW,
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation.
// connected to cpu (controls)
input logic [1:0] MemRWM,
input logic [2:0] Funct3M,
input logic [6:0] Funct7M,
input logic [1:0] AtomicM,
input logic FlushDCacheM,
output logic CommittedM,
output logic SquashSCW,
output logic DCacheMiss,
output logic DCacheAccess,
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
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
// address and write data
input logic [`XLEN-1:0] IEUAdrE,
(* mark_debug = "true" *)output logic [`XLEN-1:0] IEUAdrM,
(* mark_debug = "true" *)input logic [`XLEN-1:0] WriteDataM,
output logic [`LLEN-1:0] ReadDataW,
input logic [`XLEN-1:0] IEUAdrE, // Execution stage memory address
(* mark_debug = "true" *) output logic [`XLEN-1:0] IEUAdrM, // Memory stage memory address
(* mark_debug = "true" *) input logic [`XLEN-1:0] WriteDataM, // Write data from IEU
output logic [`LLEN-1:0] ReadDataW, // Read data to IEU or FPU
// cpu privilege
input logic [1:0] PrivilegeModeW,
input logic BigEndianM,
input logic sfencevmaM,
input logic [1:0] PrivilegeModeW, // Current privilege mode
input logic BigEndianM, // Swap byte order to big endian
input logic sfencevmaM, // Virtual memory address fence
// fpu
input logic [`FLEN-1:0] FWriteDataM,
input logic FpLoadStoreM,
input logic [`FLEN-1:0] FWriteDataM, // Write data from FPU
input logic FpLoadStoreM, // Selects FPU as store for write data
// faults
output logic LoadPageFaultM, StoreAmoPageFaultM,
output logic LoadMisalignedFaultM, LoadAccessFaultM, HPTWInstrAccessFaultM,
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
output logic LoadMisalignedFaultM, // Load address misaligned fault
output logic LoadAccessFaultM, // Load access fault (PMA)
output logic HPTWInstrAccessFaultM, // HPTW generated access fault during instruction fetch
// cpu hazard unit (trap)
output logic StoreAmoMisalignedFaultM, StoreAmoAccessFaultM,
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
output logic StoreAmoAccessFaultM, // Store or AMO access fault
// connect to ahb
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUHADDR,
(* mark_debug = "true" *) input logic [`XLEN-1:0] HRDATA,
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUHWDATA,
(* mark_debug = "true" *) input logic LSUHREADY,
(* mark_debug = "true" *) output logic LSUHWRITE,
(* mark_debug = "true" *) output logic [2:0] LSUHSIZE,
(* mark_debug = "true" *) output logic [2:0] LSUHBURST,
(* mark_debug = "true" *) output logic [1:0] LSUHTRANS,
(* mark_debug = "true" *) output logic [`XLEN/8-1:0] LSUHWSTRB,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
(* mark_debug = "true" *) input logic [`XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
(* mark_debug = "true" *) input logic LSUHREADY, // Bus ready from LSU to EBU
(* mark_debug = "true" *) output logic LSUHWRITE, // Bus write operation from LSU to EBU
(* mark_debug = "true" *) output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
(* mark_debug = "true" *) output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
(* mark_debug = "true" *) output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
(* mark_debug = "true" *) output logic [`XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
// page table walker
input logic [`XLEN-1:0] SATP_REGW, // from csr
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
input logic [1:0] STATUS_MPP,
input logic [`XLEN-1:0] PCF,
input logic ITLBMissF,
input logic InstrDAPageFaultF,
output logic [`XLEN-1:0] PTE,
output logic [1:0] PageType,
output logic ITLBWriteF, SelHPTW,
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // *** this one especially has a large note attached to it in pmpchecker.
input logic [`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 [`XLEN-1:0] PCF, // Fetch PC
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrDAPageFaultF, // ITLB hit needs to update dirty or access bits
output logic [`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[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // PMP address from privileged unit
);
logic [`XLEN+1:0] IEUAdrExtM;
logic [`XLEN+1:0] IEUAdrExtE;
logic [`PA_BITS-1:0] PAdrM;
logic DTLBMissM;
logic DTLBWriteM;
logic [1:0] PreLSURWM, LSURWM;
logic [2:0] LSUFunct3M;
logic [6:0] LSUFunct7M;
logic [1:0] LSUAtomicM;
(* mark_debug = "true" *) logic [`XLEN+1:0] IHAdrM;
logic GatedStallW;
logic DCacheStallW;
logic CacheableM;
logic BusStall;
logic HPTWStall;
logic IgnoreRequestTLB;
logic BusCommittedM, DCacheCommittedM;
logic DataDAPageFaultM;
logic [`XLEN-1:0] IHWriteDataM, IMAWriteDataM;
logic [`LLEN-1:0] IMAFWriteDataM;
logic [`LLEN-1:0] ReadDataM;
logic [(`LLEN-1)/8:0] ByteMaskM;
logic SelDTIM;
logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM;
logic [`XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`PA_BITS-1:0] PAdrM; // Physical memory address
(* mark_debug = "true" *) logic [`XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
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
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
logic DCacheStallW; // D$ busy with multicycle operation
logic BusStall; // Bus interface busy with multicycle operation
logic HPTWStall; // HPTW busy with multicycle operation
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
logic [`LLEN-1:0] DTIMReadDataWordM; // DTIM read data
logic [`LLEN-1:0] DCacheReadDataWordM; // D$ read data
logic [`LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data
logic [`LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data
logic [`LLEN-1:0] ReadDataWordM; // Read data before subword selection
logic [`LLEN-1:0] ReadDataM; // Final read data
logic [`XLEN-1:0] IHWriteDataM; // IEU or HPTW write data
logic [`XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data
logic [`LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data
logic [`LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data
logic [`LLEN-1:0] LSUWriteDataM; // Final write data
logic [(`LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE to DTLB
logic DataDAPageFaultM; // 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, ignore TLB miss
logic SelDTIM; // Select DTIM rather than bus or D$
/////////////////////////////////////////////////////////////////////////////////////////////
// Pipeline for IEUAdr E to M
// Zero-extend address to 34 bits for XLEN=32
/////////////////////////////////////////////////////////////////////////////////////////////
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE};
assign LSUStallM = DCacheStallW | HPTWStall | BusStall;
/////////////////////////////////////////////////////////////////////////////////////////////
// HPTW(only needed if VM supported)
// HPTW (only needed if VM supported)
// MMU include PMP and is needed if any privileged supported
/////////////////////////////////////////////////////////////////////////////////////////////
@ -128,81 +154,72 @@ module lsu (
.DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM,
.FlushW, .DCacheStallW, .SATP_REGW, .PCF,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.ReadDataM(ReadDataM[`XLEN-1:0]), .WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
.ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
.WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
.IHAdrM, .HPTWStall, .SelHPTW,
.IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM,
.LoadAccessFaultM, .StoreAmoAccessFaultM, .HPTWInstrAccessFaultM);
end else begin
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
end else begin // No HPTW, so signals are not multiplexed
assign PreLSURWM = MemRWM;
assign IHAdrM = IEUAdrExtM;
assign LSUFunct3M = Funct3M; assign LSUFunct7M = Funct7M; assign LSUAtomicM = AtomicM;
assign LSUFunct3M = Funct3M;
assign LSUFunct7M = Funct7M;
assign LSUAtomicM = AtomicM;
assign IHWriteDataM = WriteDataM;
assign LoadAccessFaultM = LSULoadAccessFaultM;
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
assign HPTWInstrAccessFaultM = '0;
end
// CommittedM tells the CPU's privilege unit the current instruction
// in the memory stage is a memory operaton and that memory operation is either completed
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
// There is not a clean way to restore back to a partial executed instruction. CommiteedM will
// delay the interrupt until the LSU is in a clean state.
// 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;
assign GatedStallW = StallW & ~SelHPTW;
assign LSUStallM = DCacheStallW | HPTWStall | BusStall;
// MMU and Misalignment fault logic required if privileged unit exists
/////////////////////////////////////////////////////////////////////////////////////////////
// MMU and misalignment fault logic required if privileged unit exists
/////////////////////////////////////////////////////////////////////////////////////////////
if(`ZICSR_SUPPORTED == 1) begin : dmmu
logic DisableTranslation;
logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation
assign DisableTranslation = SelHPTW | FlushDCacheM;
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.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, .StoreAmoPageFaultM,
.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,
.StoreAmoPageFaultM,
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
.DAPageFault(DataDAPageFaultM),
// *** should use LSURWM as this is includes the lr/sc squash. However this introduces a combo loop
// from squash, depends on PAdrM, depends on TLBHit, depends on these *AccessM inputs.
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin
// Determine which region of physical memory (if any) is being accessed
// conditionally move adredecs to here and ifu.
// the lsu will output LSUHSel to EBU (need the same for ifu).
// The ebu will have a mux to select between LSUHSel, IFUHSel
// mux for HWSTRB
// adrdecs out of uncore.
end else begin // No MMU, so no PMA/page faults and no address translation
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
assign {LoadPageFaultM, StoreAmoPageFaultM} = '0;
assign PAdrM = IHAdrM[`PA_BITS-1:0];
assign CacheableM = '1;
assign SelDTIM = `DTIM_SUPPORTED & ~`BUS; // if no pma then select dtim if there is a DTIM. If there is
assign CacheableM = 1'b1;
assign SelDTIM = `DTIM_SUPPORTED & ~`BUS; // 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.
end
/////////////////////////////////////////////////////////////////////////////////////////////
// Memory System
// Either Data Cache or Data Tightly Integrated Memory or just bus interface
// Memory System (options)
// 1. DTIM
// 2. DTIM and bus
// 3. Bus
// 4. Cache and bus
/////////////////////////////////////////////////////////////////////////////////////////////
logic [`LLEN-1:0] LSUWriteDataM, LittleEndianWriteDataM;
logic [`LLEN-1:0] ReadDataWordM, LittleEndianReadDataWordM;
logic [`LLEN-1:0] ReadDataWordMuxM, DTIMReadDataWordM, DCacheReadDataWordM;
logic IgnoreRequest;
// Pause IEU memory request if TLB miss. After TLB fill, replay request.
// Discard memory request on pipeline flush
assign IgnoreRequest = IgnoreRequestTLB | FlushW;
if (`DTIM_SUPPORTED) begin : dtim
@ -210,7 +227,7 @@ module lsu (
logic [1:0] DTIMMemRWM;
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
assign DTIMAdr = MemRWM[0] ? IEUAdrExtM[`PA_BITS-1:0] : IEUAdrExtE[`PA_BITS-1:0]; // zero extend or contract to PA_BITS
mux2 #(`PA_BITS) DTIMAdrMux(IEUAdrExtE[`PA_BITS-1:0], IEUAdrExtM[`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.
@ -220,33 +237,33 @@ module lsu (
end else begin
end
if (`BUS) begin : bus
localparam integer LLENWORDSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`LLEN : 1;
localparam integer LLENLOGBWPL = `DCACHE ? $clog2(LLENWORDSPERLINE) : 1;
localparam integer BEATSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`AHBW : 1;
localparam integer AHBWLOGBWPL = `DCACHE ? $clog2(BEATSPERLINE) : 1;
localparam integer LLENWORDSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`LLEN : 1; // Number of LLEN words in cacheline
localparam integer LLENLOGBWPL = `DCACHE ? $clog2(LLENWORDSPERLINE) : 1; // Log2 of ^
localparam integer BEATSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`AHBW : 1; // Number of AHBW words (beats) in cacheline
localparam integer AHBWLOGBWPL = `DCACHE ? $clog2(BEATSPERLINE) : 1; // Log2 of ^
if(`DCACHE) begin : dcache
localparam integer LINELEN = `DCACHE ? `DCACHE_LINELENINBITS : `XLEN;
logic [LINELEN-1:0] FetchBuffer;
logic [`PA_BITS-1:0] DCacheBusAdr;
logic [AHBWLOGBWPL-1:0] BeatCount;
logic DCacheBusAck;
logic SelBusBeat;
logic [1:0] CacheBusRW, BusRW;
localparam integer LLENPOVERAHBW = `LLEN / `AHBW;
logic CacheableOrFlushCacheM;
logic [1:0] CacheRWM, CacheAtomicM;
logic CacheFlushM;
localparam integer LINELEN = `DCACHE ? `DCACHE_LINELENINBITS : `XLEN; // Number of bytes in cacheline
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
logic [`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
localparam integer LLENPOVERAHBW = `LLEN / `AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
logic [1:0] CacheAtomicM; // Cache AMO
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0;
assign CacheFlushM = FlushDCacheM;
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`LLEN), .DCACHE(1)) dcache(
.clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM),
.FlushCache(CacheFlushM), .NextAdr(IEUAdrE[11:0]), .PAdr(PAdrM),
.FlushCache(FlushDCacheM), .NextAdr(IEUAdrE[11:0]), .PAdr(PAdrM),
.ByteMask(ByteMaskM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
.CacheWriteData(LSUWriteDataM), .SelHPTW,
.CacheStall(DCacheStallW), .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
@ -254,6 +271,7 @@ module lsu (
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
.FetchBuffer, .CacheBusRW,
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0));
ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .LINELEN(LINELEN), .LOGWPL(AHBWLOGBWPL), .CACHE_ENABLED(`DCACHE)) ahbcacheinterface(
.HCLK(clk), .HRESETn(~reset), .Flush(FlushW),
.HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB),
@ -264,15 +282,15 @@ module lsu (
.Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW),
.BusStall, .BusCommitted(BusCommittedM));
// FetchBuffer[`AHBW-1:0] needs to be duplicated LLENPOVERAHBW times.
// DTIMReadDataWordM should be increased to LLEN.
// *** DTIMReadDataWordM should be LLEN
// pma should generate expection for LLEN read to periph.
// 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.
// *** DTIMReadDataWordM should be increased to LLEN.
// pma should generate exception for LLEN read to periph.
mux3 #(`LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[`XLEN-1:0]}}),
.d2({{`LLEN-`XLEN{1'b0}}, DTIMReadDataWordM[`XLEN-1:0]}),
.s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM));
end else begin : passthrough // just needs a register to hold the value from the bus
logic [1:0] BusRW;
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
logic [`XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
@ -284,12 +302,13 @@ module lsu (
.HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM),
.Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer));
// Mux between the 2 sources of read data, 0: Bus, 1: DTIM
if(`DTIM_SUPPORTED) mux2 #(`XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM, SelDTIM, ReadDataWordMuxM);
else assign ReadDataWordMuxM = FetchBuffer[`XLEN-1:0];
assign LSUHBURST = 3'b0;
assign {DCacheStallW, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
end
end else begin: nobus // block: bus
end else begin: nobus // block: bus, only DTIM
assign LSUHWDATA = '0;
assign ReadDataWordMuxM = DTIMReadDataWordM;
assign {BusStall, BusCommittedM} = '0;