From 9eda7c12bd9c4f1a6f7e56bc9662a9b04f145c09 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 4 Jan 2022 23:40:37 -0600 Subject: [PATCH] the i and d caches now share common verilog. --- pipelined/src/cache/cache.sv | 280 +++++++++++++++++++++++++++++++++++ pipelined/src/ifu/ifu.sv | 28 ++++ pipelined/src/lsu/lsu.sv | 11 +- 3 files changed, 314 insertions(+), 5 deletions(-) create mode 100644 pipelined/src/cache/cache.sv diff --git a/pipelined/src/cache/cache.sv b/pipelined/src/cache/cache.sv new file mode 100644 index 000000000..f9b6da29f --- /dev/null +++ b/pipelined/src/cache/cache.sv @@ -0,0 +1,280 @@ +/////////////////////////////////////////// +// 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 +// +// 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: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// 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. +/////////////////////////////////////////// + +`include "wally-config.vh" + +module cache #(parameter integer LINELEN, + parameter integer NUMLINES, + parameter integer NUMWAYS, + parameter integer DCACHE = 1) + (input logic clk, + input logic reset, + input logic CPUBusy, + + // cpu side + input logic [1:0] LsuRWM, + input logic [1:0] LsuAtomicM, + input logic FlushDCacheM, + input logic [11:0] LsuAdrE, // virtual address, but we only use the lower 12 bits. + input logic [`PA_BITS-1:0] LsuPAdrM, // physical address + input logic [11:0] PreLsuPAdrM, // physical or virtual address + input logic [`XLEN-1:0] FinalWriteDataM, + output logic [`XLEN-1:0] ReadDataWordM, + output logic DCacheCommittedM, + + // Bus fsm interface + input logic IgnoreRequest, + output logic DCacheFetchLine, + output logic DCacheWriteLine, + + input logic DCacheBusAck, + output logic [`PA_BITS-1:0] DCacheBusAdr, + + + input logic [LINELEN-1:0] DCacheMemWriteData, + output logic [`XLEN-1:0] ReadDataLineSetsM [(LINELEN/`XLEN)-1:0], + + output logic DCacheStall, + + // to performance counters + output logic DCacheMiss, + output logic DCacheAccess, + input logic InvalidateICacheM + ); + + + localparam integer LINEBYTELEN = LINELEN/8; + localparam integer OFFSETLEN = $clog2(LINEBYTELEN); + localparam integer INDEXLEN = $clog2(NUMLINES); + localparam integer TAGLEN = `PA_BITS - OFFSETLEN - INDEXLEN; + localparam integer WORDSPERLINE = LINELEN/`XLEN; + localparam integer LOGWPL = $clog2(WORDSPERLINE); + localparam integer LOGXLENBYTES = $clog2(`XLEN/8); + + localparam integer FlushAdrThreshold = NUMLINES; + + logic [1:0] SelAdrM; + logic [INDEXLEN-1:0] RAdr; + logic [LINELEN-1:0] SRAMWriteData; + logic SetValid, ClearValid; + logic SetDirty, ClearDirty; + logic [LINELEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0]; + logic [NUMWAYS-1:0] WayHit; + logic CacheHit; + logic [LINELEN-1:0] ReadDataLineM; + logic [WORDSPERLINE-1:0] SRAMWordEnable; + + logic SRAMWordWriteEnableM; + logic SRAMLineWriteEnableM; + logic [NUMWAYS-1:0] SRAMLineWayWriteEnableM; + logic [NUMWAYS-1:0] SRAMWayWriteEnable; + + + logic [NUMWAYS-1:0] VictimWay; + logic [NUMWAYS-1:0] VictimDirtyWay; + logic VictimDirty; + + logic [2**LOGWPL-1:0] MemPAdrDecodedW; + + logic [TAGLEN-1:0] VictimTagWay [NUMWAYS-1:0]; + logic [TAGLEN-1:0] VictimTag; + + logic [INDEXLEN-1:0] FlushAdr; + logic [INDEXLEN-1:0] FlushAdrP1; + logic [INDEXLEN-1:0] FlushAdrQ; + logic FlushAdrCntEn; + logic FlushAdrCntRst; + logic FlushAdrFlag; + + 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; + + // Read Path CPU (IEU) side + + mux3 #(INDEXLEN) + AdrSelMux(.d0(LsuAdrE[INDEXLEN+OFFSETLEN-1:OFFSETLEN]), + .d1(PreLsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]), + .d2(FlushAdr), + .s(SelAdrM), + .y(RAdr)); + + cacheway #(.NUMLINES(NUMLINES), .LINELEN(LINELEN), .TAGLEN(TAGLEN), + .OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN)) + MemWay[NUMWAYS-1:0](.clk, .reset, .RAdr, + .PAdr(LsuPAdrM), + .WriteEnable(SRAMWayWriteEnable), + .VDWriteEnable(VDWriteEnableWay), + .WriteWordEnable(SRAMWordEnable), + .TagWriteEnable(SRAMLineWayWriteEnableM), + .WriteData(SRAMWriteData), + .SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelEvict, + .VictimWay, .FlushWay, .SelFlush, + .ReadDataLineWayMasked, + .WayHit, .VictimDirtyWay, .VictimTagWay, + .InvalidateAll(InvalidateICacheM)); + + generate + if(NUMWAYS > 1) begin:vict + cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES) + cachereplacementpolicy(.clk, .reset, + .WayHit, + .VictimWay, + .LsuPAdrM(LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]), + .RAdr, + .LRUWriteEn); + end else begin:vict + assign VictimWay = 1'b1; // one hot. + end + endgenerate + + assign CacheHit = | WayHit; + assign VictimDirty = | VictimDirtyWay; + + + // ReadDataLineWayMaskedM is a 2d array of cache line len by number of ways. + // Need to OR together each way in a bitwise manner. + // Final part of the AO Mux. First is the AND in the cacheway. + or_rows #(NUMWAYS, LINELEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadDataLineM)); + or_rows #(NUMWAYS, TAGLEN) VictimTagAOMux(.a(VictimTagWay), .y(VictimTag)); + + + // Convert the Read data bus ReadDataSelectWay into sets of XLEN so we can + // easily build a variable input mux. + // *** consider using a limited range shift to do this final muxing. + genvar index; + generate + if(DCACHE == 1) begin + for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux + assign ReadDataLineSetsM[index] = ReadDataLineM[((index+1)*`XLEN)-1: (index*`XLEN)]; + end + // variable input mux + assign ReadDataWordM = ReadDataLineSetsM[LsuPAdrM[LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES]]; + + end else begin + logic [31:0] ReadLineSetsF [LINELEN/16-1:0]; + logic [31:0] FinalInstrRawF; + for(index = 0; index < LINELEN / 16 - 1; index++) begin:readlinesetsmux + assign ReadLineSetsF[index] = ReadDataLineM[((index+1)*16)+16-1 : (index*16)]; + end + assign ReadLineSetsF[LINELEN/16-1] = {16'b0, ReadDataLineM[LINELEN-1:LINELEN-16]}; + + assign FinalInstrRawF = ReadLineSetsF[LsuPAdrM[$clog2(LINELEN / 32) + 1 : 1]]; + if (`XLEN == 64) begin + assign ReadDataWordM = {32'b0, FinalInstrRawF}; + end else begin + assign ReadDataWordM = FinalInstrRawF; + end + + end + endgenerate + + + // Write Path CPU (IEU) side + + onehotdecoder #(LOGWPL) + adrdec(.bin(LsuPAdrM[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]), + .decoded(MemPAdrDecodedW)); + + assign SRAMWordEnable = SRAMLineWriteEnableM ? '1 : MemPAdrDecodedW; + + assign SRAMLineWayWriteEnableM = SRAMLineWriteEnableM ? VictimWay : '0; + + mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWriteEnableM ? WayHit : '0), + .d1(SRAMLineWayWriteEnableM), + .s(SRAMLineWriteEnableM), + .y(SRAMWayWriteEnable)); + + + + mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteDataM}}), + .d1(DCacheMemWriteData), + .s(SRAMLineWriteEnableM), + .y(SRAMWriteData)); + + + mux3 #(`PA_BITS) BaseAdrMux(.d0({LsuPAdrM[`PA_BITS-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}), + .d1({VictimTag, LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}), + .d2({VictimTag, FlushAdrQ, {{OFFSETLEN}{1'b0}}}), + .s({SelFlush, SelEvict}), + .y(DCacheBusAdr)); + + + // flush address and way generation. + // increment on 2nd to last way + flopenr #(INDEXLEN) + FlushAdrReg(.clk, + .reset(reset | FlushAdrCntRst), + .en(FlushAdrCntEn & FlushWay[NUMWAYS-2]), + .d(FlushAdrP1), + .q(FlushAdr)); + assign FlushAdrP1 = FlushAdr + 1'b1; + + flopenr #(INDEXLEN) + FlushAdrQReg(.clk, + .reset(reset | FlushAdrCntRst), + .en(FlushAdrCntEn), + .d(FlushAdr), + .q(FlushAdrQ)); + + flopenl #(NUMWAYS) + FlushWayReg(.clk, + .load(reset | FlushWayCntRst), + .en(FlushWayCntEn), + .val({{NUMWAYS-1{1'b0}}, 1'b1}), + .d(NextFlushWay), + .q(FlushWay)); + + assign VDWriteEnableWay = FlushWay & {NUMWAYS{VDWriteEnable}}; + + assign NextFlushWay = {FlushWay[NUMWAYS-2:0], FlushWay[NUMWAYS-1]}; + + assign FlushAdrFlag = FlushAdr == FlushAdrThreshold[INDEXLEN-1:0] & FlushWay[NUMWAYS-1]; + + // controller + logic CacheableM; + + assign CacheableM = 1; + + // *** fixme + dcachefsm dcachefsm(.clk, .reset, .DCacheFetchLine, .DCacheWriteLine, .DCacheBusAck, + .LsuRWM, .LsuAtomicM, .CPUBusy, .CacheableM, .IgnoreRequest, + .CacheHit, .VictimDirty, .DCacheStall, .DCacheCommittedM, + .DCacheMiss, .DCacheAccess, .SelAdrM, .SetValid, + .ClearValid, .SetDirty, .ClearDirty, .SRAMWordWriteEnableM, + .SRAMLineWriteEnableM, .SelEvict, .SelFlush, + .FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst, + .FlushWayCntRst, .FlushAdrFlag, .FlushDCacheM, + .VDWriteEnable, .LRUWriteEn); + + +endmodule // dcache diff --git a/pipelined/src/ifu/ifu.sv b/pipelined/src/ifu/ifu.sv index 9d1b7a7ef..c4e261f91 100644 --- a/pipelined/src/ifu/ifu.sv +++ b/pipelined/src/ifu/ifu.sv @@ -243,6 +243,7 @@ module ifu ( logic [1:0] IfuRWF; assign IfuRWF = CacheableF ? 2'b10 : 2'b00; +/* -----\/----- EXCLUDED -----\/----- icache #(.LINELEN(`ICACHE_LINELENINBITS), .NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS), .NUMWAYS(`ICACHE_NUMWAYS)) @@ -254,7 +255,34 @@ module ifu ( .PCPF(PCPF), .PCF(PCFMux), .InvalidateICacheM); + -----/\----- EXCLUDED -----/\----- */ + logic [`XLEN-1:0] FinalInstrRawF_FIXME; + + cache #(.LINELEN(`ICACHE_LINELENINBITS), + .NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS), + .NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0)) + icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .DCacheMemWriteData(ICacheMemWriteData) , .DCacheBusAck(ICacheBusAck), + .DCacheBusAdr(ICacheBusAdr), .DCacheStall(ICacheStallF), .ReadDataWordM(FinalInstrRawF_FIXME), + .DCacheFetchLine(ICacheFetchLine), + .DCacheWriteLine(), + .ReadDataLineSetsM(), + .DCacheMiss(), + .DCacheAccess(), + .FinalWriteDataM('0), + .LsuRWM(IfuRWF), //aways read + .LsuAtomicM(2'b00), + .FlushDCacheM(1'b0), + .LsuAdrE(PCNextFMux), + .LsuPAdrM(PCPF), + .PreLsuPAdrM(PCFMux[11:0]), + .DCacheCommittedM(), + .InvalidateICacheM); + + assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0]; + + + end else begin : passthrough assign ICacheFetchLine = 0; assign ICacheBusAdr = 0; diff --git a/pipelined/src/lsu/lsu.sv b/pipelined/src/lsu/lsu.sv index ebb4cc05e..005db88ef 100644 --- a/pipelined/src/lsu/lsu.sv +++ b/pipelined/src/lsu/lsu.sv @@ -306,15 +306,16 @@ module lsu generate if(`MEM_DCACHE) begin : dcache - dcache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN), - .NUMWAYS(`DCACHE_NUMWAYS)) + cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN), + .NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1)) dcache(.clk, .reset, .CPUBusy, - .LsuRWM, .FlushDCacheM, .LsuAtomicM, .LsuAdrE, .LsuPAdrM, .PreLsuPAdrM(PreLsuPAdrM[11:0]), // still don't like this name PreLsuPAdrM, not always physical + .LsuRWM(CacheableM ? LsuRWM : 2'b00), .FlushDCacheM, .LsuAtomicM(CacheableM ? LsuAtomicM : 2'b00), + .LsuAdrE, .LsuPAdrM, .PreLsuPAdrM(PreLsuPAdrM[11:0]), // still don't like this name PreLsuPAdrM, not always physical .FinalWriteDataM, .ReadDataWordM, .DCacheStall, .DCacheMiss, .DCacheAccess, - .IgnoreRequest, .CacheableM, .DCacheCommittedM, + .IgnoreRequest, .DCacheCommittedM, .DCacheBusAdr, .ReadDataLineSetsM, .DCacheMemWriteData, - .DCacheFetchLine, .DCacheWriteLine,.DCacheBusAck); + .DCacheFetchLine, .DCacheWriteLine,.DCacheBusAck, .InvalidateICacheM(1'b0)); end else begin : passthrough assign ReadDataWordM = 0; assign DCacheStall = 0;