2022-01-05 05:40:37 +00:00
///////////////////////////////////////////
// cache (data cache)
//
// Written: ross1728@gmail.com July 07, 2021
// Implements the L1 data cache
//
// Purpose: Storage for data and meta data.
//
// 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:40:37 +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:40:37 +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:40:37 +00:00
`include " wally-config.vh "
2022-03-11 18:44:04 +00:00
module cache # ( parameter LINELEN , NUMLINES , NUMWAYS , LOGWPL , WORDLEN , MUXINTERVAL , DCACHE ) (
2022-02-05 02:42:53 +00:00
input logic clk ,
input logic reset ,
2022-01-05 05:40:37 +00:00
// cpu side
2022-02-05 02:42:53 +00:00
input logic CPUBusy ,
input logic [ 1 : 0 ] RW ,
input logic [ 1 : 0 ] Atomic ,
input logic FlushCache ,
input logic InvalidateCacheM ,
input logic [ 11 : 0 ] NextAdr , // virtual address, but we only use the lower 12 bits.
input logic [ `PA_BITS - 1 : 0 ] PAdr , // physical address
2022-03-11 00:44:50 +00:00
input logic [ ( `XLEN - 1 ) / 8 : 0 ] ByteMask ,
2022-07-08 23:56:57 +00:00
input logic [ WORDLEN - 1 : 0 ] FinalWriteData ,
2022-07-09 00:26:45 +00:00
input logic FStore2 ,
2022-02-05 02:42:53 +00:00
output logic CacheCommitted ,
output logic CacheStall ,
2022-01-06 04:37:53 +00:00
// to performance counters to cpu
2022-02-05 02:42:53 +00:00
output logic CacheMiss ,
output logic CacheAccess ,
2022-01-06 04:37:53 +00:00
// lsu control
2022-02-10 01:20:10 +00:00
input logic IgnoreRequestTLB ,
2022-03-10 21:48:31 +00:00
input logic IgnoreRequestTrapM ,
2022-04-12 22:56:23 +00:00
input logic TrapM ,
2022-03-08 22:34:02 +00:00
input logic Cacheable ,
2022-01-06 04:37:53 +00:00
// Bus fsm interface
2022-02-05 02:42:53 +00:00
output logic CacheFetchLine ,
output logic CacheWriteLine ,
input logic CacheBusAck ,
2022-03-11 17:03:36 +00:00
input logic [ LOGWPL - 1 : 0 ] WordCount ,
input logic LSUBusWriteCrit ,
2022-02-05 02:42:53 +00:00
output logic [ `PA_BITS - 1 : 0 ] CacheBusAdr ,
2022-02-13 21:06:18 +00:00
input logic [ LINELEN - 1 : 0 ] CacheBusWriteData ,
2022-03-11 17:03:36 +00:00
output logic [ WORDLEN - 1 : 0 ] ReadDataWord ) ;
2022-01-05 05:40:37 +00:00
2022-02-03 15:36:11 +00:00
// Cache parameters
2022-02-10 01:29:15 +00:00
localparam LINEBYTELEN = LINELEN / 8 ;
localparam OFFSETLEN = $clog2 ( LINEBYTELEN ) ;
localparam SETLEN = $clog2 ( NUMLINES ) ;
localparam SETTOP = SETLEN + OFFSETLEN ;
localparam TAGLEN = `PA_BITS - SETTOP ;
2022-07-08 23:56:57 +00:00
localparam WORDSPERLINE = LINELEN / WORDLEN ;
2022-02-10 01:29:15 +00:00
localparam FlushAdrThreshold = NUMLINES - 1 ;
2022-01-05 05:40:37 +00:00
2022-02-12 04:41:36 +00:00
logic SelAdr ;
2022-02-10 01:29:15 +00:00
logic [ SETLEN - 1 : 0 ] RAdr ;
2022-02-10 16:43:37 +00:00
logic [ LINELEN - 1 : 0 ] CacheWriteData ;
2022-02-12 04:27:27 +00:00
logic ClearValid ;
logic ClearDirty ;
2022-02-10 01:29:15 +00:00
logic [ LINELEN - 1 : 0 ] ReadDataLineWay [ NUMWAYS - 1 : 0 ] ;
2022-02-13 21:47:27 +00:00
logic [ NUMWAYS - 1 : 0 ] HitWay , HitWaySaved , HitWayFinal ;
2022-02-10 01:29:15 +00:00
logic CacheHit ;
2022-02-13 21:06:18 +00:00
logic SetDirty ;
logic SetValid ;
2022-02-10 01:29:15 +00:00
logic [ NUMWAYS - 1 : 0 ] VictimWay ;
logic [ NUMWAYS - 1 : 0 ] VictimDirtyWay ;
logic VictimDirty ;
logic [ TAGLEN - 1 : 0 ] VictimTagWay [ NUMWAYS - 1 : 0 ] ;
logic [ TAGLEN - 1 : 0 ] VictimTag ;
logic [ SETLEN - 1 : 0 ] FlushAdr ;
logic [ SETLEN - 1 : 0 ] FlushAdrP1 ;
logic FlushAdrCntEn ;
logic FlushAdrCntRst ;
logic FlushAdrFlag ;
logic FlushWayFlag ;
logic [ NUMWAYS - 1 : 0 ] FlushWay ;
logic [ NUMWAYS - 1 : 0 ] NextFlushWay ;
logic FlushWayCntEn ;
logic FlushWayCntRst ;
logic SelEvict ;
logic LRUWriteEn ;
logic SelFlush ;
logic ResetOrFlushAdr , ResetOrFlushWay ;
logic [ NUMWAYS - 1 : 0 ] SelectedWay ;
logic [ NUMWAYS - 1 : 0 ] SetValidWay , ClearValidWay , SetDirtyWay , ClearDirtyWay ;
2022-03-08 22:34:02 +00:00
logic [ 1 : 0 ] CacheRW , CacheAtomic ;
2022-07-19 04:37:18 +00:00
logic [ LINELEN - 1 : 0 ] ReadDataLine , ReadDataLineCache ;
2022-03-11 18:44:04 +00:00
logic [ $clog2 ( LINELEN / 8 ) - $clog2 ( MUXINTERVAL / 8 ) - 1 : 0 ] WordOffsetAddr ;
2022-03-11 17:03:36 +00:00
logic save , restore ;
2022-07-19 04:37:18 +00:00
logic SelBusBuffer ;
localparam LOGXLENBYTES = $clog2 ( `XLEN / 8 ) ;
logic [ 2 * * LOGWPL - 1 : 0 ] MemPAdrDecoded ;
logic [ LINELEN / 8 - 1 : 0 ] LineByteMask , DemuxedByteMask , LineByteMux ;
genvar index ;
2022-02-04 19:31:32 +00:00
2022-02-03 15:36:11 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// Read Path
/////////////////////////////////////////////////////////////////////////////////////////////
// Choose read address (RAdr). Normally use NextAdr, but use PAdr during stalls
// and FlushAdr when handling D$ flushes
mux3 # ( SETLEN ) AdrSelMux (
. d0 ( NextAdr [ SETTOP - 1 : OFFSETLEN ] ) , . d1 ( PAdr [ SETTOP - 1 : OFFSETLEN ] ) , . d2 ( FlushAdr ) ,
2022-02-12 05:10:58 +00:00
. s ( { SelFlush , SelAdr } ) , . y ( RAdr ) ) ;
2022-02-03 15:36:11 +00:00
// Array of cache ways, along with victim, hit, dirty, and read merging logic
2022-05-03 10:53:20 +00:00
cacheway # ( NUMLINES , LINELEN , TAGLEN , OFFSETLEN , SETLEN )
2022-07-19 04:37:18 +00:00
CacheWays [ NUMWAYS - 1 : 0 ] ( . clk , . reset , . RAdr , . PAdr , . CacheWriteData , . LineByteMask , . FStore2 ,
2022-02-10 17:40:10 +00:00
. SetValidWay , . ClearValidWay , . SetDirtyWay , . ClearDirtyWay , . SelEvict , . VictimWay ,
2022-02-13 21:47:27 +00:00
. FlushWay , . SelFlush , . ReadDataLineWay , . HitWay , . VictimDirtyWay , . VictimTagWay ,
. Invalidate ( InvalidateCacheM ) ) ;
2022-01-05 16:01:03 +00:00
if ( NUMWAYS > 1 ) begin : vict
2022-02-03 15:36:11 +00:00
cachereplacementpolicy # ( NUMWAYS , SETLEN , OFFSETLEN , NUMLINES ) cachereplacementpolicy (
2022-02-14 18:40:51 +00:00
. clk , . reset , . HitWay ( HitWayFinal ) , . VictimWay , . RAdr , . LRUWriteEn ) ;
2022-02-03 15:36:11 +00:00
end else assign VictimWay = 1 'b1 ; // one hot.
2022-02-13 21:47:27 +00:00
assign CacheHit = | HitWay ;
2022-01-05 05:40:37 +00:00
assign VictimDirty = | VictimDirtyWay ;
2022-02-03 16:52:22 +00:00
// ReadDataLineWay is a 2d array of cache line len by number of ways.
2022-01-05 05:40:37 +00:00
// Need to OR together each way in a bitwise manner.
// Final part of the AO Mux. First is the AND in the cacheway.
2022-07-19 04:37:18 +00:00
or_rows # ( NUMWAYS , LINELEN ) ReadDataAOMux ( . a ( ReadDataLineWay ) , . y ( ReadDataLineCache ) ) ;
2022-02-04 20:18:10 +00:00
or_rows # ( NUMWAYS , TAGLEN ) VictimTagAOMux ( . a ( VictimTagWay ) , . y ( VictimTag ) ) ;
2022-01-05 05:40:37 +00:00
2022-02-04 20:18:10 +00:00
// Because of the sram clocked read when the ieu is stalled the read data maybe lost.
// There are two ways to resolve. 1. We can replay the read of the sram or we can save
// the data. Replay is eaiser but creates a longer critical path.
// save/restore only wayhit and readdata.
2022-02-05 05:19:00 +00:00
if ( ! `REPLAY ) begin
2022-02-13 21:47:27 +00:00
flopenr # ( NUMWAYS ) wayhitsavereg ( clk , save , reset , HitWay , HitWaySaved ) ;
mux2 # ( NUMWAYS ) saverestoremux ( HitWay , HitWaySaved , restore , HitWayFinal ) ;
end else assign HitWayFinal = HitWay ;
2022-03-11 17:03:36 +00:00
2022-03-11 18:44:04 +00:00
// like to fix this.
if ( DCACHE )
mux2 # ( LOGWPL ) WordAdrrMux ( . d0 ( PAdr [ $clog2 ( LINELEN / 8 ) - 1 : $clog2 ( MUXINTERVAL / 8 ) ] ) ,
. d1 ( WordCount ) , . s ( LSUBusWriteCrit ) ,
2022-03-11 20:58:21 +00:00
. y ( WordOffsetAddr ) ) ;
2022-03-11 18:44:04 +00:00
else assign WordOffsetAddr = PAdr [ $clog2 ( LINELEN / 8 ) - 1 : $clog2 ( MUXINTERVAL / 8 ) ] ;
2022-07-19 04:37:18 +00:00
mux2 # ( LINELEN ) EarlyReturnBuf ( ReadDataLineCache , CacheBusWriteData , SelBusBuffer , ReadDataLine ) ;
2022-03-11 18:44:04 +00:00
subcachelineread # ( LINELEN , WORDLEN , MUXINTERVAL , LOGWPL ) subcachelineread (
. clk , . reset , . PAdr ( WordOffsetAddr ) , . save , . restore ,
. ReadDataLine , . ReadDataWord ) ;
2022-03-11 17:03:36 +00:00
2022-02-03 15:36:11 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2022-02-08 23:52:09 +00:00
// Write Path: Write data and address. Muxes between writes from bus and writes from CPU.
2022-02-03 15:36:11 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
2022-07-19 04:37:18 +00:00
logic [ LINELEN - 1 : 0 ] FinalWriteDataDup ;
assign FinalWriteDataDup = { WORDSPERLINE { FinalWriteData } } ;
onehotdecoder # ( LOGWPL ) adrdec (
. bin ( PAdr [ LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES ] ) , . decoded ( MemPAdrDecoded ) ) ;
for ( index = 0 ; index < 2 * * LOGWPL ; index + + ) begin
assign DemuxedByteMask [ ( index + 1 ) * ( `XLEN / 8 ) - 1 : index * ( `XLEN / 8 ) ] = MemPAdrDecoded [ index ] ? ByteMask : '0 ;
end
// *** have to add back in fstore2
assign LineByteMux = SetValid & ~ SetDirty ? '1 : ~ DemuxedByteMask ; // If load miss set all muxes to 1.
assign LineByteMask = ~ SetValid & ~ SetDirty ? '0 : ~ SetValid & SetDirty ? DemuxedByteMask : '1 ; // if store hit only enable the word and subword bytes, else write all bytes.
for ( index = 0 ; index < LINELEN / 8 ; index + + ) begin
mux2 # ( 8 ) WriteDataMux ( . d0 ( FinalWriteDataDup [ 8 * index + 7 : 8 * index ] ) ,
. d1 ( CacheBusWriteData [ 8 * index + 7 : 8 * index ] ) , . s ( LineByteMux [ index ] ) , . y ( CacheWriteData [ 8 * index + 7 : 8 * index ] ) ) ;
end
//mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteData}}),
// .d1(CacheBusWriteData), .s(SetValid), .y(CacheWriteData));
2022-07-05 22:36:54 +00:00
mux3 # ( `PA_BITS ) CacheBusAdrMux ( . d0 ( { PAdr [ `PA_BITS - 1 : OFFSETLEN ] , { OFFSETLEN { 1 'b0 } } } ) ,
. d1 ( { VictimTag , PAdr [ SETTOP - 1 : OFFSETLEN ] , { OFFSETLEN { 1 'b0 } } } ) ,
. d2 ( { VictimTag , FlushAdr , { OFFSETLEN { 1 'b0 } } } ) ,
2022-02-12 05:10:58 +00:00
. s ( { SelFlush , SelEvict } ) , . y ( CacheBusAdr ) ) ;
2022-02-03 15:36:11 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// Flush address and way generation during flush
/////////////////////////////////////////////////////////////////////////////////////////////
assign ResetOrFlushAdr = reset | FlushAdrCntRst ;
2022-02-12 05:10:58 +00:00
flopenr # ( SETLEN ) FlushAdrReg ( . clk , . reset ( ResetOrFlushAdr ) , . en ( FlushAdrCntEn ) ,
. d ( FlushAdrP1 ) , . q ( FlushAdr ) ) ;
2022-01-05 05:40:37 +00:00
assign FlushAdrP1 = FlushAdr + 1 'b1 ;
2022-02-03 15:36:11 +00:00
assign FlushAdrFlag = ( FlushAdr = = FlushAdrThreshold [ SETLEN - 1 : 0 ] ) ;
assign ResetOrFlushWay = reset | FlushWayCntRst ;
2022-02-12 05:10:58 +00:00
flopenl # ( NUMWAYS ) FlushWayReg ( . clk , . load ( ResetOrFlushWay ) , . en ( FlushWayCntEn ) ,
. val ( { { NUMWAYS - 1 { 1 'b0 } } , 1 'b1 } ) , . d ( NextFlushWay ) , . q ( FlushWay ) ) ;
2022-02-03 15:36:11 +00:00
assign FlushWayFlag = FlushWay [ NUMWAYS - 1 ] ;
2022-07-06 23:34:30 +00:00
if ( NUMWAYS > 1 ) assign NextFlushWay = { FlushWay [ NUMWAYS - 2 : 0 ] , FlushWay [ NUMWAYS - 1 ] } ;
else assign NextFlushWay = FlushWay [ NUMWAYS - 1 ] ;
2022-01-05 05:40:37 +00:00
2022-02-08 23:52:09 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// Write Path: Write Enables
/////////////////////////////////////////////////////////////////////////////////////////////
2022-02-13 21:47:27 +00:00
mux3 # ( NUMWAYS ) selectwaymux ( HitWayFinal , VictimWay , FlushWay ,
2022-02-13 21:06:18 +00:00
{ SelFlush , SetValid } , SelectedWay ) ;
assign SetValidWay = SetValid ? SelectedWay : '0 ;
2022-02-07 23:23:09 +00:00
assign ClearValidWay = ClearValid ? SelectedWay : '0 ;
2022-02-13 21:06:18 +00:00
assign SetDirtyWay = SetDirty ? SelectedWay : '0 ;
2022-02-08 23:52:09 +00:00
assign ClearDirtyWay = ClearDirty ? SelectedWay : '0 ;
2022-02-07 23:23:09 +00:00
2022-02-03 15:36:11 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////
// Cache FSM
/////////////////////////////////////////////////////////////////////////////////////////////
2022-03-08 22:34:02 +00:00
assign CacheRW = Cacheable ? RW : 2 'b00 ;
assign CacheAtomic = Cacheable ? Atomic : 2 'b00 ;
2022-01-05 05:52:42 +00:00
cachefsm cachefsm ( . clk , . reset , . CacheFetchLine , . CacheWriteLine , . CacheBusAck ,
2022-04-12 22:56:23 +00:00
. CacheRW , . CacheAtomic , . CPUBusy , . IgnoreRequestTLB , . IgnoreRequestTrapM , . TrapM ,
2022-02-03 15:36:11 +00:00
. CacheHit , . VictimDirty , . CacheStall , . CacheCommitted ,
2022-02-12 04:23:47 +00:00
. CacheMiss , . CacheAccess , . SelAdr ,
2022-02-13 21:06:18 +00:00
. ClearValid , . ClearDirty , . SetDirty ,
. SetValid , . SelEvict , . SelFlush ,
2022-02-03 15:36:11 +00:00
. FlushAdrCntEn , . FlushWayCntEn , . FlushAdrCntRst ,
2022-07-19 04:37:18 +00:00
. FlushWayCntRst , . FlushAdrFlag , . FlushWayFlag , . FlushCache , . SelBusBuffer ,
2022-02-04 19:31:32 +00:00
. save , . restore ,
2022-02-08 03:59:18 +00:00
. LRUWriteEn ) ;
2022-02-03 15:36:11 +00:00
endmodule