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-08-02 02:06:36 +00:00
|
|
|
module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTERVAL, DCACHE) (
|
2022-08-17 21:09:20 +00:00
|
|
|
input logic clk,
|
|
|
|
input logic reset,
|
2022-01-05 05:40:37 +00:00
|
|
|
// cpu side
|
2022-11-14 20:11:05 +00:00
|
|
|
input logic FlushStage,
|
2022-12-11 21:51:35 +00:00
|
|
|
input logic Stall,
|
2022-11-01 20:23:24 +00:00
|
|
|
input logic [1:0] CacheRW,
|
|
|
|
input logic [1:0] CacheAtomic,
|
2022-08-17 21:09:20 +00:00
|
|
|
input logic FlushCache,
|
|
|
|
input logic InvalidateCache,
|
|
|
|
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-08-02 02:06:36 +00:00
|
|
|
input logic [(WORDLEN-1)/8:0] ByteMask,
|
2022-11-14 03:36:12 +00:00
|
|
|
input logic [WORDLEN-1:0] CacheWriteData,
|
2022-08-17 21:09:20 +00:00
|
|
|
output logic CacheCommitted,
|
|
|
|
output logic CacheStall,
|
2022-01-06 04:37:53 +00:00
|
|
|
// to performance counters to cpu
|
2022-08-17 21:09:20 +00:00
|
|
|
output logic CacheMiss,
|
|
|
|
output logic CacheAccess,
|
2022-01-06 04:37:53 +00:00
|
|
|
// lsu control
|
2022-10-19 20:08:23 +00:00
|
|
|
input logic SelHPTW,
|
2022-01-06 04:37:53 +00:00
|
|
|
// Bus fsm interface
|
2022-09-23 16:46:53 +00:00
|
|
|
output logic [1:0] CacheBusRW,
|
2022-08-17 21:09:20 +00:00
|
|
|
input logic CacheBusAck,
|
2022-11-09 23:52:50 +00:00
|
|
|
input logic SelBusBeat,
|
|
|
|
input logic [LOGBWPL-1:0] BeatCount,
|
2022-08-25 17:44:39 +00:00
|
|
|
input logic [LINELEN-1:0] FetchBuffer,
|
2022-08-17 21:09:20 +00:00
|
|
|
output logic [`PA_BITS-1:0] CacheBusAdr,
|
|
|
|
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-11-29 16:52:40 +00:00
|
|
|
logic [SETLEN-1:0] CAdr;
|
2022-11-14 03:36:12 +00:00
|
|
|
logic [LINELEN-1:0] LineWriteData;
|
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-11-29 20:09:48 +00:00
|
|
|
logic [NUMWAYS-1:0] HitWay, ValidWay;
|
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;
|
2022-12-04 22:09:09 +00:00
|
|
|
logic [NUMWAYS-1:0] DirtyWay;
|
|
|
|
logic LineDirty;
|
2022-12-05 23:19:51 +00:00
|
|
|
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0];
|
|
|
|
logic [TAGLEN-1:0] Tag;
|
2022-02-10 01:29:15 +00:00
|
|
|
logic [SETLEN-1:0] FlushAdr;
|
2022-12-16 21:28:22 +00:00
|
|
|
logic [SETLEN-1:0] OldFlushAdr, NextFlushAdr, RawFlushAdr;
|
2022-02-10 01:29:15 +00:00
|
|
|
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;
|
2022-12-14 15:49:15 +00:00
|
|
|
logic SelWriteback;
|
2022-02-10 01:29:15 +00:00
|
|
|
logic LRUWriteEn;
|
|
|
|
logic SelFlush;
|
|
|
|
logic ResetOrFlushAdr, ResetOrFlushWay;
|
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-12-05 23:51:13 +00:00
|
|
|
logic SelFetchBuffer;
|
2022-12-14 15:49:15 +00:00
|
|
|
logic CacheEn;
|
2022-12-16 21:28:22 +00:00
|
|
|
logic SelOldFlushAdr;
|
|
|
|
|
2022-07-19 04:37:18 +00:00
|
|
|
|
2022-08-02 02:06:36 +00:00
|
|
|
localparam LOGLLENBYTES = $clog2(WORDLEN/8);
|
|
|
|
localparam CACHEWORDSPERLINE = `DCACHE_LINELENINBITS/WORDLEN;
|
|
|
|
localparam LOGCWPL = $clog2(CACHEWORDSPERLINE);
|
|
|
|
logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded;
|
2022-12-04 07:00:04 +00:00
|
|
|
logic [LINELEN/8-1:0] LineByteMask, DemuxedByteMask, FetchBufferByteSel;
|
2022-07-19 04:37:18 +00:00
|
|
|
genvar index;
|
2022-02-04 19:31:32 +00:00
|
|
|
|
2022-02-03 15:36:11 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Read Path
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-11-29 16:52:40 +00:00
|
|
|
// Choose read address (CAdr). Normally use NextAdr, but use PAdr during stalls
|
2022-11-16 18:36:58 +00:00
|
|
|
// and FlushAdr when handling D$ flushes
|
|
|
|
// The icache must update to the newest PCNextF on flush as it is probably a trap. Trap
|
|
|
|
// sets PCNextF to XTVEC and the icache must start reading the instruction.
|
2022-02-03 15:36:11 +00:00
|
|
|
mux3 #(SETLEN) AdrSelMux(
|
|
|
|
.d0(NextAdr[SETTOP-1:OFFSETLEN]), .d1(PAdr[SETTOP-1:OFFSETLEN]), .d2(FlushAdr),
|
2022-11-29 16:52:40 +00:00
|
|
|
.s({SelFlush, ((SelAdr | SelHPTW) & ~((DCACHE == 0) & FlushStage))}), .y(CAdr));
|
2022-02-03 15:36:11 +00:00
|
|
|
|
|
|
|
// Array of cache ways, along with victim, hit, dirty, and read merging logic
|
2022-11-16 18:36:58 +00:00
|
|
|
cacheway #(NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, DCACHE)
|
2022-12-14 15:49:15 +00:00
|
|
|
CacheWays[NUMWAYS-1:0](.clk, .reset, .CacheEn, .CAdr, .PAdr, .LineWriteData, .LineByteMask,
|
|
|
|
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelWriteback, .VictimWay,
|
2022-12-05 23:19:51 +00:00
|
|
|
.FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .TagWay, .FlushStage, .InvalidateCache);
|
2022-01-05 16:01:03 +00:00
|
|
|
if(NUMWAYS > 1) begin:vict
|
2022-11-21 04:35:02 +00:00
|
|
|
cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMLINES) cacheLRU(
|
2022-12-14 15:49:15 +00:00
|
|
|
.clk, .reset, .CacheEn, .FlushStage, .HitWay, .ValidWay, .VictimWay, .CAdr, .LRUWriteEn(LRUWriteEn & ~FlushStage),
|
2022-12-04 18:30:56 +00:00
|
|
|
.SetValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache, .FlushCache);
|
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-12-04 22:09:09 +00:00
|
|
|
assign LineDirty = | DirtyWay;
|
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-12-05 23:19:51 +00:00
|
|
|
or_rows #(NUMWAYS, TAGLEN) TagAOMux(.a(TagWay), .y(Tag));
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-03-11 18:44:04 +00:00
|
|
|
// like to fix this.
|
|
|
|
if(DCACHE)
|
2022-08-02 02:06:36 +00:00
|
|
|
mux2 #(LOGBWPL) WordAdrrMux(.d0(PAdr[$clog2(LINELEN/8) - 1 : $clog2(MUXINTERVAL/8)]),
|
2022-11-09 23:52:50 +00:00
|
|
|
.d1(BeatCount), .s(SelBusBeat),
|
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-12-05 23:51:13 +00:00
|
|
|
mux2 #(LINELEN) EarlyReturnMux(ReadDataLineCache, FetchBuffer, SelFetchBuffer, ReadDataLine);
|
2022-07-19 04:37:18 +00:00
|
|
|
|
2022-08-02 02:06:36 +00:00
|
|
|
subcachelineread #(LINELEN, WORDLEN, MUXINTERVAL) subcachelineread(
|
2022-07-23 04:29:14 +00:00
|
|
|
.PAdr(WordOffsetAddr),
|
2022-03-11 18:44:04 +00:00
|
|
|
.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-08-02 02:06:36 +00:00
|
|
|
onehotdecoder #(LOGCWPL) adrdec(
|
|
|
|
.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded));
|
|
|
|
for(index = 0; index < 2**LOGCWPL; index++) begin
|
|
|
|
assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0;
|
2022-07-19 04:37:18 +00:00
|
|
|
end
|
2022-08-02 03:09:11 +00:00
|
|
|
|
2022-12-04 07:00:04 +00:00
|
|
|
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
|
2022-12-14 15:34:29 +00:00
|
|
|
logic [LINELEN/8-1:0] LineByteMask2;
|
|
|
|
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
2022-07-19 04:37:18 +00:00
|
|
|
|
|
|
|
for(index = 0; index < LINELEN/8; index++) begin
|
2022-12-04 07:00:04 +00:00
|
|
|
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
|
|
|
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index]));
|
2022-07-19 04:37:18 +00:00
|
|
|
end
|
2022-08-25 17:44:39 +00:00
|
|
|
|
2022-07-05 22:36:54 +00:00
|
|
|
mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
|
2022-12-05 23:19:51 +00:00
|
|
|
.d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
|
|
|
|
.d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}),
|
2022-12-14 15:49:15 +00:00
|
|
|
.s({SelFlush, SelWriteback}), .y(CacheBusAdr));
|
2022-12-09 22:42:05 +00:00
|
|
|
|
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),
|
2022-12-16 21:28:22 +00:00
|
|
|
.d(FlushAdrP1), .q(RawFlushAdr));
|
|
|
|
assign NextFlushAdr = FlushAdrCntEn ? FlushAdrP1 : RawFlushAdr;
|
|
|
|
assign FlushAdrP1 = RawFlushAdr + 1'b1;
|
|
|
|
assign FlushAdrFlag = (RawFlushAdr == FlushAdrThreshold[SETLEN-1:0]);
|
2022-02-03 15:36:11 +00:00
|
|
|
assign ResetOrFlushWay = reset | FlushWayCntRst;
|
2022-12-16 21:28:22 +00:00
|
|
|
flopenr #(SETLEN) OldFlushAdrReg(.clk, .reset(ResetOrFlushAdr), .en(FlushAdrCntEn),
|
|
|
|
.d(NextFlushAdr), .q(OldFlushAdr));
|
|
|
|
mux2 #(SETLEN) FlushAdrMux(NextFlushAdr, OldFlushAdr, SelOldFlushAdr, FlushAdr);
|
|
|
|
|
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-03 15:36:11 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Cache FSM
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
2022-09-23 16:46:53 +00:00
|
|
|
cachefsm cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
|
2022-12-11 21:51:35 +00:00
|
|
|
.FlushStage, .CacheRW, .CacheAtomic, .Stall,
|
2022-12-04 22:09:09 +00:00
|
|
|
.CacheHit, .LineDirty, .CacheStall, .CacheCommitted,
|
2022-02-12 04:23:47 +00:00
|
|
|
.CacheMiss, .CacheAccess, .SelAdr,
|
2022-02-13 21:06:18 +00:00
|
|
|
.ClearValid, .ClearDirty, .SetDirty,
|
2022-12-14 15:49:15 +00:00
|
|
|
.SetValid, .SelWriteback, .SelFlush,
|
2022-12-16 21:28:22 +00:00
|
|
|
.FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst, .SelOldFlushAdr,
|
2022-12-05 23:51:13 +00:00
|
|
|
.FlushWayCntRst, .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
2022-07-23 04:36:27 +00:00
|
|
|
.InvalidateCache,
|
2022-12-14 15:49:15 +00:00
|
|
|
.CacheEn,
|
2022-02-08 03:59:18 +00:00
|
|
|
.LRUWriteEn);
|
2022-02-03 15:36:11 +00:00
|
|
|
endmodule
|