Merge pull request #544 from ross144/main

Update structural hazards, cbo.zero works for uncache memory.
This commit is contained in:
David Harris 2023-12-29 15:00:44 -08:00 committed by GitHub
commit cd985a44d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 86 additions and 98 deletions

View File

@ -18,7 +18,6 @@ all: riscoftests memfiles coveragetests
wally-riscv-arch-test: wallyriscoftests memfiles
coverage: cov/rv64gc_arch64i.ucdb
#make -C ../tests/coverage --jobs
#iter-elf.bash --cover --search ../tests/coverage
vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb -logfile cov/log
# vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb cov/buildroot_buildroot.ucdb riscv.ucdb -logfile cov/log
@ -60,4 +59,4 @@ memfiles:
make -f makefile-memfile wally-sim-files --jobs
coveragetests:
make -C ../tests/coverage/
make -C ../tests/coverage/ --jobs

14
src/cache/cache.sv vendored
View File

@ -34,7 +34,6 @@ module cache import cvw::*; #(parameter cvw_t P,
input logic Stall, // Stall the cache, preventing new accesses. In-flight access finished but does not return to READY
input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations)
// cpu side
input logic [1:0] CacheRWNext, // [1] Read, [0] Write
input logic [1:0] CacheRW, // [1] Read, [0] Write
input logic FlushCache, // Flush all dirty lines back to memory
input logic InvalidateCache, // Clear all valid bits
@ -94,7 +93,6 @@ module cache import cvw::*; #(parameter cvw_t P,
logic FlushWayCntEn;
logic SelWriteback;
logic LRUWriteEn;
logic SelFlush;
logic ResetOrFlushCntRst;
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
logic SelFetchBuffer;
@ -112,10 +110,10 @@ module cache import cvw::*; #(parameter cvw_t P,
// and FlushAdr when handling D$ flushes
// The icache must update to the newest PCNextF on flush as it is probably a trap. Trap
// sets PCNextF to XTVEC and the icache must start reading the instruction.
assign AdrSelMuxSelData = {SelFlush, ((SelAdrData | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))};
assign AdrSelMuxSelData = {FlushCache, ((SelAdrData | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))};
mux3 #(SETLEN) AdrSelMuxData(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr,
AdrSelMuxSelData, CacheSetData);
assign AdrSelMuxSelTag = {SelFlush, ((SelAdrTag | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))};
assign AdrSelMuxSelTag = {FlushCache, ((SelAdrTag | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))};
mux3 #(SETLEN) AdrSelMuxTag(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr,
AdrSelMuxSelTag, CacheSetTag);
@ -123,7 +121,7 @@ module cache import cvw::*; #(parameter cvw_t P,
cacheway #(P, PA_BITS, XLEN, NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelWay,
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
.FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
// Select victim way for associative caches
if(NUMWAYS > 1) begin:vict
@ -162,7 +160,7 @@ module cache import cvw::*; #(parameter cvw_t P,
mux3 #(PA_BITS) CacheBusAdrMux(.d0({PAdr[PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}),
.s({SelFlush, SelWriteback}), .y(CacheBusAdr));
.s({FlushCache, SelWriteback}), .y(CacheBusAdr));
/////////////////////////////////////////////////////////////////////////////////////////////
// Write Path
@ -225,10 +223,10 @@ module cache import cvw::*; #(parameter cvw_t P,
/////////////////////////////////////////////////////////////////////////////////////////////
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
.FlushStage, .CacheRW, .CacheRWNext, .Stall,
.FlushStage, .CacheRW, .Stall,
.CacheHit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelWay,
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback, .SelFlush,
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
.InvalidateCache, .CMOpM, .CacheEn, .LRUWriteEn);

14
src/cache/cachefsm.sv vendored
View File

@ -38,7 +38,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
output logic CacheStall, // Cache stalls pipeline during multicycle operation
// inputs from IEU
input logic [1:0] CacheRW, // [1] Read, [0] Write
input logic [1:0] CacheRWNext, // [1] Read, [0] Write
input logic FlushCache, // Flush all dirty lines back to memory
input logic InvalidateCache, // Clear all valid bits
input logic [3:0] CMOpM, // 0001: cbo.inval; 0010: cbo.flush; 0100: cbo.clean; 1000: cbo.zero
@ -63,7 +62,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
output logic ClearDirty, // Clear the dirty bit in the selected way and set
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
output logic LRUWriteEn, // Update the LRU state
output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
output logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
output logic FlushWayCntEn, // Enable the way counter during a flush
@ -79,7 +77,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
logic CMOWriteback;
logic CMOZeroNoEviction;
logic StallConditions;
logic StoreHazard;
typedef enum logic [3:0]{STATE_READY, // hit states
// miss states
@ -106,8 +103,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_READY & ~Stall & ~FlushStage) | (CurrState == STATE_READ_HOLD & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
assign CacheMiss = CacheAccess & ~CacheHit;
assign StoreHazard = CacheRWNext[1] & CacheRW[0] & ~CacheRW[1];
// special case on reset. When the fsm first exists reset the
// PCNextF will no longer be pointing to the correct address.
// But PCF will be the reset vector.
@ -124,7 +119,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH;
else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement
else if(AnyMiss | CMOWriteback) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
else if(StoreHazard) NextState = STATE_READ_HOLD;
else NextState = STATE_READY;
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else if(CacheBusAck) NextState = STATE_READY;
@ -150,7 +144,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
// com back to CPU
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & (CurrState == STATE_READ_HOLD));
assign StallConditions = FlushCache | AnyMiss | CMOWriteback | (StoreHazard);
assign StallConditions = FlushCache | AnyMiss | CMOWriteback;
assign CacheStall = (CurrState == STATE_READY & StallConditions) | // exclusion-tag: icache StallStates
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
@ -180,12 +174,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
(CurrState == STATE_WRITE_LINE);
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) |
(CurrState == STATE_READY & AnyMiss & LineDirty);
/* -----\/----- EXCLUDED -----\/-----
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
(CurrState == STATE_FLUSH) |
(CurrState == STATE_FLUSH_WRITEBACK);
-----/\----- EXCLUDED -----/\----- */
assign SelFlush = FlushCache;
// coverage off -item e 1 -fecexprrow 1
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |

View File

@ -43,7 +43,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
input logic SetDirty, // Set the dirty bit in the selected way and set
input logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
input logic ClearDirty, // Clear the dirty bit in the selected way and set
input logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
input logic VictimWay, // LRU selected this way as victim to evict
input logic FlushWay, // This way is selected for flush and possible writeback if dirty
input logic InvalidateCache,// Clear all valid bits
@ -80,12 +80,12 @@ module cacheway import cvw::*; #(parameter cvw_t P,
if (!READ_ONLY_CACHE) begin:flushlogic
logic FlushWayEn;
mux2 #(1) seltagmux(VictimWay, FlushWay, SelFlush, SelDirty);
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelDirty);
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
// coverage off -item e 1 -fecexprrow 3
// nonzero ways will never see SelFlush=0 while FlushWay=1 since FlushWay only advances on a subset of SelFlush assertion cases.
assign FlushWayEn = FlushWay & SelFlush;
// nonzero ways will never see FlushCache=0 while FlushWay=1 since FlushWay only advances on a subset of FlushCache assertion cases.
assign FlushWayEn = FlushWay & FlushCache;
assign SelNonHit = FlushWayEn | SelWay;
end else begin:flushlogic // no flush operation for read-only caches.
assign SelDirty = VictimWay;

View File

@ -65,6 +65,7 @@ module ahbcacheinterface #(
input logic [PA_BITS-1:0] PAdr, // Physical address of uncached memory operation
input logic [LLEN-1:0] WriteDataM, // IEU write data for uncached store
input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
input logic BusAtomic, // Uncache atomic memory operation
input logic [2:0] Funct3, // Size of uncached memory operation
input logic BusCMOZero, // Uncached cbo.zero must write zero to full sized cacheline without going through the cache
@ -121,7 +122,7 @@ module ahbcacheinterface #(
flopen #(AHBW/8) HWSTRBReg(HCLK, HREADY, BusByteMaskM[AHBW/8-1:0], HWSTRB);
buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm(
.HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat,
.HCLK, .HRESETn, .Flush, .BusRW, .BusAtomic, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat,
.CacheBusRW, .BusCMOZero, .CacheBusAck, .BeatCount, .BeatCountDelayed,
.HREADY, .HTRANS, .HWRITE, .HBURST);
endmodule

View File

@ -42,6 +42,7 @@ module buscachefsm #(
input logic Stall, // Core pipeline is stalled
input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting
input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
input logic BusAtomic, // Uncache atomic memory operation
input logic BusCMOZero, // Uncached cbo.zero must write zero to full sized cacheline without going through the cache
output logic BusStall, // Bus is busy with an in flight memory operation
output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt
@ -65,7 +66,7 @@ module buscachefsm #(
output logic [2:0] HBURST // AHB burst length
);
typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype;
typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, ATOMIC_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype;
typedef enum logic [1:0] {AHB_IDLE = 2'b00, AHB_BUSY = 2'b01, AHB_NONSEQ = 2'b10, AHB_SEQ = 2'b11} ahbtranstype;
busstatetype CurrState, NextState;
@ -87,21 +88,25 @@ module buscachefsm #(
always_comb begin
case(CurrState)
ADR_PHASE: if (HREADY & |BusRW) NextState = DATA_PHASE;
else if (HREADY & BusWrite) NextState = CACHE_WRITEBACK;
else if (HREADY & BusWrite) NextState = CACHE_WRITEBACK;
else if (HREADY & CacheBusRW[1]) NextState = CACHE_FETCH;
else NextState = ADR_PHASE;
DATA_PHASE: if(HREADY) NextState = MEM3;
else NextState = DATA_PHASE;
MEM3: if(Stall) NextState = MEM3;
else NextState = ADR_PHASE;
CACHE_FETCH: if(HREADY & FinalBeatCount & BusWrite) NextState = CACHE_WRITEBACK;
else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH;
else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE;
else NextState = CACHE_FETCH;
CACHE_WRITEBACK: if(HREADY & FinalBeatCount & BusWrite) NextState = CACHE_WRITEBACK;
else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH;
else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE;
else NextState = CACHE_WRITEBACK;
DATA_PHASE: if(HREADY & BusAtomic) NextState = ATOMIC_PHASE;
else if(HREADY & ~BusAtomic) NextState = MEM3;
else NextState = DATA_PHASE;
ATOMIC_PHASE: if(HREADY) NextState = MEM3;
else NextState = ATOMIC_PHASE;
MEM3: if(Stall) NextState = MEM3;
else NextState = ADR_PHASE;
CACHE_FETCH: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK;
else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH;
else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE;
else NextState = CACHE_FETCH;
CACHE_WRITEBACK: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK;
else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH;
else if(HREADY & FinalBeatCount & BusCMOZero) NextState = MEM3;
else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE;
else NextState = CACHE_WRITEBACK;
default: NextState = ADR_PHASE;
endcase
end
@ -120,19 +125,23 @@ module buscachefsm #(
assign CaptureEn = (CurrState == DATA_PHASE & BusRW[1] & ~Flush) | (CurrState == CACHE_FETCH & HREADY);
assign CacheAccess = CurrState == CACHE_FETCH | CurrState == CACHE_WRITEBACK;
assign BusStall = (CurrState == ADR_PHASE & ((|BusRW) | (|CacheBusRW))) |
assign BusStall = (CurrState == ADR_PHASE & ((|BusRW) | (|CacheBusRW) | BusCMOZero)) |
//(CurrState == DATA_PHASE & ~BusRW[0]) | // *** replace the next line with this. Fails uart test but i think it's a test problem not a hardware problem.
(CurrState == DATA_PHASE) |
(CurrState == CACHE_FETCH & ~HREADY) |
(CurrState == CACHE_WRITEBACK & ~HREADY);
(CurrState == ATOMIC_PHASE) |
(CurrState == CACHE_FETCH & ~FinalBeatCount) |
(CurrState == CACHE_WRITEBACK & ~FinalBeatCount);
assign BusCommitted = (CurrState != ADR_PHASE) & ~(READ_ONLY_CACHE & CurrState == MEM3);
// AHB bus interface
assign HTRANS = (CurrState == ADR_PHASE & HREADY & ((|BusRW) | (|CacheBusRW)) & ~Flush) |
assign HTRANS = (CurrState == ADR_PHASE & HREADY & ((|BusRW) | (|CacheBusRW) | BusCMOZero) & ~Flush) |
(CurrState == DATA_PHASE & BusAtomic) |
(CacheAccess & FinalBeatCount & |CacheBusRW & HREADY & ~Flush) ? AHB_NONSEQ : // if we have a pipelined request
(CacheAccess & |BeatCount) ? (`BURST_EN ? AHB_SEQ : AHB_NONSEQ) : AHB_IDLE;
assign HWRITE = (BusRW[0] | BusWrite & ~Flush) | (CurrState == CACHE_WRITEBACK & |BeatCount);
assign HWRITE = ((BusRW[0] & ~BusAtomic) | BusWrite & ~Flush) | (CurrState == DATA_PHASE & BusAtomic) |
(CurrState == CACHE_WRITEBACK & |BeatCount);
assign HBURST = `BURST_EN & ((|CacheBusRW & ~Flush) | (CacheAccess & |BeatCount)) ? LocalBurstType : 3'b0;
always_comb begin
@ -149,6 +158,7 @@ module buscachefsm #(
assign CacheBusAck = (CacheAccess & HREADY & FinalBeatCount & ~BusCMOZero);
assign SelBusBeat = (CurrState == ADR_PHASE & (BusRW[0] | BusWrite)) |
(CurrState == DATA_PHASE & BusRW[0]) |
(CurrState == ATOMIC_PHASE & BusRW[0]) |
(CurrState == CACHE_WRITEBACK) |
(CurrState == CACHE_FETCH);

View File

@ -152,9 +152,11 @@ module controller import cvw::*; #(parameter cvw_t P) (
logic [3:0] CMOpD, CMOpE; // which CMO instruction 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
logic IFUPrefetchD; // instruction prefetch
logic LSUPrefetchD, LSUPrefetchE; // data prefetch
logic AMOStallD, CMOStallD; // Structural hazards from atomic and cache management ops
logic CMOStallD; // Structural hazards from cache management ops
logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage
logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read
logic StoreStallD; // load after store hazard
// Extract fields
assign OpD = InstrD[6:0];
@ -452,20 +454,12 @@ module controller import cvw::*; #(parameter cvw_t P) (
end
// Stall on dependent operations that finish in Mem Stage and can't bypass in time
assign MatchDE = ((Rs1D == RdE) | (Rs2D == RdE)) & (RdE != 5'b0); // Decode-stage instruction source depends on result from execute stage instruction
assign FCvtIntStallD = FCvtIntE & MatchDE; // FPU to Integer transfers have single-cycle latency except fcvt
assign LoadStallD = (MemReadE|SCE) & MatchDE;
assign MDUStallD = MDUE & MatchDE; // Int mult/div is at least two cycle latency, even when coming from the FDIV
assign CSRRdStallD = CSRReadE & MatchDE;
// the synchronous DTIM cannot read immediately after write
// a cache cannot read or write immediately after a write
// atomic operations are also detected as MemRWD[1] ***check; seems like & MemRWE
// *** RT: Remove this after updating the cache.
// *** RT: Check that atomic after atomic works correctly.
assign AMOStallD = &MemRWE & MemRWD[1]; // Read after atomic operation causes structural hazard
assign CMOStallD = (|CMOpE) & (|CMOpD); // CMO op after CMO op causes structural hazard ***explain, why doesn't interact with read/write
// Structural hazard causes stall if any of these events occur
assign StructuralStallD = LoadStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | AMOStallD | CMOStallD;
assign MatchDE = ((Rs1D == RdE) | (Rs2D == RdE)) & (RdE != 5'b0); // Decode-stage instruction source depends on result from execute stage instruction
assign LoadStallD = (MemReadE|SCE) & MatchDE;
assign StoreStallD = MemRWD[1] & MemRWE[0]; // Store or AMO followed by load or AMO
assign CSRRdStallD = CSRReadE & MatchDE;
assign MDUStallD = MDUE & MatchDE; // Int mult/div is at least two cycle latency, even when coming from the FDIV
assign FCvtIntStallD = FCvtIntE & MatchDE; // FPU to Integer transfers have single-cycle latency except fcvt
assign StructuralStallD = LoadStallD | StoreStallD | CSRRdStallD | MDUStallD | FCvtIntStallD;
endmodule

View File

@ -223,6 +223,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
// **** must fix words per line vs beats per line as in lsu.
localparam WORDSPERLINE = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/P.XLEN : 1;
localparam LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
if(P.ICACHE_SUPPORTED) begin : icache
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
@ -246,7 +247,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
.CacheMiss(ICacheMiss), .CacheAccess(ICacheAccess),
.ByteMask('0), .BeatCount('0), .SelBusBeat('0),
.CacheWriteData('0),
.CacheRW(CacheRWF), .CacheRWNext('0), // CacheRWNext is only used to detect hazards. Not possible with icache
.CacheRW(CacheRWF),
.FlushCache('0),
.NextSet(PCSpillNextF[11:0]),
.PAdr(PCPF),
@ -257,13 +258,18 @@ module ifu import cvw::*; #(parameter cvw_t P) (
.HRDATA,
.Flush(FlushD), .CacheBusRW, .BusCMOZero(1'b0), .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0),
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0), .BusAtomic('0),
.CacheBusAck(ICacheBusAck), .HWDATA(), .CacheableOrFlushCacheM(1'b0), .CacheReadDataWordM('0),
.FetchBuffer, .PAdr(PCPF),
.BusRW, .Stall(GatedStallD),
.BusStall, .BusCommitted(BusCommittedF));
mux3 #(32) UnCachedDataMux(.d0(ICacheInstrF), .d1(FetchBuffer[32-1:0]), .d2(IROMInstrF),
logic [31:0] ShiftUncachedInstr;
if(P.XLEN == 64) mux4 #(32) UncachedShiftInstrMux(FetchBuffer[32-1:0], FetchBuffer[48-1:16], FetchBuffer[64-1:32], {16'b0, FetchBuffer[64-1:48]},
PCSpillF[2:1], ShiftUncachedInstr);
else mux2 #(32) UncachedShiftInstrMux(FetchBuffer[32-1:0], {16'b0, FetchBuffer[32-1:16]}, PCSpillF[1], ShiftUncachedInstr);
mux3 #(32) UnCachedDataMux(.d0(ICacheInstrF), .d1(ShiftUncachedInstr), .d2(IROMInstrF),
.s({SelIROM, ~CacheableF}), .y(InstrRawF[31:0]));
end else begin : passthrough
assign IFUHADDR = PCPF;

View File

@ -28,17 +28,15 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module dtim import cvw::*; #(parameter cvw_t P) (
input logic clk, reset,
input logic FlushW,
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
input logic [1:0] MemRWM, // Read/Write control
input logic [1:0] MemRWE, // Read/Write control
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
output logic [P.LLEN-1:0] ReadDataWordM, // Read data before subword selection
output logic DTIMStall,
output logic DTIMSelWrite
input logic clk, reset,
input logic FlushW,
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
input logic [1:0] MemRWM, // Read/Write control
input logic [1:0] MemRWE, // Read/Write control
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
output logic [P.LLEN-1:0] ReadDataWordM // Read data before subword selection
);
logic we;
@ -50,16 +48,8 @@ module dtim import cvw::*; #(parameter cvw_t P) (
localparam ADDR_WDITH = $clog2(DEPTH);
localparam OFFSET = $clog2(LLENBYTES);
logic DTIMStallHazard, DTIMStallHazardD;
assign DTIMStallHazard = MemRWM[0] & MemRWE[1];
flopr #(1) DTIMStallReg(clk, reset, DTIMStallHazard, DTIMStallHazardD);
assign DTIMStall = DTIMStallHazard & ~DTIMStallHazardD;
assign DTIMSelWrite = MemRWM[0] & ~(DTIMStallHazard & ~DTIMStall);
assign we = DTIMSelWrite & ~FlushW; // have to ignore write if Trap.
assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap.
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(DEPTH), .WIDTH(P.LLEN))
ram(.clk, .ce(ce | DTIMSelWrite), .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
endmodule

View File

@ -150,7 +150,6 @@ module lsu import cvw::*; #(parameter cvw_t P) (
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
logic SelDTIM; // Select DTIM rather than bus or D$
logic [P.XLEN-1:0] WriteDataZM;
logic DTIMStall;
/////////////////////////////////////////////////////////////////////////////////////////////
// Pipeline for IEUAdr E to M
@ -220,7 +219,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
// the trap module.
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
assign GatedStallW = StallW & ~SelHPTW;
assign CacheBusHPWTStall = DCacheStallM | HPTWStall | BusStall | DTIMStall;
assign CacheBusHPWTStall = DCacheStallM | HPTWStall | BusStall;
assign LSUStallM = CacheBusHPWTStall | SpillStallM;
/////////////////////////////////////////////////////////////////////////////////////////////
@ -269,10 +268,9 @@ module lsu import cvw::*; #(parameter cvw_t P) (
if (P.DTIM_SUPPORTED) begin : dtim
logic [P.PA_BITS-1:0] DTIMAdr;
logic [1:0] DTIMMemRWM;
logic DTIMSelWrite;
// 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], DTIMSelWrite, DTIMAdr);
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.
@ -280,9 +278,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
dtim #(P) dtim(.clk, .reset, .ce(~GatedStallW), .MemRWE(MemRWE), // *** update when you update the cache RWE
.MemRWM(DTIMMemRWM),
.DTIMAdr, .FlushW, .WriteDataM(LSUWriteDataM),
.ReadDataWordM(DTIMReadDataWordM[P.LLEN-1:0]), .ByteMaskM(ByteMaskM), .DTIMStall, .DTIMSelWrite);
end else begin
assign DTIMStall = '0;
.ReadDataWordM(DTIMReadDataWordM[P.LLEN-1:0]), .ByteMaskM(ByteMaskM));
end
if (P.BUS_SUPPORTED) begin : bus
if(P.DCACHE_SUPPORTED) begin : dcache
@ -307,11 +303,17 @@ module lsu import cvw::*; #(parameter cvw_t P) (
logic CacheStall;
logic [1:0] CacheBusRWTemp;
logic BusCMOZero;
logic [3:0] CacheCMOpM;
logic BusAtomic;
if(P.ZICBOZ_SUPPORTED) begin
assign BusCMOZero = CMOpM[3] & ~CacheableM;
assign CacheCMOpM = CacheableM ? 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;
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
@ -320,7 +322,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
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(
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB), .CacheRWNext(MemRWE), // *** change to LSURWE after updating hptw and atomic
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM),
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
@ -329,8 +331,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
.CacheCommitted(DCacheCommittedM),
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
.FetchBuffer, .CacheBusRW(CacheBusRWTemp),
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0), .CMOpM(CMOpM));
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0), .CMOpM(CacheCMOpM));
assign DCacheStallM = CacheStall & ~IgnoreRequestTLB;
assign CacheBusRW = CacheBusRWTemp;
@ -340,7 +342,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
.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, .BusCMOZero, .CacheableOrFlushCacheM,
.Funct3(LSUFunct3M), .HADDR(LSUHADDR), .CacheBusAdr(DCacheBusAdr), .CacheBusRW, .BusAtomic, .BusCMOZero, .CacheableOrFlushCacheM,
.CacheBusAck(DCacheBusAck), .FetchBuffer, .PAdr(PAdrM),
.Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW),
.BusStall, .BusCommitted(BusCommittedM));