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-02-03 15:36:11 +00:00
|
|
|
module cache #(parameter LINELEN, NUMLINES, NUMWAYS, DCACHE = 1) (
|
|
|
|
input logic clk,
|
2022-01-05 22:57:22 +00:00
|
|
|
input logic reset,
|
2022-01-05 05:40:37 +00:00
|
|
|
// cpu side
|
2022-01-06 04:37:53 +00:00
|
|
|
input logic CPUBusy,
|
2022-01-05 22:57:22 +00:00
|
|
|
input logic [1:0] RW,
|
|
|
|
input logic [1:0] Atomic,
|
|
|
|
input logic FlushCache,
|
2022-01-06 04:37:53 +00:00
|
|
|
input logic InvalidateCacheM,
|
2022-01-06 04:19:36 +00:00
|
|
|
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-01-05 22:57:22 +00:00
|
|
|
input logic [`XLEN-1:0] FinalWriteData,
|
|
|
|
output logic [`XLEN-1:0] ReadDataWord,
|
2022-01-06 04:37:53 +00:00
|
|
|
output logic CacheCommitted,
|
|
|
|
output logic CacheStall,
|
|
|
|
// to performance counters to cpu
|
|
|
|
output logic CacheMiss,
|
|
|
|
output logic CacheAccess,
|
|
|
|
// lsu control
|
2022-01-05 22:57:22 +00:00
|
|
|
input logic IgnoreRequest,
|
2022-01-06 04:37:53 +00:00
|
|
|
// Bus fsm interface
|
2022-01-05 22:57:22 +00:00
|
|
|
output logic CacheFetchLine,
|
|
|
|
output logic CacheWriteLine,
|
|
|
|
input logic CacheBusAck,
|
2022-01-06 04:37:53 +00:00
|
|
|
output logic [`PA_BITS-1:0] CacheBusAdr,
|
2022-01-05 05:52:42 +00:00
|
|
|
input logic [LINELEN-1:0] CacheMemWriteData,
|
2022-01-06 04:37:53 +00:00
|
|
|
output logic [`XLEN-1:0] ReadDataLineSets [(LINELEN/`XLEN)-1:0]);
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-02-03 15:36:11 +00:00
|
|
|
// Cache parameters
|
|
|
|
localparam LINEBYTELEN = LINELEN/8;
|
|
|
|
localparam OFFSETLEN = $clog2(LINEBYTELEN);
|
|
|
|
localparam SETLEN = $clog2(NUMLINES);
|
|
|
|
localparam SETTOP = SETLEN+OFFSETLEN;
|
|
|
|
localparam TAGLEN = `PA_BITS - SETTOP;
|
|
|
|
localparam WORDSPERLINE = LINELEN/`XLEN;
|
|
|
|
localparam LOGWPL = $clog2(WORDSPERLINE);
|
|
|
|
localparam LOGXLENBYTES = $clog2(`XLEN/8);
|
|
|
|
localparam FlushAdrThreshold = NUMLINES - 1;
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-01-05 20:14:01 +00:00
|
|
|
logic [1:0] SelAdr;
|
2022-02-03 15:36:11 +00:00
|
|
|
logic [SETLEN-1:0] RAdr;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [LINELEN-1:0] SRAMWriteData;
|
|
|
|
logic SetValid, ClearValid;
|
|
|
|
logic SetDirty, ClearDirty;
|
2022-02-03 16:52:22 +00:00
|
|
|
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [NUMWAYS-1:0] WayHit;
|
|
|
|
logic CacheHit;
|
2022-01-06 04:37:53 +00:00
|
|
|
logic [LINELEN-1:0] ReadDataLine;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [WORDSPERLINE-1:0] SRAMWordEnable;
|
2022-01-06 04:37:53 +00:00
|
|
|
logic SRAMWordWriteEnable;
|
|
|
|
logic SRAMLineWriteEnable;
|
|
|
|
logic [NUMWAYS-1:0] SRAMLineWayWriteEnable;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [NUMWAYS-1:0] SRAMWayWriteEnable;
|
2022-02-03 15:36:11 +00:00
|
|
|
logic [NUMWAYS-1:0] SRAMWordWayWriteEnable;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [NUMWAYS-1:0] VictimWay;
|
|
|
|
logic [NUMWAYS-1:0] VictimDirtyWay;
|
|
|
|
logic VictimDirty;
|
2022-01-06 04:37:53 +00:00
|
|
|
logic [2**LOGWPL-1:0] MemPAdrDecoded;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [TAGLEN-1:0] VictimTagWay [NUMWAYS-1:0];
|
|
|
|
logic [TAGLEN-1:0] VictimTag;
|
2022-02-03 15:36:11 +00:00
|
|
|
logic [SETLEN-1:0] FlushAdr;
|
|
|
|
logic [SETLEN-1:0] FlushAdrP1;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic FlushAdrCntEn;
|
|
|
|
logic FlushAdrCntRst;
|
|
|
|
logic FlushAdrFlag;
|
2022-02-03 15:36:11 +00:00
|
|
|
logic FlushWayFlag;
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [NUMWAYS-1:0] FlushWay;
|
|
|
|
logic [NUMWAYS-1:0] NextFlushWay;
|
|
|
|
logic FlushWayCntEn;
|
|
|
|
logic FlushWayCntRst;
|
|
|
|
logic VDWriteEnable;
|
|
|
|
logic SelEvict;
|
|
|
|
logic LRUWriteEn;
|
|
|
|
logic [NUMWAYS-1:0] VDWriteEnableWay;
|
|
|
|
logic SelFlush;
|
2022-02-04 19:31:32 +00:00
|
|
|
logic ResetOrFlushAdr, ResetOrFlushWay;
|
|
|
|
logic save, restore;
|
2022-02-04 20:18:10 +00:00
|
|
|
logic [NUMWAYS-1:0] WayHitSaved, WayHitRaw;
|
|
|
|
logic [LINELEN-1:0] ReadDataLineRaw, ReadDataLineSaved;
|
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),
|
|
|
|
.s(SelAdr), .y(RAdr));
|
|
|
|
|
|
|
|
// Array of cache ways, along with victim, hit, dirty, and read merging logic
|
|
|
|
cacheway #(NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN) CacheWays[NUMWAYS-1:0](
|
|
|
|
.clk, .reset, .RAdr, .PAdr,
|
|
|
|
.WriteEnable(SRAMWayWriteEnable),
|
|
|
|
.VDWriteEnable(VDWriteEnableWay),
|
|
|
|
.WriteWordEnable(SRAMWordEnable),
|
|
|
|
.TagWriteEnable(SRAMLineWayWriteEnable),
|
|
|
|
.WriteData(SRAMWriteData),
|
2022-02-04 19:31:32 +00:00
|
|
|
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelEvict, .Victim(VictimWay), .Flush(FlushWay),
|
2022-02-04 20:18:10 +00:00
|
|
|
.SelFlush,
|
|
|
|
.SelectedReadDataLine(ReadDataLineWay), .WayHit(WayHitRaw), .VictimDirty(VictimDirtyWay), .VictimTag(VictimTagWay),
|
2022-02-03 15:36:11 +00:00
|
|
|
.InvalidateAll(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(
|
|
|
|
.clk, .reset, .WayHit, .VictimWay, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .RAdr, .LRUWriteEn);
|
|
|
|
end else assign VictimWay = 1'b1; // one hot.
|
2022-01-05 05:40:37 +00:00
|
|
|
assign CacheHit = | WayHit;
|
|
|
|
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-02-04 20:35:12 +00:00
|
|
|
or_rows #(NUMWAYS, LINELEN) ReadDataAOMux(.a(ReadDataLineWay), .y(ReadDataLine));
|
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.
|
|
|
|
flopenr #(NUMWAYS) wayhitsavereg(clk, save, reset, WayHitRaw, WayHitSaved);
|
2022-02-04 20:35:12 +00:00
|
|
|
mux2 #(NUMWAYS) saverestoremux(WayHitRaw, WayHitSaved, restore, WayHit);
|
2022-02-04 20:18:10 +00:00
|
|
|
|
|
|
|
|
2022-01-05 05:40:37 +00:00
|
|
|
// Convert the Read data bus ReadDataSelectWay into sets of XLEN so we can
|
|
|
|
// easily build a variable input mux.
|
2022-02-03 15:36:11 +00:00
|
|
|
// *** move this to LSU and IFU, also remove mux from busdp into LSU.
|
|
|
|
// *** give this a module name to match block diagram
|
2022-02-04 20:35:12 +00:00
|
|
|
logic [`XLEN-1:0] ReadDataWordRaw, ReadDataWordSaved;
|
2022-01-05 05:40:37 +00:00
|
|
|
genvar index;
|
2022-02-04 20:35:12 +00:00
|
|
|
if(DCACHE == 1) begin: readdata
|
2022-01-05 16:01:03 +00:00
|
|
|
for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux
|
2022-01-06 04:37:53 +00:00
|
|
|
assign ReadDataLineSets[index] = ReadDataLine[((index+1)*`XLEN)-1: (index*`XLEN)];
|
2022-01-05 16:01:03 +00:00
|
|
|
end
|
2022-01-05 05:40:37 +00:00
|
|
|
// variable input mux
|
2022-02-04 20:35:12 +00:00
|
|
|
assign ReadDataWordRaw = ReadDataLineSets[PAdr[LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES]];
|
2022-01-05 16:01:03 +00:00
|
|
|
end else begin: readdata
|
2022-01-05 05:40:37 +00:00
|
|
|
logic [31:0] ReadLineSetsF [LINELEN/16-1:0];
|
|
|
|
logic [31:0] FinalInstrRawF;
|
2022-01-05 16:01:03 +00:00
|
|
|
for(index = 0; index < LINELEN / 16 - 1; index++)
|
2022-01-06 04:37:53 +00:00
|
|
|
assign ReadLineSetsF[index] = ReadDataLine[((index+1)*16)+16-1 : (index*16)];
|
|
|
|
assign ReadLineSetsF[LINELEN/16-1] = {16'b0, ReadDataLine[LINELEN-1:LINELEN-16]};
|
2022-01-06 04:19:36 +00:00
|
|
|
assign FinalInstrRawF = ReadLineSetsF[PAdr[$clog2(LINELEN / 32) + 1 : 1]];
|
2022-02-04 20:35:12 +00:00
|
|
|
if (`XLEN == 64) assign ReadDataWordRaw = {32'b0, FinalInstrRawF};
|
|
|
|
else assign ReadDataWordRaw = FinalInstrRawF;
|
2022-01-05 05:40:37 +00:00
|
|
|
end
|
2022-02-04 20:35:12 +00:00
|
|
|
flopen #(`XLEN) cachereaddatasavereg(clk, save, ReadDataWordRaw, ReadDataWordSaved);
|
|
|
|
mux2 #(`XLEN) readdatasaverestoremux(ReadDataWordRaw, ReadDataWordSaved,
|
|
|
|
restore, ReadDataWord);
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-02-03 15:36:11 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Write Path: Write Enables
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// *** Ross considering restructuring
|
|
|
|
onehotdecoder #(LOGWPL) adrdec(
|
|
|
|
.bin(PAdr[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]), .decoded(MemPAdrDecoded));
|
|
|
|
assign SRAMWordEnable = SRAMLineWriteEnable ? '1 : MemPAdrDecoded; // OR
|
|
|
|
assign SRAMLineWayWriteEnable = SRAMLineWriteEnable ? VictimWay : '0; // AND
|
|
|
|
assign SRAMWordWayWriteEnable = SRAMWordWriteEnable ? WayHit : '0; // AND
|
|
|
|
mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWayWriteEnable), .d1(VictimWay),
|
|
|
|
.s(SRAMLineWriteEnable), .y(SRAMWayWriteEnable));
|
2022-01-05 05:52:42 +00:00
|
|
|
mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteData}}),
|
2022-02-03 15:36:11 +00:00
|
|
|
.d1(CacheMemWriteData), .s(SRAMLineWriteEnable), .y(SRAMWriteData));
|
|
|
|
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}}}),
|
|
|
|
.s({SelFlush, SelEvict}),
|
|
|
|
.y(CacheBusAdr));
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Flush address and way generation during flush
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
assign ResetOrFlushAdr = reset | FlushAdrCntRst;
|
|
|
|
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]);
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-02-03 15:36:11 +00:00
|
|
|
assign ResetOrFlushWay = reset | FlushWayCntRst;
|
|
|
|
flopenl #(NUMWAYS) FlushWayReg(.clk, .load(ResetOrFlushWay),
|
|
|
|
.en(FlushWayCntEn), .val({{NUMWAYS-1{1'b0}}, 1'b1}),
|
|
|
|
.d(NextFlushWay), .q(FlushWay));
|
|
|
|
assign FlushWayFlag = FlushWay[NUMWAYS-1];
|
2022-01-05 05:40:37 +00:00
|
|
|
assign VDWriteEnableWay = FlushWay & {NUMWAYS{VDWriteEnable}};
|
|
|
|
assign NextFlushWay = {FlushWay[NUMWAYS-2:0], FlushWay[NUMWAYS-1]};
|
|
|
|
|
2022-02-03 15:36:11 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Cache FSM
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
2022-01-05 05:40:37 +00:00
|
|
|
|
2022-01-05 05:52:42 +00:00
|
|
|
cachefsm cachefsm(.clk, .reset, .CacheFetchLine, .CacheWriteLine, .CacheBusAck,
|
2022-02-03 15:36:11 +00:00
|
|
|
.RW, .Atomic, .CPUBusy, .IgnoreRequest,
|
|
|
|
.CacheHit, .VictimDirty, .CacheStall, .CacheCommitted,
|
|
|
|
.CacheMiss, .CacheAccess, .SelAdr, .SetValid,
|
|
|
|
.ClearValid, .SetDirty, .ClearDirty, .SRAMWordWriteEnable,
|
|
|
|
.SRAMLineWriteEnable, .SelEvict, .SelFlush,
|
|
|
|
.FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst,
|
|
|
|
.FlushWayCntRst, .FlushAdrFlag, .FlushWayFlag, .FlushCache,
|
2022-02-04 19:31:32 +00:00
|
|
|
.save, .restore,
|
2022-02-03 15:36:11 +00:00
|
|
|
.VDWriteEnable, .LRUWriteEn);
|
|
|
|
endmodule
|