Merge pull request #651 from ross144/main

Updates to cache logic.  Code quality improvements.
This commit is contained in:
David Harris 2024-03-06 13:45:01 -08:00 committed by GitHub
commit af1ecfc30d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 105 additions and 109 deletions

View File

@ -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

View File

@ -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"

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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;
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -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,

View File

@ -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.