Might have working cbo clean and flush instructions.

This commit is contained in:
Ross Thompson 2023-08-18 14:48:21 -05:00
parent 8c7eafffad
commit b842fdb863
3 changed files with 41 additions and 21 deletions

11
src/cache/cache.sv vendored
View File

@ -90,6 +90,8 @@ module cache import cvw::*; #(parameter cvw_t P,
logic [NUMWAYS-1:0] FlushWay, NextFlushWay; logic [NUMWAYS-1:0] FlushWay, NextFlushWay;
logic FlushWayCntEn; logic FlushWayCntEn;
logic SelWriteback; logic SelWriteback;
logic SelCMOWriteback;
logic SelBothWriteback;
logic LRUWriteEn; logic LRUWriteEn;
logic SelFlush; logic SelFlush;
logic ResetOrFlushCntRst; logic ResetOrFlushCntRst;
@ -116,8 +118,8 @@ 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, .CacheSet, .PAdr, .LineWriteData, .LineByteMask, .clk, .reset, .CacheEn, .CMOp, .CacheSet, .PAdr, .LineWriteData, .LineByteMask,
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .ZeroCacheLine, .SelWriteback, .VictimWay, .SetValid, .ClearValid, .SetDirty, .ClearDirty, .ZeroCacheLine, .SelWriteback, .SelCMOWriteback, .VictimWay,
.FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .TagWay, .FlushStage, .InvalidateCache); .FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .TagWay, .FlushStage, .InvalidateCache);
// Select victim way for associative caches // Select victim way for associative caches
@ -153,10 +155,11 @@ module cache import cvw::*; #(parameter cvw_t P,
.PAdr(WordOffsetAddr), .ReadDataLine, .ReadDataWord); .PAdr(WordOffsetAddr), .ReadDataLine, .ReadDataWord);
// Bus address for fetch, writeback, or flush writeback // Bus address for fetch, writeback, or flush writeback
assign SelBothWriteback = SelWriteback | SelCMOWriteback;
mux3 #(PA_BITS) CacheBusAdrMux(.d0({PAdr[PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), mux3 #(PA_BITS) CacheBusAdrMux(.d0({PAdr[PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}),
.s({SelFlush, SelWriteback}), .y(CacheBusAdr)); .s({SelFlush, SelBothWriteback}), .y(CacheBusAdr));
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Write Path // Write Path
@ -222,7 +225,7 @@ module cache import cvw::*; #(parameter cvw_t P,
.FlushStage, .CacheRW, .CacheAtomic, .Stall, .FlushStage, .CacheRW, .CacheAtomic, .Stall,
.CacheHit, .LineDirty, .CacheStall, .CacheCommitted, .CacheHit, .LineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdr, .CacheMiss, .CacheAccess, .SelAdr,
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .ZeroCacheLine, .SelWriteback, .SelFlush, .ClearDirty, .SetDirty, .SetValid, .ClearValid, .ZeroCacheLine, .SelWriteback, .SelCMOWriteback, .SelFlush,
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst, .FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer, .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
.InvalidateCache, .CMOp, .CacheEn, .LRUWriteEn); .InvalidateCache, .CMOp, .CacheEn, .LRUWriteEn);

41
src/cache/cachefsm.sv vendored
View File

@ -61,6 +61,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 ZeroCacheLine, // Write zeros to all bytes of cacheline output logic ZeroCacheLine, // Write zeros to all bytes of cacheline
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 SelCMOWriteback, // Overrides cached tag check to select a specific way and set for writeback for both data and tag
output logic LRUWriteEn, // Update the LRU state output logic LRUWriteEn, // Update the LRU state
output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
output logic FlushAdrCntEn, // Enable the counter for Flush Adr output logic FlushAdrCntEn, // Enable the counter for Flush Adr
@ -83,7 +84,11 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM
// flush cache // flush cache
STATE_FLUSH, STATE_FLUSH,
STATE_FLUSH_WRITEBACK} statetype; STATE_FLUSH_WRITEBACK,
// CMO states
STATE_CMO_WRITEBACK,
STATE_CMO_DONE
} statetype;
statetype CurrState, NextState; statetype CurrState, NextState;
@ -112,17 +117,17 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH;
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 | CMOp[1] | CMOp[2]) /* & LineDirty */NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement else if(AnyMiss) /* & LineDirty */ NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
else if((CMOp[1] | CMOp[2]) & CacheHit) NextState = STATE_CMO_WRITEBACK;
else NextState = STATE_READY; else NextState = STATE_READY;
STATE_FETCH: if(CacheBusAck & ~(CMOp[1] | CMOp[2])) NextState = STATE_WRITE_LINE; STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else if(CacheBusAck) /* CMOp[1] | CMOp[2] */ NextState = STATE_READY; else if(CacheBusAck) NextState = STATE_READY;
else NextState = STATE_FETCH; else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD; STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
else NextState = STATE_READY; else NextState = STATE_READY;
// exclusion-tag-start: icache case // exclusion-tag-start: icache case
STATE_WRITEBACK: if(CacheBusAck & (CMOp[1] | CMOp[2])) NextState = STATE_READ_HOLD; STATE_WRITEBACK: if(CacheBusAck) NextState = STATE_FETCH;
else if(CacheBusAck) NextState = STATE_FETCH;
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;
@ -131,36 +136,42 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
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_READ_HOLD;
else NextState = STATE_FLUSH_WRITEBACK; else NextState = STATE_FLUSH_WRITEBACK;
STATE_CMO_WRITEBACK: if(CacheBusAck & (CMOp[1] | CMOp[2])) NextState = STATE_CMO_DONE;
else NextState = STATE_CMO_WRITEBACK;
// exclusion-tag-end: icache case // exclusion-tag-end: icache case
default: NextState = STATE_READY; default: NextState = STATE_READY;
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_READY) & ~(READ_ONLY_CACHE & (CurrState == STATE_READ_HOLD | CurrState == STATE_CMO_DONE));
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss | CMOp[1] | CMOp[2])) | // exclusion-tag: icache StallStates assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss | CMOp[1] | CMOp[2])) | // 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.
(CurrState == STATE_FLUSH) | (CurrState == STATE_FLUSH) |
(CurrState == STATE_FLUSH_WRITEBACK); (CurrState == STATE_FLUSH_WRITEBACK) |
(CurrState == STATE_CMO_WRITEBACK);
// write enables internal to cache // write enables internal to cache
assign SetValid = CurrState == STATE_WRITE_LINE | (CurrState == STATE_READY & CMOp[3]); assign SetValid = CurrState == STATE_WRITE_LINE |
(CurrState == STATE_READY & CMOp[3]); // *** RT: NOT completely right has to be a hit
assign ClearValid = P.ZICBOM_SUPPORTED & ((CurrState == STATE_READY & CMOp[0]) | assign ClearValid = P.ZICBOM_SUPPORTED & ((CurrState == STATE_READY & CMOp[0]) |
(CurrState == STATE_WRITEBACK & CMOp[1])); (CurrState == STATE_CMO_DONE & CMOp[2]));
// coverage off -item e 1 -fecexprrow 8 // coverage off -item e 1 -fecexprrow 8
assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) | assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) |
(CurrState == STATE_WRITE_LINE) & ~FlushStage; (CurrState == STATE_WRITE_LINE) & ~FlushStage;
// exclusion-tag-start: icache flushdirtycontrols // exclusion-tag-start: icache flushdirtycontrols
assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOp[3])) | // exclusion-tag: icache SetDirty assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOp[3])) | // exclusion-tag: icache SetDirty *** NOT completely right has to be a hit for CMOp[3]
(CurrState == STATE_WRITE_LINE & (CacheRW[0])); (CurrState == STATE_WRITE_LINE & (CacheRW[0]));
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
(P.ZICBOM_SUPPORTED & CurrState == STATE_WRITEBACK & (CMOp[1] | CMOp[2] | CMOp[3])); (P.ZICBOM_SUPPORTED & CurrState == STATE_CMO_DONE & (CMOp[1] | CMOp[2]));
assign ZeroCacheLine = CurrState == STATE_READY & CMOp[3]; assign ZeroCacheLine = CurrState == STATE_READY & CMOp[3]; // *** RT: NOT completely right
assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_READY & AnyMiss & LineDirty); (CurrState == STATE_READY & AnyMiss & LineDirty);
assign SelCMOWriteback = CurrState == STATE_CMO_WRITEBACK;
assign SelFlush = (CurrState == STATE_READY & FlushCache) | assign SelFlush = (CurrState == STATE_READY & FlushCache) |
(CurrState == STATE_FLUSH) | (CurrState == STATE_FLUSH) |
@ -180,12 +191,14 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
(CurrState == STATE_WRITEBACK & CacheBusAck); (CurrState == STATE_WRITEBACK & CacheBusAck);
assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | // exclusion-tag: icache CacheBusW assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | // exclusion-tag: icache CacheBusW
(CurrState == STATE_WRITEBACK & ~CacheBusAck) | (CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck); (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
(P.ZICBOM_SUPPORTED & CurrState == STATE_CMO_WRITEBACK & (CMOp[1] | CMOp[2]) & ~CacheBusAck);
assign SelAdr = (CurrState == STATE_READY & (CacheRW[0] | AnyMiss | (|CMOp))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed assign SelAdr = (CurrState == STATE_READY & (CacheRW[0] | AnyMiss | (|CMOp))) | // 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) |
(CurrState == STATE_CMO_WRITEBACK) |
resetDelay; resetDelay;
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD; assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn

View File

@ -33,6 +33,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations) input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations)
input logic [3:0] CMOp, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
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 [$clog2(NUMLINES)-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr input logic [$clog2(NUMLINES)-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [PA_BITS-1:0] PAdr, // Physical address input logic [PA_BITS-1:0] PAdr, // Physical address
@ -43,6 +44,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
input logic ZeroCacheLine, // Write zeros to all bytes of a cache line input logic ZeroCacheLine, // Write zeros to all bytes of a cache line
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 SelWriteback, // Overrides cached tag check to select a specific way and set for writeback input logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
input logic SelCMOWriteback, // Overrides cached tag check to select a specific way and set for writeback for both data and tag
input logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr input logic SelFlush, // [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
input logic FlushWay, // This way is selected for flush and possible writeback if dirty input logic FlushWay, // This way is selected for flush and possible writeback if dirty
@ -78,7 +80,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
logic SelData; logic SelData;
logic SelNotHit2; logic SelNotHit2;
if (P.ZICBOM_SUPPORTED) begin : cbologic if (P.ZICBOZ_SUPPORTED) begin : cbologic
assign SelNotHit2 = SetValid & ~(ZeroCacheLine & HitWay); assign SelNotHit2 = SetValid & ~(ZeroCacheLine & HitWay);
end else begin : cbologic end else begin : cbologic
assign SelNotHit2 = SetValid; assign SelNotHit2 = SetValid;
@ -93,7 +95,9 @@ module cacheway import cvw::*; #(parameter cvw_t P,
// coverage off -item e 1 -fecexprrow 3 // coverage off -item e 1 -fecexprrow 3
// nonzero ways will never see SelFlush=0 while FlushWay=1 since FlushWay only advances on a subset of SelFlush assertion cases. // nonzero ways will never see SelFlush=0 while FlushWay=1 since FlushWay only advances on a subset of SelFlush assertion cases.
assign FlushWayEn = FlushWay & SelFlush; assign FlushWayEn = FlushWay & SelFlush;
// *** RT: This is slopy. I should refactor to have the fsm issue two types of writeback commands
assign SelNonHit = FlushWayEn | SelNotHit2 | SelWriteback; assign SelNonHit = FlushWayEn | SelNotHit2 | SelWriteback;
//assign SelNonHit = FlushWayEn | SelNotHit2 | SelWriteback;
end else begin:flushlogic // no flush operation for read-only caches. end else begin:flushlogic // no flush operation for read-only caches.
assign SelTag = VictimWay; assign SelTag = VictimWay;
assign SelNonHit = SelNotHit2; assign SelNonHit = SelNotHit2;
@ -124,7 +128,7 @@ 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 = SelTag ? ReadTag : '0; // AND part of AOMux assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux
assign DirtyWay = SelTag & Dirty & ValidWay; assign DirtyWay = SelTag & Dirty & ValidWay;
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]); assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]);