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-07-19 04:37:18 +00:00
input logic reset ,
2022-01-05 05:52:42 +00:00
// inputs from IEU
2022-03-08 22:34:02 +00:00
input logic [ 1 : 0 ] CacheRW ,
input logic [ 1 : 0 ] CacheAtomic ,
2022-07-19 04:37:18 +00:00
input logic FlushCache ,
2022-07-23 03:42:39 +00:00
input logic InvalidateCache ,
2022-01-05 05:52:42 +00:00
// hazard inputs
2022-07-19 04:37:18 +00:00
input logic CPUBusy ,
2022-01-05 05:52:42 +00:00
// interlock fsm
2022-07-19 04:37:18 +00:00
input logic IgnoreRequestTLB ,
2022-08-21 20:28:29 +00:00
input logic TrapM ,
2022-01-05 05:52:42 +00:00
// Bus inputs
2022-07-19 04:37:18 +00:00
input logic CacheBusAck ,
2022-01-05 05:52:42 +00:00
// dcache internals
2022-07-19 04:37:18 +00:00
input logic CacheHit ,
input logic VictimDirty ,
input logic FlushAdrFlag ,
input logic FlushWayFlag ,
2022-01-05 05:52:42 +00:00
// hazard outputs
2022-07-19 04:37:18 +00:00
output logic CacheStall ,
2022-01-05 05:52:42 +00:00
// counter outputs
2022-07-19 04:37:18 +00:00
output logic CacheMiss ,
output logic CacheAccess ,
2022-01-05 05:52:42 +00:00
// Bus outputs
2022-07-19 04:37:18 +00:00
output logic CacheCommitted ,
output logic CacheWriteLine ,
output logic CacheFetchLine ,
2022-01-05 05:52:42 +00:00
// dcache internals
2022-07-19 04:37:18 +00:00
output logic SelAdr ,
output logic ClearValid ,
output logic ClearDirty ,
output logic SetDirty ,
output logic SetValid ,
output logic SelEvict ,
output logic LRUWriteEn ,
output logic SelFlush ,
output logic FlushAdrCntEn ,
output logic FlushWayCntEn ,
output logic FlushAdrCntRst ,
output logic FlushWayCntRst ,
2022-07-23 03:42:39 +00:00
output logic SelBusBuffer ,
output logic SRAMEnable ) ;
2022-01-05 05:52:42 +00:00
2022-01-26 23:37:04 +00:00
logic resetDelay ;
2022-02-11 20:54:57 +00:00
logic AMO ;
2022-02-07 16:33:50 +00:00
logic DoAMO , DoRead , DoWrite , DoFlush ;
2022-02-12 04:23:47 +00:00
logic DoAnyUpdateHit , DoAnyHit ;
logic DoAnyMiss ;
2022-02-11 20:54:57 +00:00
logic FlushFlag , FlushWayAndNotAdrFlag ;
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 ,
STATE_FLUSH_CHECK ,
STATE_FLUSH_INCR ,
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-02-10 01:20:10 +00:00
logic IgnoreRequest ;
2022-08-21 20:28:29 +00:00
assign IgnoreRequest = IgnoreRequestTLB | TrapM ;
2022-01-05 05:52:42 +00:00
2022-02-10 01:20:10 +00:00
// if the command is used in the READY state then the cache needs to be able to supress
2022-08-19 23:07:44 +00:00
// using both IgnoreRequestTLB and DCacheTrapM. Otherwise we can just use IgnoreRequestTLB.
2022-02-10 01:20:10 +00:00
2022-08-21 20:28:29 +00:00
assign DoFlush = FlushCache & ~ TrapM ; // do NOT suppress flush on DTLBMissM. Does not depend on address translation.
2022-03-08 22:34:02 +00:00
assign AMO = CacheAtomic [ 1 ] & ( & CacheRW ) ;
2022-02-10 01:21:35 +00:00
assign DoAMO = AMO & ~ IgnoreRequest ;
2022-03-08 22:34:02 +00:00
assign DoRead = CacheRW [ 1 ] & ~ IgnoreRequest ;
assign DoWrite = CacheRW [ 0 ] & ~ IgnoreRequest ;
2022-02-07 19:29:19 +00:00
2022-07-23 03:42:39 +00:00
assign DoAnyMiss = ( DoAMO | DoRead | DoWrite ) & ~ CacheHit & ~ InvalidateCache ;
2022-02-12 04:23:47 +00:00
assign DoAnyUpdateHit = ( DoAMO | DoWrite ) & CacheHit ;
assign DoAnyHit = DoAnyUpdateHit | ( DoRead & 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-02-07 16:33:50 +00:00
assign CacheAccess = ( DoAMO | DoRead | DoWrite ) & CurrState = = STATE_READY ;
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 )
if ( reset ) CurrState < = # 1 STATE_READY ;
else CurrState < = # 1 NextState ;
always_comb begin
NextState = STATE_READY ;
case ( CurrState )
2022-07-24 05:34:11 +00:00
STATE_READY: if ( IgnoreRequest | InvalidateCache ) NextState = STATE_READY ;
else if ( DoFlush ) NextState = STATE_FLUSH ;
// Delayed LRU update. Cannot check if victim line is dirty on this cycle.
// To optimize do the fetch first, then eviction if necessary.
else if ( DoAnyMiss ) NextState = STATE_MISS_FETCH_WDV ;
else NextState = STATE_READY ;
STATE_MISS_FETCH_WDV: if ( CacheBusAck & ~ VictimDirty ) NextState = STATE_MISS_WRITE_CACHE_LINE ;
2022-07-24 06:20:29 +00:00
else if ( CacheBusAck & VictimDirty ) NextState = STATE_MISS_EVICT_DIRTY ;
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-08-21 20:59:54 +00:00
STATE_MISS_WRITE_CACHE_LINE: if ( ~ ( AMO | CacheRW [ 0 ] ) ) NextState = STATE_MISS_READ_DELAY ;
2022-08-21 20:28:29 +00:00
else NextState = STATE_READY ;
2022-08-21 20:59:54 +00:00
STATE_MISS_READ_DELAY: if ( CPUBusy ) NextState = STATE_MISS_READ_DELAY ;
else NextState = STATE_READY ;
2022-07-24 05:34:11 +00:00
STATE_MISS_EVICT_DIRTY: if ( CacheBusAck ) NextState = STATE_MISS_WRITE_CACHE_LINE ;
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-07-24 05:34:11 +00:00
STATE_FLUSH: NextState = STATE_FLUSH_CHECK ;
STATE_FLUSH_CHECK: if ( VictimDirty ) NextState = STATE_FLUSH_WRITE_BACK ;
else if ( FlushFlag ) NextState = STATE_READY ;
else if ( FlushWayFlag ) NextState = STATE_FLUSH_INCR ;
else NextState = STATE_FLUSH_CHECK ;
STATE_FLUSH_INCR: NextState = STATE_FLUSH_CHECK ;
2022-07-24 05:22:43 +00:00
STATE_FLUSH_WRITE_BACK: if ( CacheBusAck ) begin
2022-07-24 05:34:11 +00:00
if ( FlushFlag ) NextState = STATE_READY ;
else if ( FlushWayFlag ) NextState = STATE_FLUSH_INCR ;
else NextState = STATE_FLUSH_CHECK ;
end else NextState = STATE_FLUSH_WRITE_BACK ;
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-02-11 20:54:57 +00:00
assign CacheStall = ( CurrState = = STATE_READY & ( DoFlush | DoAnyMiss ) ) |
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-07-19 04:37:18 +00:00
( CurrState = = STATE_MISS_WRITE_CACHE_LINE & ~ ( AMO | CacheRW [ 0 ] ) ) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
2022-02-07 03:39:38 +00:00
( CurrState = = STATE_FLUSH ) |
2022-02-07 19:29:19 +00:00
( CurrState = = STATE_FLUSH_CHECK & ~ ( FlushFlag ) ) |
2022-02-07 03:39:38 +00:00
( CurrState = = STATE_FLUSH_INCR ) |
2022-07-24 05:22:43 +00:00
( 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 & DoAnyUpdateHit ) |
2022-07-19 04:37:18 +00:00
( CurrState = = STATE_MISS_WRITE_CACHE_LINE & ( AMO | CacheRW [ 0 ] ) ) ;
2022-02-12 04:41:36 +00:00
assign ClearValid = '0 ;
2022-07-19 04:37:18 +00:00
assign ClearDirty = ( CurrState = = STATE_MISS_WRITE_CACHE_LINE & ~ ( AMO | CacheRW [ 0 ] ) ) |
2022-07-24 05:22:43 +00:00
( CurrState = = STATE_FLUSH_WRITE_BACK & CacheBusAck ) ;
2022-02-11 20:54:57 +00:00
assign LRUWriteEn = ( CurrState = = STATE_READY & DoAnyHit ) |
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-07-24 06:20:29 +00:00
assign SelEvict = ( CurrState = = STATE_MISS_EVICT_DIRTY ) |
( CurrState = = STATE_MISS_FETCH_WDV & CacheBusAck & VictimDirty ) ;
2022-02-07 16:43:58 +00:00
assign SelFlush = ( CurrState = = STATE_FLUSH ) | ( CurrState = = STATE_FLUSH_CHECK ) |
2022-07-24 05:22:43 +00:00
( CurrState = = STATE_FLUSH_INCR ) | ( CurrState = = STATE_FLUSH_WRITE_BACK ) ;
2022-02-11 20:54:57 +00:00
assign FlushWayAndNotAdrFlag = FlushWayFlag & ~ FlushAdrFlag ;
assign FlushAdrCntEn = ( CurrState = = STATE_FLUSH_CHECK & ~ VictimDirty & FlushWayAndNotAdrFlag ) |
2022-07-24 05:22:43 +00:00
( CurrState = = STATE_FLUSH_WRITE_BACK & FlushWayAndNotAdrFlag & CacheBusAck ) ;
2022-02-07 19:29:19 +00:00
assign FlushWayCntEn = ( CurrState = = STATE_FLUSH_CHECK & ~ VictimDirty & ~ ( FlushFlag ) ) |
2022-07-24 05:22:43 +00:00
( CurrState = = STATE_FLUSH_WRITE_BACK & ~ FlushFlag & CacheBusAck ) ;
2022-02-11 20:00:01 +00:00
assign FlushAdrCntRst = ( CurrState = = STATE_READY ) ;
assign FlushWayCntRst = ( CurrState = = STATE_READY ) | ( CurrState = = STATE_FLUSH_INCR ) ;
2022-02-08 23:52:09 +00:00
// Bus interface controls
2022-07-20 03:42:25 +00:00
assign CacheFetchLine = ( CurrState = = STATE_READY & DoAnyMiss ) ;
2022-07-24 06:20:29 +00:00
assign CacheWriteLine = ( CurrState = = STATE_MISS_FETCH_WDV & CacheBusAck & VictimDirty ) |
2022-02-07 17:16:20 +00:00
( CurrState = = STATE_FLUSH_CHECK & VictimDirty ) ;
2022-02-07 19:19:37 +00:00
// **** can this be simplified?
2022-08-21 20:28:29 +00:00
assign SelAdr = ( CurrState = = STATE_READY & ( IgnoreRequestTLB & ~ TrapM ) ) | // Ignore Request is needed on TLB miss.
2022-08-19 23:07:44 +00:00
// use the raw requests as we don't want DCacheTrapM in the critical path
2022-03-08 22:34:02 +00:00
( CurrState = = STATE_READY & ( ( AMO | CacheRW [ 0 ] ) & CacheHit ) ) | // changes if store delay hazard removed
2022-07-19 04:37:18 +00:00
( CurrState = = STATE_READY & ( DoAnyMiss ) ) |
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-08-21 20:28:29 +00:00
assign SelBusBuffer = CurrState = = STATE_MISS_WRITE_CACHE_LINE | CurrState = = STATE_MISS_READ_DELAY ;
2022-07-23 03:42:39 +00:00
assign SRAMEnable = ( CurrState = = STATE_READY & ~ CPUBusy | CacheStall ) | ( CurrState ! = STATE_READY ) | reset ;
2022-02-07 16:43:58 +00:00
2022-01-05 05:52:42 +00:00
endmodule // cachefsm