cachefsm exclude icache logic without code reuse

This commit is contained in:
Alec Vercruysse 2023-04-12 15:57:45 -07:00
parent 800f0245f3
commit a3d9e11b0f
2 changed files with 105 additions and 127 deletions

View file

@ -27,17 +27,41 @@
# This file should be a last resort. It's preferable to put
# // coverage off
# statements inline with the code whenever possible.
# a hack to describe coverage exclusions without hardcoding linenumbers:
do GetLineNum.do
# LZA (i<64) statement confuses coverage tool
# This is ugly to exlcude the whole file - is there a better option? // coverage off isn't working
coverage exclude -srcfile lzc.sv
# Exclude D$ states from coverage in the I$ instance of cachefsm.
# This is cleaner than trying to set an I$-specific pragma in cachefsm.sv
# Also exclude the write line to ready transition for the I$ since we can't get a flush
# during this operation.
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK
### Exclude D$ states and logic for the I$ instance
# This is cleaner than trying to set an I$-specific pragma in cachefsm.sv (which would exclude it for the D$ instance too)
# Also exclude the write line to ready transition for the I$ since we can't get a flush during this operation.
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK STATE_WRITEBACK
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY
# exclude unused transitions from case statement. Unfortunately the whole branch needs to be excluded I think. Expression coverage should still work.
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache state-case"] -item b 1
# exclude branch/condition coverage: LineDirty if statement
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache FETCHStatement"] -item bc 1
# exclude the unreachable logic
set start [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-start: icache case"]
set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache case"]
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $start-$end
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache WRITEBACKStatement"]
# exclude Atomic Operation logic
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache storeAMO"] -item e 1 -fecexprrow 6
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache storeAMO1"] -item e 1 -fecexprrow 2-4
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache AnyUpdateHit"] -item e 1 -fecexprrow 2
# cache write logic
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheW"] -item e 1 -fecexprrow 4
# output signal logic
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache StallStates"] -item e 1 -fecexprrow 8 12 14
set start [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-start: icache flushdirtycontrols"]
set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache flushdirtycontrols"]
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $start-$end
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusW"]
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache SelAdrCauses"] -item e 1 -fecexprrow 4 10
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusRCauses"] -item e 1 -fecexprrow 1-2 12
######################
# Toggle exclusions

198
src/cache/cachefsm.sv vendored
View file

@ -86,25 +86,18 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
statetype CurrState, NextState;
// no atomic operations on i$
if (!READ_ONLY_CACHE) begin
assign AMO = CacheAtomic[1] & (&CacheRW);
assign StoreAMO = AMO | CacheRW[0];
assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache;
assign AnyUpdateHit = StoreAMO & CacheHit;
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit);
assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; // for performance counter
end
else begin
assign AnyMiss = CacheRW[1] & ~CacheHit & ~InvalidateCache;
assign AnyUpdateHit = 0; // todo clear all RO cache of usage of this logic
assign AnyHit = CacheRW[1] & CacheHit;
assign CacheAccess = CacheRW[1] & CurrState == STATE_READY; // for performance counter
end
assign AMO = CacheAtomic[1] & (&CacheRW);
assign StoreAMO = AMO | CacheRW[0];
assign CacheMiss = CacheAccess & ~CacheHit; // for performance counter
assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: icache storeAMO
assign AnyUpdateHit = (StoreAMO) & CacheHit; // exclusion-tag: icache storeAMO1
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
// outputs for the performance counters.
assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; // exclusion-tag: icache CacheW
assign CacheMiss = CacheAccess & ~CacheHit;
// 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.
@ -113,120 +106,81 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
always_ff @(posedge clk)
if (reset | FlushStage) CurrState <= #1 STATE_READY;
else CurrState <= #1 NextState;
// seperating NextState logic by ro vs rw cache results in code duplication but this is needed to hit coverage.
if (!READ_ONLY_CACHE)
always_comb begin
NextState = STATE_READY;
case (CurrState)
STATE_READY: if(InvalidateCache) NextState = STATE_READY;
else if(FlushCache) NextState = STATE_FLUSH;
else if(AnyMiss & ~LineDirty) NextState = STATE_FETCH;
else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK;
else NextState = STATE_READY;
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
else NextState = STATE_READY;
STATE_WRITEBACK: if(CacheBusAck) NextState = STATE_FETCH;
else NextState = STATE_WRITEBACK;
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same
// time as getting back the bus ack.
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
else if (FlushFlag) NextState = STATE_READ_HOLD;
else NextState = STATE_FLUSH;
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
else if(CacheBusAck) NextState = STATE_READ_HOLD;
else NextState = STATE_FLUSH_WRITEBACK;
default: NextState = STATE_READY;
endcase
end // always_comb
else // READ_ONLY_CACHE
always_comb begin
NextState = STATE_READY;
case (CurrState)
STATE_READY: if(InvalidateCache) NextState = STATE_READY;
else if(AnyMiss) NextState = STATE_FETCH;
else NextState = STATE_READY;
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
else NextState = STATE_READY;
default: NextState = STATE_READY;
endcase // case (CurrState)
end // always_comb
always_comb begin
NextState = STATE_READY;
case (CurrState) // exclusion-tag: icache state-case
STATE_READY: if(InvalidateCache) NextState = STATE_READY;
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 & LineDirty) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
else NextState = STATE_READY;
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
else NextState = STATE_READY;
// exclusion-tag-start: icache case
STATE_WRITEBACK: if(CacheBusAck) NextState = STATE_FETCH;
else NextState = STATE_WRITEBACK;
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
else if (FlushFlag) NextState = STATE_READ_HOLD;
else NextState = STATE_FLUSH;
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
else if(CacheBusAck) NextState = STATE_READ_HOLD;
else NextState = STATE_FLUSH_WRITEBACK;
// exclusion-tag-end: icache case
default: NextState = STATE_READY;
endcase
end
// com back to CPU
if (!READ_ONLY_CACHE) begin
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) |
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
(CurrState == STATE_FLUSH) |
(CurrState == STATE_FLUSH_WRITEBACK);
assign CacheCommitted = CurrState != STATE_READY;
assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // changes if store delay hazard removed
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) |
resetDelay;
assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) |
(CurrState == STATE_WRITE_LINE & (StoreAMO));
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) |
(CurrState == STATE_FLUSH & LineDirty); // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
// Flush and eviction controls
assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_READY & AnyMiss & LineDirty);
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
(CurrState == STATE_FLUSH) |
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD);
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | // exclusion-tag: icache StallStates
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
(CurrState == STATE_FLUSH) |
(CurrState == STATE_FLUSH_WRITEBACK);
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
(CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty);
assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck);
assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
// Bus interface controls
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) |
(CurrState == STATE_FETCH & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & CacheBusAck);
assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) |
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck);
// write enable internal to cache
assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache;
end
else begin
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) |
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITE_LINE); // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
assign CacheCommitted = (CurrState != STATE_READY) & ~(CurrState == STATE_READ_HOLD);
assign SelAdr = (CurrState == STATE_READY & AnyMiss) | // changes if store delay hazard removed
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITE_LINE) |
resetDelay;
assign SetDirty = 0;
assign ClearDirty = 0;
assign SelWriteback = 0;
assign SelFlush = 0;
assign FlushAdrCntEn = 0;
assign FlushWayCntEn = 0;
assign FlushCntRst = 0;
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss) |
(CurrState == STATE_FETCH & ~CacheBusAck);
assign CacheBusRW[0] = 0;
assign CacheEn = (~Stall | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache;
end // else: (READ_ONLY_CACHE)
// write enables internal to cache
assign SetValid = CurrState == STATE_WRITE_LINE;
// coverage off -item e 1 -fecexprrow 8
assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) |
(CurrState == STATE_WRITE_LINE) & ~FlushStage;
// exclusion-tag-start: icache flushdirtycontrols
assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) | // exclusion-tag: icache SetDirty
(CurrState == STATE_WRITE_LINE & (StoreAMO));
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) | // exclusion-tag: icache ClearDirty
(CurrState == STATE_FLUSH & LineDirty); // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
// Flush and eviction controls
assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_READY & AnyMiss & LineDirty);
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
(CurrState == STATE_FLUSH) |
(CurrState == STATE_FLUSH_WRITEBACK);
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
(CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty);
assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck);
assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
// exclusion-tag-end: icache flushdirtycontrols
// Bus interface controls
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
(CurrState == STATE_FETCH & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & CacheBusAck);
assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | // exclusion-tag: icache CacheBusW
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck);
assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) |
resetDelay;
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache;
endmodule // cachefsm