cvw/pipelined/src/cache/cachefsm.sv

192 lines
9.4 KiB
Systemverilog
Raw Normal View History

///////////////////////////////////////////
// dcache (data cache) fsm
//
// Written: ross1728@gmail.com August 25, 2021
// Implements the L1 data cache fsm
//
// Purpose: Controller for the dcache fsm
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// MIT LICENSE
// 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"
module cachefsm
(input logic clk,
input logic reset,
// inputs from IEU
input logic FlushStage,
input logic [1:0] CacheRW,
input logic [1:0] CacheAtomic,
input logic FlushCache,
input logic InvalidateCache,
// hazard inputs
2022-12-11 21:49:34 +00:00
input logic Stall,
// Bus inputs
input logic CacheBusAck,
// dcache internals
input logic CacheHit,
2022-12-04 22:09:09 +00:00
input logic LineDirty,
input logic FlushAdrFlag,
input logic FlushWayFlag,
// hazard outputs
output logic CacheStall,
// counter outputs
output logic CacheMiss,
output logic CacheAccess,
// Bus outputs
output logic CacheCommitted,
output logic [1:0] CacheBusRW,
// dcache internals
output logic SelAdr,
output logic ClearValid,
output logic ClearDirty,
output logic SetDirty,
output logic SetValid,
2022-12-14 15:49:15 +00:00
output logic SelWriteback,
output logic LRUWriteEn,
output logic SelFlush,
output logic FlushAdrCntEn,
output logic FlushWayCntEn,
output logic FlushCntRst,
output logic SelFetchBuffer,
2022-12-14 15:49:15 +00:00
output logic CacheEn);
logic resetDelay;
2022-12-04 22:09:09 +00:00
logic AMO, StoreAMO;
logic AnyUpdateHit, AnyHit;
logic AnyMiss;
logic FlushFlag;
2022-02-07 19:29:19 +00:00
2022-02-12 04:54:05 +00:00
typedef enum logic [3:0] {STATE_READY, // hit states
// miss states
STATE_MISS_FETCH_WDV,
STATE_MISS_EVICT_DIRTY,
STATE_MISS_WRITE_CACHE_LINE,
STATE_MISS_READ_DELAY, // required for back to back reads. structural hazard on writting SRAM
2022-02-12 04:54:05 +00:00
// flush cache
STATE_FLUSH,
STATE_FLUSH_WRITE_BACK} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
2022-03-08 22:34:02 +00:00
assign AMO = CacheAtomic[1] & (&CacheRW);
2022-12-04 22:09:09 +00:00
assign StoreAMO = AMO | CacheRW[0];
2022-02-07 19:29:19 +00:00
2022-12-04 22:09:09 +00:00
assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache;
assign AnyUpdateHit = (StoreAMO) & CacheHit;
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit);
2022-02-07 19:29:19 +00:00
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
// outputs for the performance counters.
assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY;
2022-02-07 16:33:50 +00:00
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.
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
always_ff @(posedge clk)
if (reset | FlushStage) CurrState <= #1 STATE_READY;
else CurrState <= #1 NextState;
always_comb begin
NextState = STATE_READY;
case (CurrState)
2022-12-16 22:32:21 +00:00
STATE_READY: if(InvalidateCache) NextState = STATE_READY;
else if(FlushCache) NextState = STATE_FLUSH;
2022-07-24 05:34:11 +00:00
// Delayed LRU update. Cannot check if victim line is dirty on this cycle.
// To optimize do the fetch first, then eviction if necessary.
2022-12-04 22:09:09 +00:00
else if(AnyMiss & ~LineDirty) NextState = STATE_MISS_FETCH_WDV;
else if(AnyMiss & LineDirty) NextState = STATE_MISS_EVICT_DIRTY;
2022-12-16 22:32:21 +00:00
else NextState = STATE_READY;
STATE_MISS_FETCH_WDV: if(CacheBusAck) NextState = STATE_MISS_WRITE_CACHE_LINE;
else NextState = STATE_MISS_FETCH_WDV;
STATE_MISS_WRITE_CACHE_LINE: NextState = STATE_MISS_READ_DELAY;
STATE_MISS_READ_DELAY: if(Stall) NextState = STATE_MISS_READ_DELAY;
else NextState = STATE_READY;
STATE_MISS_EVICT_DIRTY: if(CacheBusAck) NextState = STATE_MISS_FETCH_WDV;
else NextState = STATE_MISS_EVICT_DIRTY;
// 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.
2022-12-16 22:32:21 +00:00
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITE_BACK;
else if (FlushFlag) NextState = STATE_READY;
else NextState = STATE_FLUSH;
STATE_FLUSH_WRITE_BACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
else if(CacheBusAck) NextState = STATE_READY;
else NextState = STATE_FLUSH_WRITE_BACK;
default: NextState = STATE_READY;
endcase
end
2022-02-08 23:52:09 +00:00
// com back to CPU
assign CacheCommitted = CurrState != STATE_READY;
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) |
2022-02-07 03:39:38 +00:00
(CurrState == STATE_MISS_FETCH_WDV) |
2022-02-12 04:54:05 +00:00
(CurrState == STATE_MISS_EVICT_DIRTY) |
2022-12-04 22:09:09 +00:00
(CurrState == STATE_MISS_WRITE_CACHE_LINE & ~(StoreAMO)) | // 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 & ~(FlushFlag & ~LineDirty)) |
(CurrState == STATE_FLUSH_WRITE_BACK & ~(FlushFlag & CacheBusAck));
2022-02-08 23:52:09 +00:00
// write enables internal to cache
2022-02-13 21:06:18 +00:00
assign SetValid = CurrState == STATE_MISS_WRITE_CACHE_LINE;
assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) |
2022-12-04 22:09:09 +00:00
(CurrState == STATE_MISS_WRITE_CACHE_LINE & (StoreAMO));
assign ClearValid = '0;
2022-12-04 22:09:09 +00:00
assign ClearDirty = (CurrState == STATE_MISS_WRITE_CACHE_LINE & ~(StoreAMO)) |
(CurrState == STATE_FLUSH_WRITE_BACK & CacheBusAck);
assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) |
(CurrState == STATE_MISS_WRITE_CACHE_LINE);
2022-02-08 23:52:09 +00:00
// Flush and eviction controls
2022-12-14 15:49:15 +00:00
assign SelWriteback = (CurrState == STATE_MISS_EVICT_DIRTY & ~CacheBusAck) |
2022-12-04 22:09:09 +00:00
(CurrState == STATE_READY & AnyMiss & LineDirty);
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
(CurrState == STATE_FLUSH & ~FlushFlag) |
(CurrState == STATE_FLUSH_WRITE_BACK & ~(CacheBusAck & FlushFlag));
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITE_BACK & FlushWayFlag & CacheBusAck) |
(CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty);
assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITE_BACK & CacheBusAck);
2022-12-16 22:32:21 +00:00
assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) |
(CurrState == STATE_FLUSH_WRITE_BACK & FlushFlag & CacheBusAck);
2022-02-08 23:52:09 +00:00
// Bus interface controls
2022-12-04 22:09:09 +00:00
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) |
(CurrState == STATE_MISS_FETCH_WDV & ~CacheBusAck) |
(CurrState == STATE_MISS_EVICT_DIRTY & CacheBusAck);
2022-12-04 22:09:09 +00:00
assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) |
(CurrState == STATE_MISS_EVICT_DIRTY & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITE_BACK & ~CacheBusAck);
2022-02-07 19:19:37 +00:00
// **** can this be simplified?
2022-12-04 22:09:09 +00:00
assign SelAdr = (CurrState == STATE_READY & ((StoreAMO) & CacheHit)) | // changes if store delay hazard removed
(CurrState == STATE_READY & (AnyMiss)) |
(CurrState == STATE_MISS_FETCH_WDV) |
(CurrState == STATE_MISS_EVICT_DIRTY) |
2022-02-12 05:10:58 +00:00
(CurrState == STATE_MISS_WRITE_CACHE_LINE) |
resetDelay;
assign SelFetchBuffer = CurrState == STATE_MISS_WRITE_CACHE_LINE | CurrState == STATE_MISS_READ_DELAY;
2022-12-14 15:49:15 +00:00
assign CacheEn = (CurrState == STATE_READY & ~Stall | CacheStall) | (CurrState != STATE_READY) | reset;
2022-02-07 16:43:58 +00:00
endmodule // cachefsm