mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge pull request #651 from ross144/main
Updates to cache logic. Code quality improvements.
This commit is contained in:
commit
af1ecfc30d
@ -21,7 +21,7 @@ ROOT := ..
|
|||||||
LIBRARY_DIRS :=
|
LIBRARY_DIRS :=
|
||||||
LIBRARY_FILES :=
|
LIBRARY_FILES :=
|
||||||
|
|
||||||
MARCH :=-march=rv64imfdc
|
MARCH :=-march=rv64imfdc_zifencei
|
||||||
MABI :=-mabi=lp64d
|
MABI :=-mabi=lp64d
|
||||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
|
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
|
||||||
LINKER :=linker.x
|
LINKER :=linker.x
|
@ -94,5 +94,5 @@ end_of_bios:
|
|||||||
.globl _dtb
|
.globl _dtb
|
||||||
.align 4, 0
|
.align 4, 0
|
||||||
_dtb:
|
_dtb:
|
||||||
.incbin "wally-vcu118.dtb"
|
#.incbin "wally-vcu118.dtb"
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// SDC.sv
|
// SDC.sv
|
||||||
//
|
//
|
||||||
// Written: Ross Thompson September 25, 2021
|
// Written: Rose Thompson September 25, 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: driver for sdc reader.
|
// Purpose: driver for sdc reader.
|
16
src/cache/cache.sv
vendored
16
src/cache/cache.sv
vendored
@ -82,7 +82,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
logic ClearDirty, SetDirty, SetValid, ClearValid;
|
logic ClearDirty, SetDirty, SetValid, ClearValid;
|
||||||
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
|
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
|
||||||
logic [NUMWAYS-1:0] HitWay, ValidWay;
|
logic [NUMWAYS-1:0] HitWay, ValidWay;
|
||||||
logic CacheHit;
|
logic Hit;
|
||||||
logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay;
|
logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay;
|
||||||
logic LineDirty, HitLineDirty;
|
logic LineDirty, HitLineDirty;
|
||||||
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0];
|
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0];
|
||||||
@ -98,7 +98,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
|
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
|
||||||
logic SelFetchBuffer;
|
logic SelFetchBuffer;
|
||||||
logic CacheEn;
|
logic CacheEn;
|
||||||
logic SelWay;
|
logic SelVictim;
|
||||||
logic [LINELEN/8-1:0] LineByteMask;
|
logic [LINELEN/8-1:0] LineByteMask;
|
||||||
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
||||||
genvar index;
|
genvar index;
|
||||||
@ -120,7 +120,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
// Array of cache ways, along with victim, hit, dirty, and read merging logic
|
// Array of cache ways, along with victim, hit, dirty, and read merging logic
|
||||||
cacheway #(P, PA_BITS, XLEN, NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
|
cacheway #(P, PA_BITS, XLEN, NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
|
||||||
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelWay,
|
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelVictim,
|
||||||
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
|
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
|
||||||
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
|
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
end else
|
end else
|
||||||
assign VictimWay = 1'b1; // one hot.
|
assign VictimWay = 1'b1; // one hot.
|
||||||
|
|
||||||
assign CacheHit = |HitWay;
|
assign Hit = |HitWay;
|
||||||
assign LineDirty = |DirtyWay;
|
assign LineDirty = |DirtyWay;
|
||||||
assign HitLineDirty = |HitDirtyWay;
|
assign HitLineDirty = |HitDirtyWay;
|
||||||
|
|
||||||
@ -180,14 +180,14 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
assign DemuxedByteMask = BlankByteMask << ((MUXINTERVAL/8) * WordOffsetAddr);
|
assign DemuxedByteMask = BlankByteMask << ((MUXINTERVAL/8) * WordOffsetAddr);
|
||||||
|
|
||||||
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
|
assign FetchBufferByteSel = SetDirty ? ~DemuxedByteMask : '1; // If load miss set all muxes to 1.
|
||||||
|
|
||||||
// Merge write data into fetched cache line for store miss
|
// Merge write data into fetched cache line for store miss
|
||||||
for(index = 0; index < LINELEN/8; index++) begin
|
for(index = 0; index < LINELEN/8; index++) begin
|
||||||
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
||||||
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index]));
|
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index]));
|
||||||
end
|
end
|
||||||
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : 0;
|
assign LineByteMask = SetDirty ? DemuxedByteMask : '1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin:WriteSelLogic
|
begin:WriteSelLogic
|
||||||
@ -226,8 +226,8 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
|
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
|
||||||
.FlushStage, .CacheRW, .Stall,
|
.FlushStage, .CacheRW, .Stall,
|
||||||
.CacheHit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
|
.Hit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
|
||||||
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelWay,
|
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelVictim,
|
||||||
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
|
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
|
||||||
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
|
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
|
||||||
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
||||||
|
44
src/cache/cacheLRU.sv
vendored
44
src/cache/cacheLRU.sv
vendored
@ -1,7 +1,7 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// cacheLRU.sv
|
// cacheLRU.sv
|
||||||
//
|
//
|
||||||
// Written: Ross Thompson ross1728@gmail.com
|
// Written: Rose Thompson ross1728@gmail.com
|
||||||
// Created: 20 July 2021
|
// Created: 20 July 2021
|
||||||
// Modified: 20 January 2023
|
// Modified: 20 January 2023
|
||||||
//
|
//
|
||||||
@ -36,8 +36,8 @@ module cacheLRU
|
|||||||
input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant
|
input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant
|
||||||
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
|
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
|
||||||
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
|
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
|
||||||
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||||
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||||
input logic [SETLEN-1:0] PAdr, // Physical address
|
input logic [SETLEN-1:0] PAdr, // Physical address
|
||||||
input logic LRUWriteEn, // Update the LRU state
|
input logic LRUWriteEn, // Update the LRU state
|
||||||
input logic SetValid, // Set the dirty bit in the selected way and set
|
input logic SetValid, // Set the dirty bit in the selected way and set
|
||||||
@ -51,23 +51,27 @@ module cacheLRU
|
|||||||
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
|
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
|
||||||
logic [NUMWAYS-2:0] CurrLRU;
|
logic [NUMWAYS-2:0] CurrLRU;
|
||||||
logic [NUMWAYS-2:0] NextLRU;
|
logic [NUMWAYS-2:0] NextLRU;
|
||||||
logic [NUMWAYS-1:0] Way;
|
logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
|
||||||
logic [LOGNUMWAYS-1:0] WayEncoded;
|
|
||||||
logic [NUMWAYS-2:0] WayExpanded;
|
logic [NUMWAYS-2:0] WayExpanded;
|
||||||
logic AllValid;
|
logic AllValid;
|
||||||
|
|
||||||
genvar row;
|
genvar row;
|
||||||
|
|
||||||
/* verilator lint_off UNOPTFLAT */
|
/* verilator lint_off UNOPTFLAT */
|
||||||
// Ross: For some reason verilator does not like this. I checked and it is not a circular path.
|
// Rose: For some reason verilator does not like this. I checked and it is not a circular path.
|
||||||
logic [NUMWAYS-2:0] LRUUpdate;
|
logic [NUMWAYS-2:0] LRUUpdate;
|
||||||
logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0];
|
logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0];
|
||||||
/* verilator lint_on UNOPTFLAT */
|
/* verilator lint_on UNOPTFLAT */
|
||||||
|
|
||||||
|
logic [NUMWAYS-1:0] FirstZero;
|
||||||
|
logic [LOGNUMWAYS-1:0] FirstZeroWay;
|
||||||
|
logic [LOGNUMWAYS-1:0] VictimWayEnc;
|
||||||
|
|
||||||
|
binencoder #(NUMWAYS) hitwayencoder(HitWay, HitWayEncoded);
|
||||||
|
|
||||||
assign AllValid = &ValidWay;
|
assign AllValid = &ValidWay;
|
||||||
|
|
||||||
///// Update replacement bits.
|
///// Update replacement bits.
|
||||||
|
|
||||||
// coverage off
|
// coverage off
|
||||||
// Excluded from coverage b/c it is untestable without varying NUMWAYS.
|
// Excluded from coverage b/c it is untestable without varying NUMWAYS.
|
||||||
function integer log2 (integer value);
|
function integer log2 (integer value);
|
||||||
@ -80,8 +84,7 @@ module cacheLRU
|
|||||||
// coverage on
|
// coverage on
|
||||||
|
|
||||||
// On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay.
|
// On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay.
|
||||||
mux2 #(NUMWAYS) WayMux(HitWay, VictimWay, SetValid, Way);
|
mux2 #(LOGNUMWAYS) WayMuxEnc(HitWayEncoded, VictimWayEnc, SetValid, Way);
|
||||||
binencoder #(NUMWAYS) encoder(Way, WayEncoded);
|
|
||||||
|
|
||||||
// bit duplication
|
// bit duplication
|
||||||
// expand HitWay as HitWay[3], {{2}{HitWay[2]}}, {{4}{HitWay[1]}, {{8{HitWay[0]}}, ...
|
// expand HitWay as HitWay[3], {{2}{HitWay[2]}}, {{4}{HitWay[1]}, {{8{HitWay[0]}}, ...
|
||||||
@ -89,7 +92,7 @@ module cacheLRU
|
|||||||
localparam integer DuplicationFactor = 2**(LOGNUMWAYS-row-1);
|
localparam integer DuplicationFactor = 2**(LOGNUMWAYS-row-1);
|
||||||
localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1;
|
localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1;
|
||||||
localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2;
|
localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2;
|
||||||
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{WayEncoded[row]}};
|
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{Way[row]}};
|
||||||
end
|
end
|
||||||
|
|
||||||
genvar node;
|
genvar node;
|
||||||
@ -102,14 +105,14 @@ module cacheLRU
|
|||||||
localparam r = LOGNUMWAYS - ctr_depth;
|
localparam r = LOGNUMWAYS - ctr_depth;
|
||||||
|
|
||||||
// the child node will be updated if its parent was updated and
|
// the child node will be updated if its parent was updated and
|
||||||
// the WayEncoded bit was the correct value.
|
// the Way bit was the correct value.
|
||||||
// The if statement is only there for coverage since LRUUpdate[root] is always 1.
|
// The if statement is only there for coverage since LRUUpdate[root] is always 1.
|
||||||
if (node == NUMWAYS-2) begin
|
if (node == NUMWAYS-2) begin
|
||||||
assign LRUUpdate[lchild] = ~WayEncoded[r];
|
assign LRUUpdate[lchild] = ~Way[r];
|
||||||
assign LRUUpdate[rchild] = WayEncoded[r];
|
assign LRUUpdate[rchild] = Way[r];
|
||||||
end else begin
|
end else begin
|
||||||
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
|
assign LRUUpdate[lchild] = LRUUpdate[node] & ~Way[r];
|
||||||
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
|
assign LRUUpdate[rchild] = LRUUpdate[node] & Way[r];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -129,28 +132,25 @@ module cacheLRU
|
|||||||
assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0];
|
assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
logic [NUMWAYS-1:0] FirstZero;
|
|
||||||
logic [LOGNUMWAYS-1:0] FirstZeroWay;
|
|
||||||
logic [LOGNUMWAYS-1:0] VictimWayEnc;
|
|
||||||
|
|
||||||
priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero);
|
priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero);
|
||||||
binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay);
|
binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay);
|
||||||
mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc);
|
mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc);
|
||||||
//decoder #(LOGNUMWAYS) decoder (Intermediate[NUMWAYS-2], VictimWay);
|
|
||||||
decoder #(LOGNUMWAYS) decoder (VictimWayEnc, VictimWay);
|
decoder #(LOGNUMWAYS) decoder (VictimWayEnc, VictimWay);
|
||||||
|
|
||||||
// LRU storage must be reset for modelsim to run. However the reset value does not actually matter in practice.
|
// LRU storage must be reset for modelsim to run. However the reset value does not actually matter in practice.
|
||||||
// This is a two port memory.
|
// This is a two port memory.
|
||||||
// Every cycle must read from CacheSetData and each load/store must write the new LRU.
|
// Every cycle must read from CacheSetData and each load/store must write the new LRU.
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset | (InvalidateCache & ~FlushStage)) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= 0;
|
if (reset | (InvalidateCache & ~FlushStage))
|
||||||
|
for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= 0; // exclusion-tag: initialize
|
||||||
if(CacheEn) begin
|
if(CacheEn) begin
|
||||||
if(LRUWriteEn)
|
if(LRUWriteEn)
|
||||||
LRUMemory[PAdr] <= NextLRU;
|
LRUMemory[PAdr] <= NextLRU;
|
||||||
if(LRUWriteEn & (PAdr == CacheSetTag))
|
if(LRUWriteEn & (PAdr == CacheSetTag))
|
||||||
CurrLRU <= NextLRU;
|
CurrLRU <= #1 NextLRU;
|
||||||
else
|
else
|
||||||
CurrLRU <= LRUMemory[CacheSetTag];
|
CurrLRU <= #1 LRUMemory[CacheSetTag];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
76
src/cache/cachefsm.sv
vendored
76
src/cache/cachefsm.sv
vendored
@ -50,7 +50,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
output logic CacheAccess, // Cache access
|
output logic CacheAccess, // Cache access
|
||||||
|
|
||||||
// cache internals
|
// cache internals
|
||||||
input logic CacheHit, // Exactly 1 way hits
|
input logic Hit, // Exactly 1 way hits
|
||||||
input logic LineDirty, // The selected line and way is dirty
|
input logic LineDirty, // The selected line and way is dirty
|
||||||
input logic HitLineDirty, // The cache hit way is dirty
|
input logic HitLineDirty, // The cache hit way is dirty
|
||||||
input logic FlushAdrFlag, // On last set of a cache flush
|
input logic FlushAdrFlag, // On last set of a cache flush
|
||||||
@ -63,7 +63,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||||
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
||||||
output logic LRUWriteEn, // Update the LRU state
|
output logic LRUWriteEn, // Update the LRU state
|
||||||
output logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
|
output logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||||
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
|
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
|
||||||
output logic FlushWayCntEn, // Enable the way counter during a flush
|
output logic FlushWayCntEn, // Enable the way counter during a flush
|
||||||
output logic FlushCntRst, // Reset both flush counters
|
output logic FlushCntRst, // Reset both flush counters
|
||||||
@ -79,12 +79,12 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
logic CMOZeroNoEviction;
|
logic CMOZeroNoEviction;
|
||||||
logic StallConditions;
|
logic StallConditions;
|
||||||
|
|
||||||
typedef enum logic [3:0]{STATE_READY, // hit states
|
typedef enum logic [3:0]{STATE_ACCESS, // hit states
|
||||||
// miss states
|
// miss states
|
||||||
STATE_FETCH,
|
STATE_FETCH,
|
||||||
STATE_WRITEBACK,
|
STATE_WRITEBACK,
|
||||||
STATE_WRITE_LINE,
|
STATE_WRITE_LINE,
|
||||||
STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM
|
STATE_ADDRESS_SETUP, // required for back to back reads. structural hazard on writting SRAM
|
||||||
// flush cache
|
// flush cache
|
||||||
STATE_FLUSH,
|
STATE_FLUSH,
|
||||||
STATE_FLUSH_WRITEBACK
|
STATE_FLUSH_WRITEBACK
|
||||||
@ -92,60 +92,60 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
statetype CurrState, NextState;
|
statetype CurrState, NextState;
|
||||||
|
|
||||||
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||||
assign AnyUpdateHit = (CacheRW[0]) & CacheHit; // exclusion-tag: icache storeAMO1
|
assign AnyUpdateHit = (CacheRW[0]) & Hit; // exclusion-tag: icache storeAMO1
|
||||||
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit
|
assign AnyHit = AnyUpdateHit | (CacheRW[1] & Hit); // exclusion-tag: icache AnyUpdateHit
|
||||||
assign CMOZeroNoEviction = CMOpM[3] & ~LineDirty; // (hit or miss) with no writeback store zeros now
|
assign CMOZeroNoEviction = CMOpM[3] & ~LineDirty; // (hit or miss) with no writeback store zeros now
|
||||||
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & CacheHit & HitLineDirty) | CMOpM[3] & LineDirty;
|
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & Hit & HitLineDirty) | CMOpM[3] & LineDirty;
|
||||||
|
|
||||||
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
|
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
|
||||||
|
|
||||||
// outputs for the performance counters.
|
// outputs for the performance counters.
|
||||||
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_READY & ~Stall & ~FlushStage) | (CurrState == STATE_READ_HOLD & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
|
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_ACCESS & ~Stall & ~FlushStage) | (CurrState == STATE_ADDRESS_SETUP & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
|
||||||
assign CacheMiss = CacheAccess & ~CacheHit;
|
assign CacheMiss = CacheAccess & ~Hit;
|
||||||
|
|
||||||
// special case on reset. When the fsm first exists reset the
|
// special case on reset. When the fsm first exists reset twayhe
|
||||||
// PCNextF will no longer be pointing to the correct address.
|
// PCNextF will no longer be pointing to the correct address.
|
||||||
// But PCF will be the reset vector.
|
// But PCF will be the reset vector.
|
||||||
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
|
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
|
||||||
|
|
||||||
always_ff @(posedge clk)
|
always_ff @(posedge clk)
|
||||||
if (reset | FlushStage) CurrState <= #1 STATE_READY;
|
if (reset | FlushStage) CurrState <= #1 STATE_ACCESS;
|
||||||
else CurrState <= #1 NextState;
|
else CurrState <= #1 NextState;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
NextState = STATE_READY;
|
NextState = STATE_ACCESS;
|
||||||
case (CurrState) // exclusion-tag: icache state-case
|
case (CurrState) // exclusion-tag: icache state-case
|
||||||
STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck
|
STATE_ACCESS: if(InvalidateCache) NextState = STATE_ACCESS; // exclusion-tag: dcache InvalidateCheck
|
||||||
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; // exclusion-tag: icache FLUSHStatement
|
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; // exclusion-tag: icache FLUSHStatement
|
||||||
else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement
|
else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement
|
||||||
else if((AnyMiss | CMOWriteback) & ~READ_ONLY_CACHE) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
|
else if((AnyMiss | CMOWriteback) & ~READ_ONLY_CACHE) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
|
||||||
else NextState = STATE_READY;
|
else NextState = STATE_ACCESS;
|
||||||
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
|
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
|
||||||
else NextState = STATE_FETCH;
|
else NextState = STATE_FETCH;
|
||||||
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
|
STATE_WRITE_LINE: NextState = STATE_ADDRESS_SETUP;
|
||||||
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
|
STATE_ADDRESS_SETUP: if(Stall) NextState = STATE_ADDRESS_SETUP;
|
||||||
else NextState = STATE_READY;
|
else NextState = STATE_ACCESS;
|
||||||
// exclusion-tag-start: icache case
|
// exclusion-tag-start: icache case
|
||||||
STATE_WRITEBACK: if(CacheBusAck & ~(|CMOpM[3:1])) NextState = STATE_FETCH;
|
STATE_WRITEBACK: if(CacheBusAck & ~(|CMOpM[3:1])) NextState = STATE_FETCH;
|
||||||
else if(CacheBusAck) NextState = STATE_READ_HOLD; // Read_hold lowers CacheStall
|
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP; // Read_hold lowers CacheStall
|
||||||
else NextState = STATE_WRITEBACK;
|
else NextState = STATE_WRITEBACK;
|
||||||
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
|
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
|
||||||
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
|
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
|
||||||
else if (FlushFlag) NextState = STATE_READ_HOLD;
|
else if (FlushFlag) NextState = STATE_ADDRESS_SETUP;
|
||||||
else NextState = STATE_FLUSH;
|
else NextState = STATE_FLUSH;
|
||||||
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
|
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
|
||||||
else if(CacheBusAck) NextState = STATE_READ_HOLD;
|
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP;
|
||||||
else NextState = STATE_FLUSH_WRITEBACK;
|
else NextState = STATE_FLUSH_WRITEBACK;
|
||||||
// exclusion-tag-end: icache case
|
// exclusion-tag-end: icache case
|
||||||
default: NextState = STATE_READY;
|
default: NextState = STATE_ACCESS;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
// com back to CPU
|
// com back to CPU
|
||||||
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & (CurrState == STATE_READ_HOLD));
|
assign CacheCommitted = (CurrState != STATE_ACCESS) & ~(READ_ONLY_CACHE & (CurrState == STATE_ADDRESS_SETUP));
|
||||||
assign StallConditions = FlushCache | AnyMiss | CMOWriteback; // exclusion-tag: icache FlushCache
|
assign StallConditions = FlushCache | AnyMiss | CMOWriteback; // exclusion-tag: icache FlushCache
|
||||||
assign CacheStall = (CurrState == STATE_READY & StallConditions) | // exclusion-tag: icache StallStates
|
assign CacheStall = (CurrState == STATE_ACCESS & StallConditions) | // exclusion-tag: icache StallStates
|
||||||
(CurrState == STATE_FETCH) |
|
(CurrState == STATE_FETCH) |
|
||||||
(CurrState == STATE_WRITEBACK) |
|
(CurrState == STATE_WRITEBACK) |
|
||||||
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
|
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
|
||||||
@ -153,26 +153,26 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
(CurrState == STATE_FLUSH_WRITEBACK);
|
(CurrState == STATE_FLUSH_WRITEBACK);
|
||||||
// write enables internal to cache
|
// write enables internal to cache
|
||||||
assign SetValid = CurrState == STATE_WRITE_LINE |
|
assign SetValid = CurrState == STATE_WRITE_LINE |
|
||||||
(CurrState == STATE_READY & CMOZeroNoEviction) |
|
(CurrState == STATE_ACCESS & CMOZeroNoEviction) |
|
||||||
(CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]);
|
(CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]);
|
||||||
assign ClearValid = (CurrState == STATE_READY & CMOpM[0]) |
|
assign ClearValid = (CurrState == STATE_ACCESS & CMOpM[0]) |
|
||||||
(CurrState == STATE_WRITEBACK & CMOpM[2] & CacheBusAck);
|
(CurrState == STATE_WRITEBACK & CMOpM[2] & CacheBusAck);
|
||||||
assign LRUWriteEn = (((CurrState == STATE_READY & (AnyHit | CMOZeroNoEviction)) |
|
assign LRUWriteEn = (((CurrState == STATE_ACCESS & (AnyHit | CMOZeroNoEviction)) |
|
||||||
(CurrState == STATE_WRITE_LINE)) & ~FlushStage) |
|
(CurrState == STATE_WRITE_LINE)) & ~FlushStage) |
|
||||||
(CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck);
|
(CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck);
|
||||||
// exclusion-tag-start: icache flushdirtycontrols
|
// exclusion-tag-start: icache flushdirtycontrols
|
||||||
assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
|
assign SetDirty = (CurrState == STATE_ACCESS & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
|
||||||
(CurrState == STATE_WRITE_LINE & (CacheRW[0])) |
|
(CurrState == STATE_WRITE_LINE & (CacheRW[0])) |
|
||||||
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
|
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
|
||||||
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty
|
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty
|
||||||
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
|
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
|
||||||
// Flush and eviction controls
|
// Flush and eviction controls
|
||||||
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
|
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
|
||||||
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
|
assign SelVictim = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
|
||||||
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~CacheHit))) |
|
(CurrState == STATE_ACCESS & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~Hit))) |
|
||||||
(CurrState == STATE_WRITE_LINE);
|
(CurrState == STATE_WRITE_LINE);
|
||||||
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) |
|
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) |
|
||||||
(CurrState == STATE_READY & AnyMiss & LineDirty);
|
(CurrState == STATE_ACCESS & AnyMiss & LineDirty);
|
||||||
// coverage off -item e 1 -fecexprrow 1
|
// coverage off -item e 1 -fecexprrow 1
|
||||||
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
|
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
|
||||||
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
|
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
|
||||||
@ -183,29 +183,29 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
|
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
|
||||||
// exclusion-tag-end: icache flushdirtycontrols
|
// exclusion-tag-end: icache flushdirtycontrols
|
||||||
// Bus interface controls
|
// Bus interface controls
|
||||||
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
|
assign CacheBusRW[1] = (CurrState == STATE_ACCESS & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
|
||||||
(CurrState == STATE_FETCH & ~CacheBusAck) |
|
(CurrState == STATE_FETCH & ~CacheBusAck) |
|
||||||
(CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM));
|
(CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM));
|
||||||
|
|
||||||
logic LoadMiss;
|
logic LoadMiss;
|
||||||
assign LoadMiss = (CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
assign LoadMiss = (CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||||
|
|
||||||
assign CacheBusRW[0] = (CurrState == STATE_READY & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
|
assign CacheBusRW[0] = (CurrState == STATE_ACCESS & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
|
||||||
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
|
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
|
||||||
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
|
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
|
||||||
(CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & ~CacheBusAck);
|
(CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & ~CacheBusAck);
|
||||||
|
|
||||||
assign SelAdrData = (CurrState == STATE_READY & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
|
assign SelAdrData = (CurrState == STATE_ACCESS & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
|
||||||
(CurrState == STATE_FETCH) |
|
(CurrState == STATE_FETCH) |
|
||||||
(CurrState == STATE_WRITEBACK) |
|
(CurrState == STATE_WRITEBACK) |
|
||||||
(CurrState == STATE_WRITE_LINE) |
|
(CurrState == STATE_WRITE_LINE) |
|
||||||
resetDelay;
|
resetDelay;
|
||||||
assign SelAdrTag = (CurrState == STATE_READY & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
|
assign SelAdrTag = (CurrState == STATE_ACCESS & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
|
||||||
(CurrState == STATE_FETCH) |
|
(CurrState == STATE_FETCH) |
|
||||||
(CurrState == STATE_WRITEBACK) |
|
(CurrState == STATE_WRITEBACK) |
|
||||||
(CurrState == STATE_WRITE_LINE) |
|
(CurrState == STATE_WRITE_LINE) |
|
||||||
resetDelay;
|
resetDelay;
|
||||||
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
|
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_ADDRESS_SETUP;
|
||||||
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
|
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_ACCESS) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
|
||||||
|
|
||||||
endmodule // cachefsm
|
endmodule // cachefsm
|
||||||
|
33
src/cache/cacheway.sv
vendored
33
src/cache/cacheway.sv
vendored
@ -42,7 +42,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
input logic SetValid, // Set the valid bit in the selected way and set
|
input logic SetValid, // Set the valid bit in the selected way and set
|
||||||
input logic ClearValid, // Clear the valid bit in the selected way and set
|
input logic ClearValid, // Clear the valid bit in the selected way and set
|
||||||
input logic SetDirty, // Set the dirty bit in the selected way and set
|
input logic SetDirty, // Set the dirty bit in the selected way and set
|
||||||
input logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
|
input logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||||
input logic ClearDirty, // Clear the dirty bit in the selected way and set
|
input logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||||
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
||||||
input logic VictimWay, // LRU selected this way as victim to evict
|
input logic VictimWay, // LRU selected this way as victim to evict
|
||||||
@ -68,7 +68,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
logic [LINELEN-1:0] ReadDataLine;
|
logic [LINELEN-1:0] ReadDataLine;
|
||||||
logic [TAGLEN-1:0] ReadTag;
|
logic [TAGLEN-1:0] ReadTag;
|
||||||
logic Dirty;
|
logic Dirty;
|
||||||
logic SelDirty;
|
logic SelecteDirty;
|
||||||
logic SelectedWriteWordEn;
|
logic SelectedWriteWordEn;
|
||||||
logic [LINELEN/8-1:0] FinalByteMask;
|
logic [LINELEN/8-1:0] FinalByteMask;
|
||||||
logic SetValidEN, ClearValidEN;
|
logic SetValidEN, ClearValidEN;
|
||||||
@ -77,33 +77,30 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
logic SetDirtyWay;
|
logic SetDirtyWay;
|
||||||
logic ClearDirtyWay;
|
logic ClearDirtyWay;
|
||||||
logic SelNonHit;
|
logic SelNonHit;
|
||||||
logic SelData;
|
logic SelectedWay;
|
||||||
logic InvalidateCacheDelay;
|
logic InvalidateCacheDelay;
|
||||||
|
|
||||||
if (!READ_ONLY_CACHE) begin:flushlogic
|
if (!READ_ONLY_CACHE) begin:flushlogic
|
||||||
logic FlushWayEn;
|
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelecteDirty);
|
||||||
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelDirty);
|
mux3 #(1) selectedmux(HitWay, FlushWay, VictimWay, {SelVictim, FlushCache}, SelectedWay);
|
||||||
|
|
||||||
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
|
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
|
||||||
// coverage off -item e 1 -fecexprrow 3
|
// coverage off -item e 1 -fecexprrow 3
|
||||||
// nonzero ways will never see FlushCache=0 while FlushWay=1 since FlushWay only advances on a subset of FlushCache assertion cases.
|
// nonzero ways will never see FlushCache=0 while FlushWay=1 since FlushWay only advances on a subset of FlushCache assertion cases.
|
||||||
assign FlushWayEn = FlushWay & FlushCache;
|
|
||||||
assign SelNonHit = FlushWayEn | SelWay;
|
|
||||||
end else begin:flushlogic // no flush operation for read-only caches.
|
end else begin:flushlogic // no flush operation for read-only caches.
|
||||||
assign SelDirty = VictimWay;
|
assign SelecteDirty = VictimWay;
|
||||||
assign SelNonHit = SelWay;
|
mux2 #(1) selectedwaymux(HitWay, SelecteDirty, SelVictim , SelectedWay);
|
||||||
end
|
end
|
||||||
|
|
||||||
mux2 #(1) selectedwaymux(HitWay, SelDirty, SelNonHit , SelData);
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Write Enable demux
|
// Write Enable demux
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
assign SetValidWay = SetValid & SelData;
|
assign SetValidWay = SetValid & SelectedWay;
|
||||||
assign ClearValidWay = ClearValid & SelData; // exclusion-tag: icache ClearValidWay
|
assign ClearValidWay = ClearValid & SelectedWay; // exclusion-tag: icache ClearValidWay
|
||||||
assign SetDirtyWay = SetDirty & SelData; // exclusion-tag: icache SetDirtyWay
|
assign SetDirtyWay = SetDirty & SelectedWay; // exclusion-tag: icache SetDirtyWay
|
||||||
assign ClearDirtyWay = ClearDirty & SelData;
|
assign ClearDirtyWay = ClearDirty & SelectedWay;
|
||||||
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
|
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
|
||||||
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
||||||
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN
|
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN
|
||||||
@ -120,9 +117,9 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
||||||
|
|
||||||
// AND portion of distributed tag multiplexer
|
// AND portion of distributed tag multiplexer
|
||||||
assign TagWay = SelData ? ReadTag : 0; // AND part of AOMux
|
assign TagWay = SelectedWay ? ReadTag : 0; // AND part of AOMux
|
||||||
assign HitDirtyWay = Dirty & ValidWay;
|
assign HitDirtyWay = Dirty & ValidWay;
|
||||||
assign DirtyWay = SelDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
|
assign DirtyWay = SelecteDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
|
||||||
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; // exclusion-tag: dcache HitWay
|
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; // exclusion-tag: dcache HitWay
|
||||||
|
|
||||||
flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay);
|
flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay);
|
||||||
@ -152,7 +149,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
end
|
end
|
||||||
|
|
||||||
// AND portion of distributed read multiplexers
|
// AND portion of distributed read multiplexers
|
||||||
assign ReadDataLineWay = SelData ? ReadDataLine : 0; // AND part of AO mux.
|
assign ReadDataLineWay = SelectedWay ? ReadDataLine : 0; // AND part of AO mux.
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Valid Bits
|
// Valid Bits
|
||||||
|
@ -37,6 +37,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic [P.XLEN-1:0] IEUAdrM, // 2 byte aligned PC in Fetch stage
|
input logic [P.XLEN-1:0] IEUAdrM, // 2 byte aligned PC in Fetch stage
|
||||||
input logic [P.XLEN-1:0] IEUAdrE, // The next IEUAdrM
|
input logic [P.XLEN-1:0] IEUAdrE, // The next IEUAdrM
|
||||||
input logic [2:0] Funct3M, // Size of memory operation
|
input logic [2:0] Funct3M, // Size of memory operation
|
||||||
|
input logic FpLoadStoreM, // Floating point Load or Store
|
||||||
input logic [1:0] MemRWM,
|
input logic [1:0] MemRWM,
|
||||||
input logic [P.LLEN*2-1:0] DCacheReadDataWordM, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
input logic [P.LLEN*2-1:0] DCacheReadDataWordM, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
||||||
input logic CacheBusHPWTStall, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
input logic CacheBusHPWTStall, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
||||||
@ -52,7 +53,6 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic [P.XLEN-1:0] IEUAdrSpillE, // The next PCF for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] IEUAdrSpillE, // The next PCF for one of the two memory addresses of the spill
|
||||||
output logic [P.XLEN-1:0] IEUAdrSpillM, // IEUAdrM for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] IEUAdrSpillM, // IEUAdrM for one of the two memory addresses of the spill
|
||||||
output logic SelSpillE, // During the transition between the two spill operations, the IFU should stall the pipeline
|
output logic SelSpillE, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||||
output logic SelStoreDelay, //*** this is bad. really don't like moving this outside
|
|
||||||
output logic [P.LLEN-1:0] DCacheReadDataWordSpillM, // The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
output logic [P.LLEN-1:0] DCacheReadDataWordSpillM, // The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||||
output logic SpillStallM);
|
output logic SpillStallM);
|
||||||
|
|
||||||
@ -72,6 +72,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
logic [P.XLEN-1:0] IEUAdrIncrementM;
|
logic [P.XLEN-1:0] IEUAdrIncrementM;
|
||||||
|
|
||||||
|
localparam OFFSET_LEN = $clog2(LLENINBYTES);
|
||||||
logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM;
|
logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM;
|
||||||
logic [$clog2(LLENINBYTES)+2:0] ShiftAmount;
|
logic [$clog2(LLENINBYTES)+2:0] ShiftAmount;
|
||||||
logic PotentialSpillM;
|
logic PotentialSpillM;
|
||||||
@ -93,12 +94,15 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// compute misalignement
|
// compute misalignement
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (Funct3M[1:0])
|
case (Funct3M & {FpLoadStoreM, 2'b11})
|
||||||
2'b00: AccessByteOffsetM = 0; // byte access
|
3'b000: AccessByteOffsetM = 0; // byte access
|
||||||
2'b01: AccessByteOffsetM = {2'b00, IEUAdrM[0]}; // half access
|
3'b001: AccessByteOffsetM = {{OFFSET_LEN-1{1'b0}}, IEUAdrM[0]}; // half access
|
||||||
2'b10: AccessByteOffsetM = {1'b0, IEUAdrM[1:0]}; // word access
|
3'b010: AccessByteOffsetM = {{OFFSET_LEN-2{1'b0}}, IEUAdrM[1:0]}; // word access
|
||||||
2'b11: AccessByteOffsetM = IEUAdrM[2:0]; // double access
|
3'b011: if(P.LLEN >= 64) AccessByteOffsetM = {{OFFSET_LEN-3{1'b0}}, IEUAdrM[2:0]}; // double access
|
||||||
default: AccessByteOffsetM = IEUAdrM[2:0];
|
else AccessByteOffsetM = 0; // shouldn't happen
|
||||||
|
3'b100: if(P.LLEN == 128) AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0]; // quad access
|
||||||
|
else AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0];
|
||||||
|
default: AccessByteOffsetM = 0; // shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
case (Funct3M[1:0])
|
case (Funct3M[1:0])
|
||||||
2'b00: PotentialSpillM = 0; // byte access
|
2'b00: PotentialSpillM = 0; // byte access
|
||||||
@ -118,20 +122,17 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (CurrState)
|
case (CurrState)
|
||||||
STATE_READY: if (ValidSpillM & ~MemRWM[0]) NextState = STATE_SPILL; // load spill
|
STATE_READY: if (ValidSpillM) NextState = STATE_SPILL; // load spill
|
||||||
else if(ValidSpillM) NextState = STATE_STORE_DELAY; // store spill
|
|
||||||
else NextState = STATE_READY; // no spill
|
else NextState = STATE_READY; // no spill
|
||||||
STATE_SPILL: if(StallM) NextState = STATE_SPILL;
|
STATE_SPILL: if(StallM) NextState = STATE_SPILL;
|
||||||
else NextState = STATE_READY;
|
else NextState = STATE_READY;
|
||||||
STATE_STORE_DELAY: NextState = STATE_SPILL;
|
|
||||||
default: NextState = STATE_READY;
|
default: NextState = STATE_READY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
assign SelSpillM = (CurrState == STATE_SPILL | CurrState == STATE_STORE_DELAY);
|
assign SelSpillM = CurrState == STATE_SPILL;
|
||||||
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall) | (CurrState == STATE_STORE_DELAY);
|
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall);
|
||||||
assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM;
|
assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM;
|
||||||
assign SelStoreDelay = (CurrState == STATE_STORE_DELAY); // *** Can this be merged into the PreLSURWM logic?
|
|
||||||
assign SpillStallM = SelSpillE;
|
assign SpillStallM = SelSpillE;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -143,7 +143,6 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [(P.LLEN-1)/8:0] ByteMaskExtendedM; // Selects which bytes within a word to write
|
logic [(P.LLEN-1)/8:0] ByteMaskExtendedM; // Selects which bytes within a word to write
|
||||||
logic [1:0] MemRWSpillM;
|
logic [1:0] MemRWSpillM;
|
||||||
logic SpillStallM;
|
logic SpillStallM;
|
||||||
logic SelStoreDelay;
|
|
||||||
|
|
||||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||||
@ -164,12 +163,11 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
|
flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
|
||||||
if(MISALIGN_SUPPORT) begin : ziccslm_align
|
if(MISALIGN_SUPPORT) begin : ziccslm_align
|
||||||
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
|
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
|
||||||
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M,
|
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM,
|
||||||
.MemRWM,
|
.MemRWM,
|
||||||
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
|
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
|
||||||
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
|
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
|
||||||
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM,
|
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM);
|
||||||
.SelStoreDelay);
|
|
||||||
assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
|
assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
|
||||||
assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
|
assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
|
||||||
end else begin : no_ziccslm_align
|
end else begin : no_ziccslm_align
|
||||||
@ -180,7 +178,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign ByteMaskSpillM = ByteMaskM;
|
assign ByteMaskSpillM = ByteMaskM;
|
||||||
assign LSUWriteDataSpillM = LSUWriteDataM;
|
assign LSUWriteDataSpillM = LSUWriteDataM;
|
||||||
assign MemRWSpillM = MemRWM;
|
assign MemRWSpillM = MemRWM;
|
||||||
assign {SpillStallM, SelStoreDelay} = 0;
|
assign {SpillStallM} = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if(P.ZICBOZ_SUPPORTED) begin : cboz
|
if(P.ZICBOZ_SUPPORTED) begin : cboz
|
||||||
@ -333,7 +331,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
|
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
|
||||||
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(CACHEWORDLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
|
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(CACHEWORDLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
|
||||||
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
|
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
|
||||||
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM),
|
.CacheRW(CacheRWM),
|
||||||
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
|
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
|
||||||
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
|
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
|
||||||
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW,
|
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW,
|
||||||
|
@ -80,7 +80,7 @@ module privdec import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
if (P.U_SUPPORTED) begin:wfi
|
if (P.U_SUPPORTED) begin:wfi
|
||||||
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
|
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
|
||||||
assign WFICountPlus1 = wfiM ? 0 : WFICount + 1; // restart counting on WFI
|
assign WFICountPlus1 = wfiM ? WFICount + 1 : '0; // restart counting on WFI
|
||||||
flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
|
flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
|
||||||
// coverage off -item e 1 -fecexprrow 1
|
// coverage off -item e 1 -fecexprrow 1
|
||||||
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
|
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
|
||||||
|
Loading…
Reference in New Issue
Block a user