2022-01-05 05:52:42 +00:00
///////////////////////////////////////////
2023-04-14 04:01:57 +00:00
// cachefsm.sv
2022-01-05 05:52:42 +00:00
//
2023-01-20 19:05:10 +00:00
// Written: Ross Thompson ross1728@gmail.com
// Created: 25 August 2021
// Modified: 20 January 2023
2022-01-05 05:52:42 +00:00
//
2023-04-14 04:01:57 +00:00
// Purpose: Controller for the cache fsm
2022-01-05 05:52:42 +00:00
//
2023-01-20 21:01:54 +00:00
// Documentation: RISC-V System on Chip Design Chapter 7 (Figure 7.14 and Table 7.1)
2023-01-20 19:05:10 +00:00
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2022-01-05 05:52:42 +00:00
//
2023-01-10 19:35:20 +00:00
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
2022-01-07 12:58:40 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
2022-01-05 05:52:42 +00:00
2023-08-15 23:17:15 +00:00
module cachefsm import cvw : : * ; # ( parameter cvw_t P ,
parameter READ_ONLY_CACHE = 0 ) (
2023-01-15 03:43:29 +00:00
input logic clk ,
input logic reset ,
2023-01-20 18:49:55 +00:00
// hazard and privilege unit
input logic Stall , // Stall the cache, preventing new accesses. In-flight access finished but does not return to READY
input logic FlushStage , // Pipeline flush of second stage (prevent writes and bus operations)
output logic CacheCommitted , // Cache has started bus operation that shouldn't be interrupted
output logic CacheStall , // Cache stalls pipeline during multicycle operation
2023-01-15 03:43:29 +00:00
// inputs from IEU
2023-01-20 18:49:55 +00:00
input logic [ 1 : 0 ] CacheRW , // [1] Read, [0] Write
input logic [ 1 : 0 ] CacheAtomic , // Atomic operation
input logic FlushCache , // Flush all dirty lines back to memory
input logic InvalidateCache , // Clear all valid bits
2023-08-14 20:43:12 +00:00
input logic [ 3 : 0 ] CMOp , // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
2023-01-20 18:49:55 +00:00
// Bus controls
input logic CacheBusAck , // Bus operation completed
output logic [ 1 : 0 ] CacheBusRW , // [1] Read (cache line fetch) or [0] write bus (cache line writeback)
// performance counter outputs
output logic CacheMiss , // Cache miss
2023-04-13 23:54:15 +00:00
output logic CacheAccess , // Cache access
2022-01-05 05:52:42 +00:00
2023-01-20 19:05:10 +00:00
// cache internals
input logic CacheHit , // Exactly 1 way hits
input logic LineDirty , // The selected line and way is dirty
input logic FlushAdrFlag , // On last set of a cache flush
input logic FlushWayFlag , // On the last way for any set of a cache flush
output logic SelAdr , // [0] SRAM reads from NextAdr, [1] SRAM reads from PAdr
2023-04-13 23:54:15 +00:00
output logic SetValid , // Set the valid bit in the selected way and set
2023-08-14 20:43:12 +00:00
output logic ClearValid , // Clear the valid bit in the selected way and set
2023-01-20 19:05:10 +00:00
output logic SetDirty , // Set the dirty bit in the selected way and set
2023-08-14 20:43:12 +00:00
output logic ClearDirty , // Clear the dirty bit in the selected way and set
2023-08-17 17:46:40 +00:00
output logic ZeroCacheLine , // Write zeros to all bytes of cacheline
2023-08-24 21:47:35 +00:00
output logic CMOZeroHit , // CMOZ hit
2023-01-20 19:05:10 +00:00
output logic SelWriteback , // Overrides cached tag check to select a specific way and set for writeback
2023-08-18 19:48:21 +00:00
output logic SelCMOWriteback , // Overrides cached tag check to select a specific way and set for writeback for both data and tag
2023-01-20 19:05:10 +00:00
output logic LRUWriteEn , // Update the LRU state
output logic SelFlush , // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
2023-11-20 17:28:03 +00:00
output logic SelWay , // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
2023-01-20 19:05:10 +00:00
output logic FlushAdrCntEn , // Enable the counter for Flush Adr
output logic FlushWayCntEn , // Enable the way counter during a flush
output logic FlushCntRst , // Reset both flush counters
output logic SelFetchBuffer , // Bypass the SRAM for a load hit by directly using the read data from the ahbcacheinterface's FetchBuffer
output logic CacheEn // Enable the cache memory arrays. Disable hold read data constant
2023-01-15 03:43:29 +00:00
) ;
2022-01-05 05:52:42 +00:00
2023-03-24 20:15:38 +00:00
logic resetDelay ;
logic AnyUpdateHit , AnyHit ;
logic AnyMiss ;
logic FlushFlag ;
2023-08-24 21:47:35 +00:00
logic CMOWritebackHit ;
logic CMOZeroNoEviction ;
logic CMOZeroEviction ;
2023-01-15 03:43:29 +00:00
typedef enum logic [ 3 : 0 ] { STATE_READY , // hit states
2023-03-24 20:15:38 +00:00
// miss states
STATE_FETCH ,
STATE_WRITEBACK ,
STATE_WRITE_LINE ,
STATE_READ_HOLD , // required for back to back reads. structural hazard on writting SRAM
// flush cache
STATE_FLUSH ,
2023-08-18 19:48:21 +00:00
STATE_FLUSH_WRITEBACK ,
// CMO states
STATE_CMO_WRITEBACK ,
STATE_CMO_DONE
} statetype ;
2022-01-05 05:52:42 +00:00
2023-01-21 00:47:36 +00:00
statetype CurrState , NextState ;
2022-01-05 05:52:42 +00:00
2023-07-31 19:12:53 +00:00
assign AnyMiss = ( CacheRW [ 0 ] | CacheRW [ 1 ] ) & ~ CacheHit & ~ InvalidateCache ; // exclusion-tag: cache AnyMiss
2023-08-24 21:47:35 +00:00
assign AnyUpdateHit = ( CacheRW [ 0 ] ) & CacheHit ; // exclusion-tag: icache storeAMO1
2023-04-12 22:57:45 +00:00
assign AnyHit = AnyUpdateHit | ( CacheRW [ 1 ] & CacheHit ) ; // exclusion-tag: icache AnyUpdateHit
2023-08-24 21:47:35 +00:00
assign CMOWritebackHit = ( CMOp [ 1 ] | CMOp [ 2 ] ) & CacheHit ;
assign CMOZeroNoEviction = CMOp [ 3 ] & ~ LineDirty ; // (hit or miss) with no writeback store zeros now
assign CMOZeroEviction = CMOp [ 3 ] & LineDirty ; // (hit or miss) with writeback dirty line
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.
2023-08-31 07:27:47 +00:00
assign CacheAccess = ( | CacheRW ) & ( ( CurrState = = STATE_READY & ~ Stall & ~ FlushStage ) | ( CurrState = = STATE_READ_HOLD & ~ Stall & ~ FlushStage ) ) ; // exclusion-tag: icache CacheW
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 ;
2023-04-12 22:57:45 +00:00
case ( CurrState ) // exclusion-tag: icache state-case
2023-04-19 08:28:45 +00:00
STATE_READY: if ( InvalidateCache ) NextState = STATE_READY ; // exclusion-tag: dcache InvalidateCheck
2023-03-24 20:15:38 +00:00
else if ( FlushCache & ~ READ_ONLY_CACHE ) NextState = STATE_FLUSH ;
2023-04-12 22:57:45 +00:00
else if ( AnyMiss & ( READ_ONLY_CACHE | ~ LineDirty ) ) NextState = STATE_FETCH ; // exclusion-tag: icache FETCHStatement
2023-08-24 21:47:35 +00:00
else if ( AnyMiss | CMOZeroEviction ) NextState = STATE_WRITEBACK ; // exclusion-tag: icache WRITEBACKStatement
else if ( CMOWritebackHit ) NextState = STATE_CMO_WRITEBACK ;
2023-03-24 20:15:38 +00:00
else NextState = STATE_READY ;
2023-08-18 19:48:21 +00:00
STATE_FETCH: if ( CacheBusAck ) NextState = STATE_WRITE_LINE ;
else if ( CacheBusAck ) NextState = STATE_READY ;
2023-03-24 20:15:38 +00:00
else NextState = STATE_FETCH ;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD ;
STATE_READ_HOLD: if ( Stall ) NextState = STATE_READ_HOLD ;
else NextState = STATE_READY ;
2023-04-12 22:57:45 +00:00
// exclusion-tag-start: icache case
2023-08-24 21:47:35 +00:00
STATE_WRITEBACK: if ( CacheBusAck & ~ CMOp [ 3 ] ) NextState = STATE_FETCH ;
else if ( CacheBusAck ) NextState = STATE_CMO_DONE ;
2023-03-24 20:15:38 +00:00
else NextState = STATE_WRITEBACK ;
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.
2023-03-24 20:15:38 +00:00
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 ;
2023-08-18 19:48:21 +00:00
STATE_CMO_WRITEBACK: if ( CacheBusAck & ( CMOp [ 1 ] | CMOp [ 2 ] ) ) NextState = STATE_CMO_DONE ;
else NextState = STATE_CMO_WRITEBACK ;
2023-08-24 21:47:35 +00:00
STATE_CMO_DONE: if ( Stall ) NextState = STATE_CMO_DONE ;
else NextState = STATE_READY ;
2023-04-12 22:57:45 +00:00
// exclusion-tag-end: icache case
2023-03-24 20:15:38 +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
2023-08-18 19:48:21 +00:00
assign CacheCommitted = ( CurrState ! = STATE_READY ) & ~ ( READ_ONLY_CACHE & ( CurrState = = STATE_READ_HOLD | CurrState = = STATE_CMO_DONE ) ) ;
2023-08-24 21:47:35 +00:00
assign CacheStall = ( CurrState = = STATE_READY & ( FlushCache | AnyMiss | CMOWritebackHit | CMOZeroEviction ) ) | // exclusion-tag: icache StallStates
2022-12-21 22:49:53 +00:00
( CurrState = = STATE_FETCH ) |
( CurrState = = STATE_WRITEBACK ) |
2023-01-20 15:41:18 +00:00
( 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.
2022-12-17 01:28:32 +00:00
( CurrState = = STATE_FLUSH ) |
2023-08-18 19:48:21 +00:00
( CurrState = = STATE_FLUSH_WRITEBACK ) |
( CurrState = = STATE_CMO_WRITEBACK ) ;
2022-02-08 23:52:09 +00:00
// write enables internal to cache
2023-08-24 21:47:35 +00:00
assign CMOZeroHit = CurrState = = STATE_READY & CMOp [ 3 ] & CacheHit ;
2023-08-18 19:48:21 +00:00
assign SetValid = CurrState = = STATE_WRITE_LINE |
2023-11-20 17:28:03 +00:00
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_READY & CMOZeroNoEviction ) |
2023-08-24 21:47:35 +00:00
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_WRITEBACK & CacheBusAck & CMOp [ 3 ] ) ;
2023-08-21 22:51:51 +00:00
assign ClearValid = P . ZICBOM_SUPPORTED & ( ( CurrState = = STATE_READY & CMOp [ 0 ] & CacheHit ) |
2023-08-18 21:32:22 +00:00
( CurrState = = STATE_CMO_WRITEBACK & CMOp [ 2 ] & CacheBusAck ) ) ;
2023-04-12 20:32:36 +00:00
// coverage off -item e 1 -fecexprrow 8
2023-09-05 19:07:58 +00:00
assign LRUWriteEn = ( ( ( CurrState = = STATE_READY & ( AnyHit | CMOZeroNoEviction ) ) |
( CurrState = = STATE_WRITE_LINE ) ) & ~ FlushStage ) |
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_WRITEBACK & CMOp [ 3 ] & CacheBusAck ) ;
2023-04-12 22:57:45 +00:00
// exclusion-tag-start: icache flushdirtycontrols
2023-08-24 21:47:35 +00:00
assign SetDirty = ( CurrState = = STATE_READY & ( AnyUpdateHit | CMOZeroNoEviction ) ) | // exclusion-tag: icache SetDirty
( CurrState = = STATE_WRITE_LINE & ( CacheRW [ 0 ] ) ) |
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_WRITEBACK & ( CMOp [ 3 ] & CacheBusAck ) ) ;
2023-07-31 19:12:53 +00:00
assign ClearDirty = ( CurrState = = STATE_WRITE_LINE & ~ ( CacheRW [ 0 ] ) ) | // exclusion-tag: icache ClearDirty
2023-08-14 20:43:12 +00:00
( 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.
2022-02-08 23:52:09 +00:00
// Flush and eviction controls
2023-08-18 21:32:22 +00:00
( P . ZICBOM_SUPPORTED & CurrState = = STATE_CMO_WRITEBACK & ( CMOp [ 1 ] | CMOp [ 2 ] ) & CacheBusAck ) ;
2023-11-20 17:28:03 +00:00
assign SelWay = SelWriteback | ( CurrState = = STATE_WRITE_LINE ) |
// This is almost the same as setvalid, but on cachehit we don't want to select
// the nonhit way, but instead want to force this to zero
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_READY & CMOZeroNoEviction & ~ CacheHit ) |
( P . ZICBOZ_SUPPORTED & CurrState = = STATE_WRITEBACK & CacheBusAck & CMOp [ 3 ] ) ;
2023-08-24 21:47:35 +00:00
assign ZeroCacheLine = P . ZICBOZ_SUPPORTED & ( ( CurrState = = STATE_READY & CMOZeroNoEviction ) |
( CurrState = = STATE_WRITEBACK & ( CMOp [ 3 ] & CacheBusAck ) ) ) ;
2022-12-21 22:49:53 +00:00
assign SelWriteback = ( CurrState = = STATE_WRITEBACK & ~ CacheBusAck ) |
2022-12-04 22:09:09 +00:00
( CurrState = = STATE_READY & AnyMiss & LineDirty ) ;
2023-08-18 19:48:21 +00:00
assign SelCMOWriteback = CurrState = = STATE_CMO_WRITEBACK ;
2022-12-16 22:22:40 +00:00
assign SelFlush = ( CurrState = = STATE_READY & FlushCache ) |
2023-03-24 20:15:38 +00:00
( CurrState = = STATE_FLUSH ) |
( CurrState = = STATE_FLUSH_WRITEBACK ) ;
2023-04-22 17:07:48 +00:00
// coverage off -item e 1 -fecexprrow 1
2023-04-19 08:28:45 +00:00
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
2022-12-21 22:49:53 +00:00
assign FlushAdrCntEn = ( CurrState = = STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck ) |
2023-03-24 20:15:38 +00:00
( CurrState = = STATE_FLUSH & FlushWayFlag & ~ LineDirty ) ;
2022-12-16 21:28:22 +00:00
assign FlushWayCntEn = ( CurrState = = STATE_FLUSH & ~ LineDirty ) |
2023-03-24 20:15:38 +00:00
( CurrState = = STATE_FLUSH_WRITEBACK & CacheBusAck ) ;
2022-12-16 22:32:21 +00:00
assign FlushCntRst = ( CurrState = = STATE_FLUSH & FlushFlag & ~ LineDirty ) |
2023-03-24 20:15:38 +00:00
( CurrState = = STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck ) ;
2023-04-12 22:57:45 +00:00
// exclusion-tag-end: icache flushdirtycontrols
2022-02-08 23:52:09 +00:00
// Bus interface controls
2023-04-12 22:57:45 +00:00
assign CacheBusRW [ 1 ] = ( CurrState = = STATE_READY & AnyMiss & ~ LineDirty ) | // exclusion-tag: icache CacheBusRCauses
2022-12-21 22:49:53 +00:00
( CurrState = = STATE_FETCH & ~ CacheBusAck ) |
2023-08-24 21:47:35 +00:00
( CurrState = = STATE_WRITEBACK & CacheBusAck & ~ CMOp [ 3 ] ) ;
2023-04-12 22:57:45 +00:00
assign CacheBusRW [ 0 ] = ( CurrState = = STATE_READY & AnyMiss & LineDirty ) | // exclusion-tag: icache CacheBusW
2023-08-18 19:48:21 +00:00
( CurrState = = STATE_WRITEBACK & ~ CacheBusAck ) |
( CurrState = = STATE_FLUSH_WRITEBACK & ~ CacheBusAck ) |
( P . ZICBOM_SUPPORTED & CurrState = = STATE_CMO_WRITEBACK & ( CMOp [ 1 ] | CMOp [ 2 ] ) & ~ CacheBusAck ) ;
2023-01-20 18:49:55 +00:00
2023-08-17 21:57:54 +00:00
assign SelAdr = ( CurrState = = STATE_READY & ( CacheRW [ 0 ] | AnyMiss | ( | CMOp ) ) ) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
2022-12-21 22:49:53 +00:00
( CurrState = = STATE_FETCH ) |
( CurrState = = STATE_WRITEBACK ) |
( CurrState = = STATE_WRITE_LINE ) |
2023-08-18 19:48:21 +00:00
( CurrState = = STATE_CMO_WRITEBACK ) |
2022-02-12 04:41:36 +00:00
resetDelay ;
2022-12-21 22:49:53 +00:00
assign SelFetchBuffer = CurrState = = STATE_WRITE_LINE | CurrState = = STATE_READ_HOLD ;
2023-04-19 08:28:45 +00:00
assign CacheEn = ( ~ Stall | FlushCache | AnyMiss ) | ( CurrState ! = STATE_READY ) | reset | InvalidateCache ; // exclusion-tag: dcache CacheEn
2022-02-07 16:43:58 +00:00
2022-01-05 05:52:42 +00:00
endmodule // cachefsm