2022-01-05 05:52:42 +00:00
///////////////////////////////////////////
// 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
//
2022-01-07 12:58:40 +00:00
// 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:
2022-01-05 05:52:42 +00:00
//
2022-01-07 12:58:40 +00:00
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
2022-01-05 05:52:42 +00:00
//
2022-01-07 12:58:40 +00:00
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
2022-01-05 05:52:42 +00:00
`include " wally-config.vh "
module cachefsm
( input logic clk ,
2022-09-23 16:46:53 +00:00
input logic reset ,
2022-01-05 05:52:42 +00:00
// inputs from IEU
2022-11-14 20:11:05 +00:00
input logic FlushStage ,
2022-09-23 16:46:53 +00:00
input logic [ 1 : 0 ] CacheRW ,
input logic [ 1 : 0 ] CacheAtomic ,
input logic FlushCache ,
input logic InvalidateCache ,
2022-01-05 05:52:42 +00:00
// hazard inputs
2022-12-11 21:49:34 +00:00
input logic Stall ,
2022-01-05 05:52:42 +00:00
// Bus inputs
2022-09-23 16:46:53 +00:00
input logic CacheBusAck ,
2022-01-05 05:52:42 +00:00
// dcache internals
2022-09-23 16:46:53 +00:00
input logic CacheHit ,
2022-12-04 22:09:09 +00:00
input logic LineDirty ,
2022-09-23 16:46:53 +00:00
input logic FlushAdrFlag ,
input logic FlushWayFlag ,
2022-01-05 05:52:42 +00:00
// hazard outputs
2022-09-23 16:46:53 +00:00
output logic CacheStall ,
2022-01-05 05:52:42 +00:00
// counter outputs
2022-09-23 16:46:53 +00:00
output logic CacheMiss ,
output logic CacheAccess ,
2022-01-05 05:52:42 +00:00
// Bus outputs
2022-09-23 16:46:53 +00:00
output logic CacheCommitted ,
output logic [ 1 : 0 ] CacheBusRW ,
2022-01-05 05:52:42 +00:00
// dcache internals
2022-09-23 16:46:53 +00:00
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 ,
2022-09-23 16:46:53 +00:00
output logic LRUWriteEn ,
output logic SelFlush ,
output logic FlushAdrCntEn ,
output logic FlushWayCntEn ,
2022-12-16 21:34:14 +00:00
output logic FlushCntRst ,
2022-12-05 23:51:13 +00:00
output logic SelFetchBuffer ,
2022-12-14 15:49:15 +00:00
output logic CacheEn ) ;
2022-01-05 05:52:42 +00:00
2022-01-26 23:37:04 +00:00
logic resetDelay ;
2022-12-04 22:09:09 +00:00
logic AMO , StoreAMO ;
2022-11-07 21:03:43 +00:00
logic AnyUpdateHit , AnyHit ;
logic AnyMiss ;
2022-12-16 22:22:40 +00:00
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 ,
2022-08-21 20:28:29 +00:00
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 ,
2022-07-24 05:22:43 +00:00
STATE_FLUSH_WRITE_BACK } statetype ;
2022-01-05 05:52:42 +00:00
( * 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 ;
2022-11-07 21:03:43 +00:00
assign AnyHit = AnyUpdateHit | ( CacheRW [ 1 ] & CacheHit ) ;
2022-02-07 19:29:19 +00:00
assign FlushFlag = FlushAdrFlag & FlushWayFlag ;
2022-01-05 05:52:42 +00:00
// outputs for the performance counters.
2022-11-07 21:03:43 +00:00
assign CacheAccess = ( AMO | CacheRW [ 1 ] | CacheRW [ 0 ] ) & CurrState = = STATE_READY ;
2022-02-07 16:33:50 +00:00
assign CacheMiss = CacheAccess & ~ CacheHit ;
2022-01-05 05:52:42 +00:00
2022-01-26 23:37:04 +00:00
// 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 ) ) ;
2022-01-05 05:52:42 +00:00
always_ff @ ( posedge clk )
2022-11-14 20:11:05 +00:00
if ( reset | FlushStage ) CurrState < = # 1 STATE_READY ;
2022-01-05 05:52:42 +00:00
else CurrState < = # 1 NextState ;
always_comb begin
NextState = STATE_READY ;
case ( CurrState )
2022-11-01 20:23:24 +00:00
STATE_READY: if ( InvalidateCache ) NextState = STATE_READY ;
2022-11-07 21:03:43 +00:00
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-07-24 05:34:11 +00:00
else NextState = STATE_READY ;
2022-10-04 20:29:32 +00:00
STATE_MISS_FETCH_WDV: if ( CacheBusAck ) NextState = STATE_MISS_WRITE_CACHE_LINE ;
2022-07-24 05:34:11 +00:00
else NextState = STATE_MISS_FETCH_WDV ;
2022-08-21 20:28:29 +00:00
//STATE_MISS_WRITE_CACHE_LINE: NextState = STATE_READY;
2022-10-04 20:29:32 +00:00
STATE_MISS_WRITE_CACHE_LINE: NextState = STATE_MISS_READ_DELAY ;
2022-09-26 22:41:30 +00:00
//else NextState = STATE_READY;
2022-12-11 21:49:34 +00:00
STATE_MISS_READ_DELAY: if ( Stall ) NextState = STATE_MISS_READ_DELAY ;
2022-08-21 20:59:54 +00:00
else NextState = STATE_READY ;
2022-10-04 20:29:32 +00:00
STATE_MISS_EVICT_DIRTY: if ( CacheBusAck ) NextState = STATE_MISS_FETCH_WDV ;
2022-07-24 05:34:11 +00:00
else NextState = STATE_MISS_EVICT_DIRTY ;
2022-07-24 06:20:29 +00:00
// 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 21:28:22 +00:00
STATE_FLUSH: if ( LineDirty ) NextState = STATE_FLUSH_WRITE_BACK ;
else if ( FlushFlag & FlushWayFlag ) NextState = STATE_READY ;
else NextState = STATE_FLUSH ;
STATE_FLUSH_WRITE_BACK: if ( CacheBusAck & ~ ( FlushFlag & FlushWayFlag ) ) NextState = STATE_FLUSH ;
else if ( CacheBusAck ) NextState = STATE_READY ;
else NextState = STATE_FLUSH_WRITE_BACK ;
2022-07-24 05:34:11 +00:00
default : NextState = STATE_READY ;
2022-01-05 05:52:42 +00:00
endcase
end
2022-02-08 23:52:09 +00:00
// com back to CPU
2022-01-05 05:52:42 +00:00
assign CacheCommitted = CurrState ! = STATE_READY ;
2022-11-07 21:03:43 +00:00
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.
2022-12-16 21:28:22 +00:00
( CurrState = = STATE_FLUSH & ~ ( FlushFlag & ~ LineDirty ) ) |
//(CurrState == STATE_FLUSH_CHECK & ~(FlushFlag)) |
//(CurrState == STATE_FLUSH_INCR) |
( 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 ;
2022-11-07 21:03:43 +00:00
assign SetDirty = ( CurrState = = STATE_READY & AnyUpdateHit ) |
2022-12-04 22:09:09 +00:00
( CurrState = = STATE_MISS_WRITE_CACHE_LINE & ( StoreAMO ) ) ;
2022-02-12 04:41:36 +00:00
assign ClearValid = '0 ;
2022-12-04 22:09:09 +00:00
assign ClearDirty = ( CurrState = = STATE_MISS_WRITE_CACHE_LINE & ~ ( StoreAMO ) ) |
2022-07-24 05:22:43 +00:00
( CurrState = = STATE_FLUSH_WRITE_BACK & CacheBusAck ) ;
2022-11-07 21:03:43 +00:00
assign LRUWriteEn = ( CurrState = = STATE_READY & AnyHit ) |
2022-07-19 04:37:18 +00:00
( 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 ) ;
2022-12-16 22:22:40 +00:00
assign SelFlush = ( CurrState = = STATE_READY & FlushCache ) |
( CurrState = = STATE_FLUSH & ~ FlushFlag ) |
( CurrState = = STATE_FLUSH_WRITE_BACK & ~ ( CacheBusAck & FlushFlag ) ) ;
2022-12-16 21:28:22 +00:00
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 21:34:14 +00:00
assign FlushCntRst = ( CurrState = = STATE_FLUSH & FlushFlag & FlushWayFlag & ~ LineDirty ) |
2022-12-16 21:28:22 +00:00
( CurrState = = STATE_FLUSH_WRITE_BACK & FlushFlag & FlushWayFlag & 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 ) |
2022-10-04 20:29:32 +00:00
( 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 ) |
2022-09-27 16:34:33 +00:00
( CurrState = = STATE_MISS_EVICT_DIRTY & ~ CacheBusAck ) |
2022-12-16 22:22:40 +00:00
( 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
2022-11-07 21:03:43 +00:00
( CurrState = = STATE_READY & ( AnyMiss ) ) |
2022-02-12 04:41:36 +00:00
( CurrState = = STATE_MISS_FETCH_WDV ) |
( CurrState = = STATE_MISS_EVICT_DIRTY ) |
2022-02-12 05:10:58 +00:00
( CurrState = = STATE_MISS_WRITE_CACHE_LINE ) |
2022-02-12 04:41:36 +00:00
resetDelay ;
2022-07-19 04:37:18 +00:00
2022-12-05 23:51:13 +00:00
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
2022-01-05 05:52:42 +00:00
endmodule // cachefsm