mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
In the dcache we added a register to save the load read data in the event an itlb miss occurs concurrently with the load in the memory stage. Under this situation we need to record the load ReadDataM into a temporary register, SavedReadDataM. At this time the CPU is stall; however the walker is going to change the address in the dcache which destroys this data. When leaving the PTW_READY state via a walker instruction fault or ITLB write we select this SavedReadDataM so that the CPU can capture it.
444 lines
14 KiB
Systemverilog
444 lines
14 KiB
Systemverilog
///////////////////////////////////////////
|
|
// 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 LSUStall,
|
|
// Memory Stage
|
|
|
|
// 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 ExceptionM,
|
|
input logic PendingInterruptM,
|
|
output logic CommittedM,
|
|
output logic SquashSCW,
|
|
output logic DataMisalignedM,
|
|
output logic DCacheMiss,
|
|
output logic DCacheAccess,
|
|
|
|
// address and write data
|
|
input logic [`XLEN-1:0] MemAdrM,
|
|
input logic [`XLEN-1:0] MemAdrE,
|
|
input logic [`XLEN-1:0] WriteDataM,
|
|
output logic [`XLEN-1:0] ReadDataM,
|
|
|
|
// cpu privilege
|
|
input logic [1:0] PrivilegeModeW,
|
|
input logic DTLBFlushM,
|
|
// faults
|
|
output logic DTLBLoadPageFaultM, DTLBStorePageFaultM,
|
|
output logic LoadMisalignedFaultM, LoadAccessFaultM,
|
|
// cpu hazard unit (trap)
|
|
output logic StoreMisalignedFaultM, StoreAccessFaultM,
|
|
|
|
// connect to ahb
|
|
input logic CommitM, // should this be generated in the abh interface?
|
|
output logic [`PA_BITS-1:0] DCtoAHBPAdrM,
|
|
output logic DCtoAHBReadM,
|
|
output logic DCtoAHBWriteM,
|
|
input logic DCfromAHBAck,
|
|
input logic [`XLEN-1:0] DCfromAHBReadData,
|
|
output logic [`XLEN-1:0] DCtoAHBWriteData,
|
|
output logic [2:0] DCtoAHBSizeM,
|
|
|
|
// mmu management
|
|
|
|
// 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,
|
|
output logic [`XLEN-1:0] PTE,
|
|
output logic [1:0] PageType,
|
|
output logic ITLBWriteF,
|
|
output logic WalkerInstrPageFaultF,
|
|
output logic WalkerLoadPageFaultM,
|
|
output logic WalkerStorePageFaultM,
|
|
|
|
output logic DTLBHitM, // not connected
|
|
|
|
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.
|
|
|
|
// output logic [5:0] DHSELRegionsM
|
|
|
|
);
|
|
|
|
logic SquashSCM;
|
|
logic DTLBPageFaultM;
|
|
logic MemAccessM;
|
|
|
|
/* -----\/----- EXCLUDED -----\/-----
|
|
logic preCommittedM;
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
|
|
typedef enum {STATE_READY,
|
|
STATE_FETCH,
|
|
STATE_FETCH_AMO_1,
|
|
STATE_FETCH_AMO_2,
|
|
STATE_STALLED,
|
|
STATE_PTW_READY,
|
|
STATE_PTW_FETCH,
|
|
STATE_PTW_DONE} statetype;
|
|
statetype CurrState, NextState;
|
|
|
|
logic [`PA_BITS-1:0] MemPAdrM; // from mmu to dcache
|
|
|
|
logic DTLBMissM;
|
|
// logic [`XLEN-1:0] PTE;
|
|
logic DTLBWriteM;
|
|
logic HPTWStall;
|
|
logic [`XLEN-1:0] HPTWPAdrE;
|
|
// logic [`XLEN-1:0] HPTWPAdrM;
|
|
logic [`PA_BITS-1:0] TranslationPAdr;
|
|
logic HPTWRead;
|
|
logic [1:0] MemRWMtoDCache;
|
|
logic [1:0] MemRWMtoLRSC;
|
|
logic [2:0] Funct3MtoDCache;
|
|
logic [1:0] AtomicMtoDCache;
|
|
logic [`PA_BITS-1:0] MemPAdrMtoDCache;
|
|
logic [11:0] MemAdrEtoDCache;
|
|
logic [`XLEN-1:0] ReadDataWfromDCache;
|
|
logic StallWtoDCache;
|
|
logic MemReadM;
|
|
logic DataMisalignedMfromDCache;
|
|
logic HPTWReady;
|
|
logic DisableTranslation; // used to stop intermediate PTE physical addresses being saved to TLB.
|
|
logic DCacheStall;
|
|
|
|
logic CacheableM;
|
|
logic CacheableMtoDCache;
|
|
logic SelPTW;
|
|
|
|
logic CommittedMfromDCache;
|
|
logic PendingInterruptMtoDCache;
|
|
logic FlushWtoDCache;
|
|
logic WalkerPageFaultM;
|
|
|
|
logic [`XLEN-1:0] LSUData;
|
|
|
|
hptw hptw(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.SATP_REGW(SATP_REGW),
|
|
.PCF(PCF),
|
|
.MemAdrM(MemAdrM),
|
|
.ITLBMissF(ITLBMissF),
|
|
.DTLBMissM(DTLBMissM),
|
|
.MemRWM(MemRWM),
|
|
.PTE(PTE),
|
|
.PageType,
|
|
.ITLBWriteF(ITLBWriteF),
|
|
.DTLBWriteM(DTLBWriteM),
|
|
.HPTWReadPTE(LSUData),
|
|
.HPTWStall(HPTWStall),
|
|
.TranslationPAdr,
|
|
.HPTWRead(HPTWRead),
|
|
.SelPTW(SelPTW),
|
|
.WalkerInstrPageFaultF(WalkerInstrPageFaultF),
|
|
.WalkerLoadPageFaultM(WalkerLoadPageFaultM),
|
|
.WalkerStorePageFaultM(WalkerStorePageFaultM));
|
|
|
|
|
|
assign WalkerPageFaultM = WalkerStorePageFaultM | WalkerLoadPageFaultM;
|
|
|
|
// arbiter between IEU and hptw
|
|
lsuArb arbiter(.clk(clk),
|
|
.reset(reset),
|
|
// HPTW connection
|
|
.SelPTW(SelPTW),
|
|
.HPTWRead(HPTWRead),
|
|
.TranslationPAdrE(TranslationPAdr),
|
|
.HPTWStall(HPTWStall),
|
|
// CPU connection
|
|
.MemRWM(MemRWM),
|
|
.Funct3M(Funct3M),
|
|
.AtomicM(AtomicM),
|
|
.MemAdrM(MemAdrM),
|
|
.MemAdrE(MemAdrE),
|
|
.CommittedM(CommittedM),
|
|
.PendingInterruptM(PendingInterruptM),
|
|
.StallW(StallW),
|
|
.DataMisalignedM(DataMisalignedM),
|
|
.LSUStall(LSUStall),
|
|
// DCACHE
|
|
.DisableTranslation(DisableTranslation),
|
|
.MemRWMtoLRSC(MemRWMtoLRSC),
|
|
.Funct3MtoDCache(Funct3MtoDCache),
|
|
.AtomicMtoDCache(AtomicMtoDCache),
|
|
.MemPAdrMtoDCache(MemPAdrMtoDCache),
|
|
.MemAdrEtoDCache(MemAdrEtoDCache),
|
|
.StallWtoDCache(StallWtoDCache),
|
|
.DataMisalignedMfromDCache(DataMisalignedMfromDCache),
|
|
.CommittedMfromDCache(CommittedMfromDCache),
|
|
.PendingInterruptMtoDCache(PendingInterruptMtoDCache),
|
|
.DCacheStall(DCacheStall));
|
|
|
|
|
|
|
|
|
|
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
|
|
dmmu(.PAdr(MemPAdrMtoDCache),
|
|
.VAdr(MemAdrM),
|
|
.Size(Funct3MtoDCache[1:0]),
|
|
.PTE(PTE),
|
|
.PageTypeWriteVal(PageType),
|
|
.TLBWrite(DTLBWriteM),
|
|
.TLBFlush(DTLBFlushM),
|
|
.PhysicalAddress(MemPAdrM),
|
|
.TLBMiss(DTLBMissM),
|
|
.TLBHit(DTLBHitM),
|
|
.TLBPageFault(DTLBPageFaultM),
|
|
.ExecuteAccessF(1'b0),
|
|
//.AtomicAccessM(AtomicMaskedM[1]),
|
|
.AtomicAccessM(1'b0),
|
|
.WriteAccessM(MemRWMtoLRSC[0]),
|
|
.ReadAccessM(MemRWMtoLRSC[1]),
|
|
.SquashBusAccess(),
|
|
.DisableTranslation(DisableTranslation),
|
|
.InstrAccessFaultF(),
|
|
.Cacheable(CacheableM),
|
|
.Idempotent(),
|
|
.AtomicAllowed(),
|
|
.*); // *** the pma/pmp instruction acess faults don't really matter here. is it possible to parameterize which outputs exist?
|
|
|
|
|
|
assign MemReadM = MemRWMtoLRSC[1] & ~(ExceptionM | PendingInterruptMtoDCache) & ~DTLBMissM; // & ~NonBusTrapM & ~DTLBMissM & CurrState != STATE_STALLED;
|
|
lrsc lrsc(.clk, .reset, .FlushW, .StallWtoDCache, .MemReadM, .MemRWMtoLRSC, .AtomicMtoDCache, .MemPAdrM,
|
|
.SquashSCM, .SquashSCW, .MemRWMtoDCache);
|
|
|
|
// *** BUG, this is most likely wrong
|
|
assign CacheableMtoDCache = SelPTW ? 1'b1 : CacheableM;
|
|
|
|
generate
|
|
if (`XLEN == 32) assign DCtoAHBSizeM = CacheableMtoDCache ? 3'b010 : Funct3MtoDCache;
|
|
else assign DCtoAHBSizeM = CacheableMtoDCache ? 3'b011 : Funct3MtoDCache;
|
|
endgenerate;
|
|
|
|
|
|
// Specify which type of page fault is occurring
|
|
assign DTLBLoadPageFaultM = DTLBPageFaultM & MemRWMtoLRSC[1];
|
|
assign DTLBStorePageFaultM = DTLBPageFaultM & MemRWMtoLRSC[0];
|
|
|
|
// Determine if an Unaligned access is taking place
|
|
always_comb
|
|
case(Funct3MtoDCache[1:0])
|
|
2'b00: DataMisalignedMfromDCache = 0; // lb, sb, lbu
|
|
2'b01: DataMisalignedMfromDCache = MemPAdrMtoDCache[0]; // lh, sh, lhu
|
|
2'b10: DataMisalignedMfromDCache = MemPAdrMtoDCache[1] | MemPAdrMtoDCache[0]; // lw, sw, flw, fsw, lwu
|
|
2'b11: DataMisalignedMfromDCache = |MemPAdrMtoDCache[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 DataMisalignedMfromDCache 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
|
|
/* -----\/----- EXCLUDED -----\/-----
|
|
|
|
// *** BUG for now leave this out. come back later after the d cache is working. July 09, 2021
|
|
|
|
assign MemReadM = MemRWMtoLRSC[1] & ~NonBusTrapM & ~DTLBMissM & CurrState != STATE_STALLED;
|
|
assign MemWriteM = MemRWMtoLRSC[0] & ~NonBusTrapM & ~DTLBMissM & ~SquashSCM & CurrState != STATE_STALLED;
|
|
assign AtomicMaskedM = CurrState != STATE_STALLED ? AtomicMtoDCache : 2'b00 ;
|
|
assign MemAccessM = MemReadM | MemWriteM;
|
|
|
|
// Determine if M stage committed
|
|
// Reset whenever unstalled. Set when access successfully occurs
|
|
flopr #(1) committedMreg(clk,reset,(CommittedMfromDCache | CommitM) & StallM,preCommittedM);
|
|
assign CommittedMfromDCache = preCommittedM | CommitM;
|
|
|
|
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
|
|
// Determine if address is valid
|
|
assign LoadMisalignedFaultM = DataMisalignedMfromDCache & MemRWMtoLRSC[1];
|
|
assign StoreMisalignedFaultM = DataMisalignedMfromDCache & MemRWMtoLRSC[0];
|
|
|
|
dcache dcache(.clk(clk),
|
|
.reset(reset),
|
|
.StallM(StallM),
|
|
.StallWtoDCache(StallWtoDCache),
|
|
.FlushM(FlushM),
|
|
.FlushW(FlushWtoDCache),
|
|
.MemRWM(MemRWMtoDCache),
|
|
.Funct3M(Funct3MtoDCache),
|
|
.Funct7M(Funct7M),
|
|
.AtomicM(AtomicMtoDCache),
|
|
.MemAdrE(MemAdrEtoDCache),
|
|
.MemPAdrM(MemPAdrM),
|
|
.VAdr(MemAdrM[11:0]),
|
|
.WriteDataM(WriteDataM),
|
|
.ReadDataM(ReadDataM),
|
|
.LSUData(LSUData),
|
|
.DCacheStall(DCacheStall),
|
|
.CommittedM(CommittedMfromDCache),
|
|
.DCacheMiss,
|
|
.DCacheAccess,
|
|
.ExceptionM(ExceptionM),
|
|
.PendingInterruptM(PendingInterruptMtoDCache),
|
|
.DTLBMissM(DTLBMissM),
|
|
.CacheableM(CacheableMtoDCache),
|
|
.DTLBWriteM(DTLBWriteM),
|
|
.ITLBWriteF(ITLBWriteF),
|
|
.SelPTW(SelPTW),
|
|
.WalkerPageFaultM(WalkerPageFaultM),
|
|
.WalkerInstrPageFaultF(WalkerInstrPageFaultF),
|
|
|
|
// AHB connection
|
|
.AHBPAdr(DCtoAHBPAdrM),
|
|
.AHBRead(DCtoAHBReadM),
|
|
.AHBWrite(DCtoAHBWriteM),
|
|
.AHBAck(DCfromAHBAck),
|
|
.HWDATA(DCtoAHBWriteData),
|
|
.HRDATA(DCfromAHBReadData)
|
|
);
|
|
|
|
// assign AtomicMaskedM = 2'b00; // *** Remove from AHB
|
|
|
|
|
|
// Data stall
|
|
//assign LSUStall = (NextState == STATE_FETCH) || (NextState == STATE_FETCH_AMO_1) || (NextState == STATE_FETCH_AMO_2);
|
|
// BUG *** July 09, 2021
|
|
//assign HPTWReady = (CurrState == STATE_READY);
|
|
|
|
|
|
// 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.
|
|
|
|
/* -----\/----- EXCLUDED -----\/-----
|
|
// *** BUG will need to modify this so we can handle the ptw. July 09, 2021
|
|
|
|
flopenl #(.TYPE(statetype)) stateReg(.clk(clk),
|
|
.load(reset),
|
|
.en(1'b1),
|
|
.d(NextState),
|
|
.val(STATE_READY),
|
|
.q(CurrState));
|
|
|
|
always_comb begin
|
|
case (CurrState)
|
|
STATE_READY:
|
|
if (DTLBMissM) begin
|
|
NextState = STATE_PTW_READY;
|
|
LSUStall = 1'b1;
|
|
end else if (AtomicMaskedM[1]) begin
|
|
NextState = STATE_FETCH_AMO_1; // *** should be some misalign check
|
|
LSUStall = 1'b1;
|
|
end else if((MemReadM & AtomicMtoDCache[0]) | (MemWriteM & AtomicMtoDCache[0])) begin
|
|
NextState = STATE_FETCH_AMO_2;
|
|
LSUStall = 1'b1;
|
|
end else if (MemAccessM & ~DataMisalignedMfromDCache) begin
|
|
NextState = STATE_FETCH;
|
|
LSUStall = 1'b1;
|
|
end else begin
|
|
NextState = STATE_READY;
|
|
LSUStall = 1'b0;
|
|
end
|
|
STATE_FETCH_AMO_1: begin
|
|
LSUStall = 1'b1;
|
|
if (DCfromAHBAck) begin
|
|
NextState = STATE_FETCH_AMO_2;
|
|
end else begin
|
|
NextState = STATE_FETCH_AMO_1;
|
|
end
|
|
end
|
|
STATE_FETCH_AMO_2: begin
|
|
LSUStall = 1'b1;
|
|
if (DCfromAHBAck & ~StallWtoDCache) begin
|
|
NextState = STATE_FETCH_AMO_2;
|
|
end else if (DCfromAHBAck & StallWtoDCache) begin
|
|
NextState = STATE_STALLED;
|
|
end else begin
|
|
NextState = STATE_FETCH_AMO_2;
|
|
end
|
|
end
|
|
STATE_FETCH: begin
|
|
LSUStall = 1'b1;
|
|
if (DCfromAHBAck & ~StallWtoDCache) begin
|
|
NextState = STATE_READY;
|
|
end else if (DCfromAHBAck & StallWtoDCache) begin
|
|
NextState = STATE_STALLED;
|
|
end else begin
|
|
NextState = STATE_FETCH;
|
|
end
|
|
end
|
|
STATE_STALLED: begin
|
|
LSUStall = 1'b0;
|
|
if (~StallWtoDCache) begin
|
|
NextState = STATE_READY;
|
|
end else begin
|
|
NextState = STATE_STALLED;
|
|
end
|
|
end
|
|
STATE_PTW_READY: begin
|
|
LSUStall = 1'b0;
|
|
if (DTLBWriteM) begin
|
|
NextState = STATE_READY;
|
|
LSUStall = 1'b1;
|
|
end else if (MemReadM & ~DataMisalignedMfromDCache) begin
|
|
NextState = STATE_PTW_FETCH;
|
|
end else begin
|
|
NextState = STATE_PTW_READY;
|
|
end
|
|
end
|
|
STATE_PTW_FETCH : begin
|
|
LSUStall = 1'b1;
|
|
if (DCfromAHBAck & ~DTLBWriteM) begin
|
|
NextState = STATE_PTW_READY;
|
|
end else if (DCfromAHBAck & DTLBWriteM) begin
|
|
NextState = STATE_READY;
|
|
end else begin
|
|
NextState = STATE_PTW_FETCH;
|
|
end
|
|
end
|
|
STATE_PTW_DONE: begin
|
|
NextState = STATE_READY;
|
|
end
|
|
default: begin
|
|
LSUStall = 1'b0;
|
|
NextState = STATE_READY;
|
|
end
|
|
endcase
|
|
end // always_comb
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
|
|
|
|
endmodule
|
|
|