mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-23 13:27:16 -04:00
the i and d caches now share common verilog.
This commit is contained in:
parent
b06c3b8acd
commit
9eda7c12bd
3 changed files with 314 additions and 5 deletions
280
pipelined/src/cache/cache.sv
vendored
Normal file
280
pipelined/src/cache/cache.sv
vendored
Normal file
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue