forked from Github_Repos/cvw
refactor cachefsm to get full coverage
I had to exclude i$ states in coverage-exclusions-rv64gc.do, but it's referred to by scope, which should be pretty robust
This commit is contained in:
parent
1ce2ab5daa
commit
729f81a0df
@ -32,6 +32,12 @@
|
||||
# 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
|
||||
coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY
|
||||
|
||||
######################
|
||||
# Toggle exclusions
|
||||
|
195
src/cache/cachefsm.sv
vendored
195
src/cache/cachefsm.sv
vendored
@ -86,18 +86,25 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
|
||||
|
||||
statetype CurrState, NextState;
|
||||
|
||||
assign AMO = CacheAtomic[1] & (&CacheRW);
|
||||
assign StoreAMO = AMO | CacheRW[0];
|
||||
// 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 AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache;
|
||||
assign AnyUpdateHit = (StoreAMO) & CacheHit;
|
||||
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit);
|
||||
assign CacheMiss = CacheAccess & ~CacheHit; // for performance counter
|
||||
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
|
||||
|
||||
// outputs for the performance counters.
|
||||
assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY;
|
||||
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.
|
||||
@ -106,77 +113,119 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
|
||||
always_ff @(posedge clk)
|
||||
if (reset | FlushStage) CurrState <= #1 STATE_READY;
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
always_comb begin
|
||||
NextState = STATE_READY;
|
||||
case (CurrState)
|
||||
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;
|
||||
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
|
||||
|
||||
// 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
|
||||
|
||||
// com back to CPU
|
||||
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD);
|
||||
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) |
|
||||
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) |
|
||||
(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;
|
||||
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.
|
||||
assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) |
|
||||
(CurrState == STATE_WRITE_LINE);
|
||||
// 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);
|
||||
// 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);
|
||||
|
||||
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 SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
|
||||
assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache;
|
||||
|
||||
endmodule // cachefsm
|
||||
|
Loading…
Reference in New Issue
Block a user