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 // alu.sv
// //
// Written: David_Harris@hmc.edu 9 January 2021 // Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
// Created: 9 January 2021
// Modified: // Modified:
// //
// Purpose: RISC-V Arithmetic/Logic Unit // 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. // A component of the CORE-V-WALLY configurable RISC-V project.
// //

View File

@ -178,7 +178,7 @@ module ifu (
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// Memory // 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 // 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. // 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 // There is not a clean way to restore back to a partial executed instruction. CommiteedM will

View File

@ -1,13 +1,16 @@
/////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// lsu.sv // lsu.sv
// //
// Written: David_Harris@hmc.edu 9 January 2021 // Written: David_Harris@hmc.edu, ross1728@gmail.com
// Modified: // Created: 9 January 2021
// Modified: 11 January 2023
// //
// Purpose: Load/Store Unit // Purpose: Load/Store Unit
// Top level of the memory-stage core logic // HPTW, DMMU, data cache, interface to external bus
// Contains data cache, DTLB, subword read/write datapath, 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. // A component of the CORE-V-WALLY configurable RISC-V project.
// //
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University // 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, // 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 // either express or implied. See the License for the specific language governing permissions
// and limitations under the License. // 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" `include "wally-config.vh"
module lsu ( module lsu (
input logic clk, reset, input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW, input logic StallM, FlushM, StallW, FlushW,
output logic LSUStallM, output logic LSUStallM, // LSU stalls pipeline during a multicycle operation.
// connected to cpu (controls) // connected to cpu (controls)
input logic [1:0] MemRWM, input logic [1:0] MemRWM, // Read/Write control
input logic [2:0] Funct3M, input logic [2:0] Funct3M, // Size of memory operation
input logic [6:0] Funct7M, input logic [6:0] Funct7M, // Atomic memory operation function
input logic [1:0] AtomicM, input logic [1:0] AtomicM, // Atomic memory operation
input logic FlushDCacheM, input logic FlushDCacheM, // Flush D cache to next level of memory
output logic CommittedM, output logic CommittedM, // Delay interrupts while memory operation in flight
output logic SquashSCW, output logic SquashSCW, // Store conditional failed disable write to GPR
output logic DCacheMiss, output logic DCacheMiss, // D cache miss for performance counters
output logic DCacheAccess, output logic DCacheAccess, // D cache memory access for performance counters
// address and write data // address and write data
input logic [`XLEN-1:0] IEUAdrE, input logic [`XLEN-1:0] IEUAdrE, // Execution stage memory address
(* mark_debug = "true" *)output logic [`XLEN-1:0] IEUAdrM, (* mark_debug = "true" *) output logic [`XLEN-1:0] IEUAdrM, // Memory stage memory address
(* mark_debug = "true" *)input logic [`XLEN-1:0] WriteDataM, (* mark_debug = "true" *) input logic [`XLEN-1:0] WriteDataM, // Write data from IEU
output logic [`LLEN-1:0] ReadDataW, output logic [`LLEN-1:0] ReadDataW, // Read data to IEU or FPU
// cpu privilege // cpu privilege
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW, // Current privilege mode
input logic BigEndianM, input logic BigEndianM, // Swap byte order to big endian
input logic sfencevmaM, input logic sfencevmaM, // Virtual memory address fence
// fpu // fpu
input logic [`FLEN-1:0] FWriteDataM, input logic [`FLEN-1:0] FWriteDataM, // Write data from FPU
input logic FpLoadStoreM, input logic FpLoadStoreM, // Selects FPU as store for write data
// faults // faults
output logic LoadPageFaultM, StoreAmoPageFaultM, output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
output logic LoadMisalignedFaultM, LoadAccessFaultM, HPTWInstrAccessFaultM, 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) // 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 // connect to ahb
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUHADDR, (* 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, (* 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, (* mark_debug = "true" *) output logic [`XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
(* mark_debug = "true" *) input logic LSUHREADY, (* mark_debug = "true" *) input logic LSUHREADY, // Bus ready from LSU to EBU
(* mark_debug = "true" *) output logic LSUHWRITE, (* mark_debug = "true" *) output logic LSUHWRITE, // Bus write operation from LSU to EBU
(* mark_debug = "true" *) output logic [2:0] LSUHSIZE, (* mark_debug = "true" *) output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
(* mark_debug = "true" *) output logic [2:0] LSUHBURST, (* mark_debug = "true" *) output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
(* mark_debug = "true" *) output logic [1:0] LSUHTRANS, (* 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, (* mark_debug = "true" *) output logic [`XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
// page table walker // page table walker
input logic [`XLEN-1:0] SATP_REGW, // from csr input logic [`XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, 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, input logic [1:0] STATUS_MPP, // Machine previous privilege mode
input logic [`XLEN-1:0] PCF, input logic [`XLEN-1:0] PCF, // Fetch PC
input logic ITLBMissF, input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrDAPageFaultF, input logic InstrDAPageFaultF, // ITLB hit needs to update dirty or access bits
output logic [`XLEN-1:0] PTE, output logic [`XLEN-1:0] PTE, // Page table entry write to ITLB
output logic [1:0] PageType, output logic [1:0] PageType, // Type of page table entry to write to ITLB
output logic ITLBWriteF, SelHPTW, output logic ITLBWriteF, // Write PTE to ITLB
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
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 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] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`XLEN+1:0] IEUAdrExtE; logic [`XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
logic [`PA_BITS-1:0] PAdrM; logic [`PA_BITS-1:0] PAdrM; // Physical memory address
logic DTLBMissM; (* mark_debug = "true" *) logic [`XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
logic DTLBWriteM;
logic [1:0] PreLSURWM, LSURWM; logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
logic [2:0] LSUFunct3M; logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
logic [6:0] LSUFunct7M; logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
logic [1:0] LSUAtomicM; logic [6:0] LSUFunct7M; // AMO function gated by HPTW
(* mark_debug = "true" *) logic [`XLEN+1:0] IHAdrM; logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
logic GatedStallW;
logic DCacheStallW; logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
logic CacheableM;
logic BusStall; logic DCacheStallW; // D$ busy with multicycle operation
logic HPTWStall; logic BusStall; // Bus interface busy with multicycle operation
logic IgnoreRequestTLB; logic HPTWStall; // HPTW busy with multicycle operation
logic BusCommittedM, DCacheCommittedM;
logic DataDAPageFaultM; logic CacheableM; // PMA indicates memory address is cacheable
logic [`XLEN-1:0] IHWriteDataM, IMAWriteDataM; logic BusCommittedM; // Bus memory operation in flight, delay interrupts
logic [`LLEN-1:0] IMAFWriteDataM; logic DCacheCommittedM; // D$ memory operation started, delay interrupts
logic [`LLEN-1:0] ReadDataM;
logic [(`LLEN-1)/8:0] ByteMaskM; logic [`LLEN-1:0] DTIMReadDataWordM; // DTIM read data
logic SelDTIM; logic [`LLEN-1:0] DCacheReadDataWordM; // D$ read data
logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM; 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); flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
assign IEUAdrExtM = {2'b00, IEUAdrM}; assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE}; 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 // MMU include PMP and is needed if any privileged supported
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
@ -128,81 +154,72 @@ module lsu (
.DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM, .DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM,
.FlushW, .DCacheStallW, .SATP_REGW, .PCF, .FlushW, .DCacheStallW, .SATP_REGW, .PCF,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .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, .IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
.IHAdrM, .HPTWStall, .SelHPTW, .IHAdrM, .HPTWStall, .SelHPTW,
.IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM, .IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM,
.LoadAccessFaultM, .StoreAmoAccessFaultM, .HPTWInstrAccessFaultM); .LoadAccessFaultM, .StoreAmoAccessFaultM, .HPTWInstrAccessFaultM);
end else begin end else begin // No HPTW, so signals are not multiplexed
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
assign PreLSURWM = MemRWM; assign PreLSURWM = MemRWM;
assign IHAdrM = IEUAdrExtM; 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 IHWriteDataM = WriteDataM;
assign LoadAccessFaultM = LSULoadAccessFaultM; assign LoadAccessFaultM = LSULoadAccessFaultM;
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM; assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
assign HPTWInstrAccessFaultM = '0; assign HPTWInstrAccessFaultM = '0;
end end
// CommittedM tells the CPU's privilege unit the current instruction // CommittedM indicates the cache, bus, or HPTW are busy with a multiple cycle operation.
// in the memory stage is a memory operaton and that memory operation is either completed // CommittedM is 1 after the first cycle and until the last cycle. Partially completed memory
// or is partially executed. Partially completed memory operations need to prevent an interrupts. // operations delay interrupts until the next instruction by suppressing pending interrupts in
// There is not a clean way to restore back to a partial executed instruction. CommiteedM will // the trap module.
// delay the interrupt until the LSU is in a clean state.
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM; assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
assign GatedStallW = StallW & ~SelHPTW; 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 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; assign DisableTranslation = SelHPTW | FlushDCacheM;
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0)) mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .DisableTranslation, .PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
.VAdr(IHAdrM), .PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM),
.Size(LSUFunct3M[1:0]), .PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM),
.PTE, .InstrAccessFaultF(), .LoadAccessFaultM(LSULoadAccessFaultM),
.PageTypeWriteVal(PageType), .StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
.TLBWrite(DTLBWriteM), .StoreAmoPageFaultM,
.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. .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
.DAPageFault(DataDAPageFaultM), .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), .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin end else begin // No MMU, so no PMA/page faults and no address translation
// 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.
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0; assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
assign {LoadPageFaultM, StoreAmoPageFaultM} = '0; assign {LoadPageFaultM, StoreAmoPageFaultM} = '0;
assign PAdrM = IHAdrM[`PA_BITS-1:0]; assign PAdrM = IHAdrM[`PA_BITS-1:0];
assign CacheableM = '1; assign CacheableM = 1'b1;
assign SelDTIM = `DTIM_SUPPORTED & ~`BUS; // if no pma then select dtim if there is a DTIM. If there is 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. // a bus then this is always 0. Cannot have both without PMA.
end end
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Memory System // Memory System (options)
// Either Data Cache or Data Tightly Integrated Memory or just bus interface // 1. DTIM
// 2. DTIM and bus
// 3. Bus
// 4. Cache and bus
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
logic [`LLEN-1:0] LSUWriteDataM, LittleEndianWriteDataM;
logic [`LLEN-1:0] ReadDataWordM, LittleEndianReadDataWordM; // Pause IEU memory request if TLB miss. After TLB fill, replay request.
logic [`LLEN-1:0] ReadDataWordMuxM, DTIMReadDataWordM, DCacheReadDataWordM; // Discard memory request on pipeline flush
logic IgnoreRequest;
assign IgnoreRequest = IgnoreRequestTLB | FlushW; assign IgnoreRequest = IgnoreRequestTLB | FlushW;
if (`DTIM_SUPPORTED) begin : dtim if (`DTIM_SUPPORTED) begin : dtim
@ -210,7 +227,7 @@ module lsu (
logic [1:0] DTIMMemRWM; logic [1:0] DTIMMemRWM;
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory. // 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; assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length. // **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point. // **** create config to support DTIM with floating point.
@ -220,33 +237,33 @@ module lsu (
end else begin end else begin
end end
if (`BUS) begin : bus if (`BUS) begin : bus
localparam integer LLENWORDSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`LLEN : 1; localparam integer LLENWORDSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`LLEN : 1; // Number of LLEN words in cacheline
localparam integer LLENLOGBWPL = `DCACHE ? $clog2(LLENWORDSPERLINE) : 1; localparam integer LLENLOGBWPL = `DCACHE ? $clog2(LLENWORDSPERLINE) : 1; // Log2 of ^
localparam integer BEATSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`AHBW : 1; localparam integer BEATSPERLINE = `DCACHE ? `DCACHE_LINELENINBITS/`AHBW : 1; // Number of AHBW words (beats) in cacheline
localparam integer AHBWLOGBWPL = `DCACHE ? $clog2(BEATSPERLINE) : 1; localparam integer AHBWLOGBWPL = `DCACHE ? $clog2(BEATSPERLINE) : 1; // Log2 of ^
if(`DCACHE) begin : dcache if(`DCACHE) begin : dcache
localparam integer LINELEN = `DCACHE ? `DCACHE_LINELENINBITS : `XLEN; localparam integer LINELEN = `DCACHE ? `DCACHE_LINELENINBITS : `XLEN; // Number of bytes in cacheline
logic [LINELEN-1:0] FetchBuffer; logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
logic [`PA_BITS-1:0] DCacheBusAdr; logic [`PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
logic [AHBWLOGBWPL-1:0] BeatCount; logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
logic DCacheBusAck; logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
logic SelBusBeat; logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
logic [1:0] CacheBusRW, BusRW; logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
localparam integer LLENPOVERAHBW = `LLEN / `AHBW; logic [1:0] BusRW; // Uncached bus memory access
logic CacheableOrFlushCacheM; localparam integer LLENPOVERAHBW = `LLEN / `AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
logic [1:0] CacheRWM, CacheAtomicM; logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
logic CacheFlushM; 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 BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM; assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0; assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0;
assign CacheFlushM = FlushDCacheM;
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN), cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`LLEN), .DCACHE(1)) dcache( .NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`LLEN), .DCACHE(1)) dcache(
.clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM), .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]), .ByteMask(ByteMaskM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
.CacheWriteData(LSUWriteDataM), .SelHPTW, .CacheWriteData(LSUWriteDataM), .SelHPTW,
.CacheStall(DCacheStallW), .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess), .CacheStall(DCacheStallW), .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
@ -254,6 +271,7 @@ module lsu (
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM), .CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
.FetchBuffer, .CacheBusRW, .FetchBuffer, .CacheBusRW,
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0)); .CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0));
ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .LINELEN(LINELEN), .LOGWPL(AHBWLOGBWPL), .CACHE_ENABLED(`DCACHE)) ahbcacheinterface( ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .LINELEN(LINELEN), .LOGWPL(AHBWLOGBWPL), .CACHE_ENABLED(`DCACHE)) ahbcacheinterface(
.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HCLK(clk), .HRESETn(~reset), .Flush(FlushW),
.HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB), .HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB),
@ -264,15 +282,15 @@ module lsu (
.Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW), .Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW),
.BusStall, .BusCommitted(BusCommittedM)); .BusStall, .BusCommitted(BusCommittedM));
// FetchBuffer[`AHBW-1:0] needs to be duplicated LLENPOVERAHBW times. // Mux between the 3 sources of read data, 0: cache, 1: Bus, 2: DTIM
// DTIMReadDataWordM should be increased to LLEN. // Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times.
// *** DTIMReadDataWordM should be LLEN // *** DTIMReadDataWordM should be increased to LLEN.
// pma should generate expection for LLEN read to periph. // pma should generate exception for LLEN read to periph.
mux3 #(`LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[`XLEN-1:0]}}), mux3 #(`LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[`XLEN-1:0]}}),
.d2({{`LLEN-`XLEN{1'b0}}, DTIMReadDataWordM[`XLEN-1:0]}), .d2({{`LLEN-`XLEN{1'b0}}, DTIMReadDataWordM[`XLEN-1:0]}),
.s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM)); .s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM));
end else begin : passthrough // just needs a register to hold the value from the bus end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
logic [`XLEN-1:0] FetchBuffer; logic [`XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
@ -284,12 +302,13 @@ module lsu (
.HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM), .HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM),
.Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer)); .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); if(`DTIM_SUPPORTED) mux2 #(`XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM, SelDTIM, ReadDataWordMuxM);
else assign ReadDataWordMuxM = FetchBuffer[`XLEN-1:0]; else assign ReadDataWordMuxM = FetchBuffer[`XLEN-1:0];
assign LSUHBURST = 3'b0; assign LSUHBURST = 3'b0;
assign {DCacheStallW, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0; assign {DCacheStallW, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
end end
end else begin: nobus // block: bus end else begin: nobus // block: bus, only DTIM
assign LSUHWDATA = '0; assign LSUHWDATA = '0;
assign ReadDataWordMuxM = DTIMReadDataWordM; assign ReadDataWordMuxM = DTIMReadDataWordM;
assign {BusStall, BusCommittedM} = '0; assign {BusStall, BusCommittedM} = '0;