diff --git a/src/cache/cache.sv b/src/cache/cache.sv index 43e58083b..bf751bc31 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -98,7 +98,8 @@ module cache import cvw::*; #(parameter cvw_t P, logic CacheEn; logic [LINELEN/8-1:0] LineByteMask; logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr; - + logic ZeroCacheLine; + logic [LINELEN-1:0] PreLineWriteData; genvar index; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -116,7 +117,7 @@ module cache import cvw::*; #(parameter cvw_t P, // 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]( .clk, .reset, .CacheEn, .CacheSet, .PAdr, .LineWriteData, .LineByteMask, - .SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelWriteback, .VictimWay, + .SetValid, .ClearValid, .SetDirty, .ClearDirty, .ZeroCacheLine, .SelWriteback, .VictimWay, .FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .TagWay, .FlushStage, .InvalidateCache); // Select victim way for associative caches @@ -160,6 +161,11 @@ module cache import cvw::*; #(parameter cvw_t P, ///////////////////////////////////////////////////////////////////////////////////////////// // Write Path ///////////////////////////////////////////////////////////////////////////////////////////// + if(P.ZICBOZ_SUPPORTED) begin : cboz_supported + mux2 #(LINELEN) WriteDataMux(FetchBuffer, '0, ZeroCacheLine, PreLineWriteData); + end else begin + assign PreLineWriteData = FetchBuffer; + end if(!READ_ONLY_CACHE) begin:WriteSelLogic logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded; logic [LINELEN/8-1:0] DemuxedByteMask, FetchBufferByteSel; @@ -174,14 +180,14 @@ module cache import cvw::*; #(parameter cvw_t P, // Merge write data into fetched cache line for store miss for(index = 0; index < LINELEN/8; index++) begin mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]), - .d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index])); + .d1(PreLineWriteData[8*index+7:8*index]), .s(FetchBufferByteSel[index] | ZeroCacheLine), .y(LineWriteData[8*index+7:8*index])); end assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0; end else begin:WriteSelLogic // No need for this mux if the cache does not handle writes. - assign LineWriteData = FetchBuffer; + assign LineWriteData = PreLineWriteData; assign LineByteMask = '1; end @@ -216,7 +222,7 @@ module cache import cvw::*; #(parameter cvw_t P, .FlushStage, .CacheRW, .CacheAtomic, .Stall, .CacheHit, .LineDirty, .CacheStall, .CacheCommitted, .CacheMiss, .CacheAccess, .SelAdr, - .ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback, .SelFlush, + .ClearDirty, .SetDirty, .SetValid, .ClearValid, .ZeroCacheLine, .SelWriteback, .SelFlush, .FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst, .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer, .InvalidateCache, .CMOp, .CacheEn, .LRUWriteEn); diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index 9d819f000..ce044569b 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -59,6 +59,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P, output logic ClearValid, // Clear the valid bit in the selected way and set output logic SetDirty, // Set 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 SelWriteback, // Overrides cached tag check to select a specific way and set for writeback output logic LRUWriteEn, // Update the LRU state output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr @@ -113,14 +114,14 @@ module cachefsm import cvw::*; #(parameter cvw_t P, else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement else if(AnyMiss | CMOp[2] | CMOp[3]) /* & LineDirty */NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement else NextState = STATE_READY; - STATE_FETCH: if(CacheBusAck & ~(CMOp[2] | CMOp[3]))) NextState = STATE_WRITE_LINE; - else (CacheBusAck) /* CMOp[2] | CMOp[3] */ NextState = STATE_READY; + STATE_FETCH: if(CacheBusAck & ~(CMOp[2] | CMOp[3])) NextState = STATE_WRITE_LINE; + else if(CacheBusAck) /* CMOp[2] | CMOp[3] */ NextState = STATE_READY; else NextState = STATE_FETCH; STATE_WRITE_LINE: NextState = STATE_READ_HOLD; STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; else NextState = STATE_READY; // exclusion-tag-start: icache case - STATE_WRITEBACK: if(CacheBusAck & (CMop[2] | CMOp[3])) NextState = STATE_READY; + STATE_WRITEBACK: if(CacheBusAck & (CMOp[2] | CMOp[3])) NextState = STATE_READY; else if(CacheBusAck) NextState = STATE_FETCH; 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. @@ -144,19 +145,20 @@ module cachefsm import cvw::*; #(parameter cvw_t P, (CurrState == STATE_FLUSH) | (CurrState == STATE_FLUSH_WRITEBACK); // write enables internal to cache - assign SetValid = CurrState == STATE_WRITE_LINE; + assign SetValid = CurrState == STATE_WRITE_LINE | (CurrState == STATE_READY & CMOp[3]); assign ClearValid = P.ZICBOM_SUPPORTED & ((CurrState == STATE_READY & CMOp[0]) | (CurrState == STATE_WRITEBACK & CMOp[1])); // coverage off -item e 1 -fecexprrow 8 assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) | (CurrState == STATE_WRITE_LINE) & ~FlushStage; // exclusion-tag-start: icache flushdirtycontrols - assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) | // exclusion-tag: icache SetDirty + assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOp[3])) | // exclusion-tag: icache SetDirty (CurrState == STATE_WRITE_LINE & (CacheRW[0])); 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. // Flush and eviction controls - (P.ZICBOM_SUPPORTED & CurrState == STATE_WRITEBACK & (CMOp[1] | CMOp[2] | CMOp[3])); + (P.ZICBOM_SUPPORTED & CurrState == STATE_WRITEBACK & (CMOp[1] | CMOp[2] | CMOp[3])); + assign ZeroCacheLine = CurrState == STATE_READY & CMOp[3]; assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | (CurrState == STATE_READY & AnyMiss & LineDirty); diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 240e66859..fb361977a 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -40,6 +40,7 @@ module cacheway import cvw::*; #(parameter cvw_t P, 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 SetDirty, // Set the dirty bit in the selected way and set + 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 SelWriteback, // Overrides cached tag check to select a specific way and set for writeback input logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr @@ -75,7 +76,13 @@ module cacheway import cvw::*; #(parameter cvw_t P, logic ClearDirtyWay; logic SelNonHit; logic SelData; - + logic SelNotHit2; + + if (P.ZICBOM_SUPPORTED) begin : cbologic + assign SelNotHit2 = SetValid & ~(ZeroCacheLine & HitWay); + end else begin : cbologic + assign SelNotHit2 = SetValid; + end if (!READ_ONLY_CACHE) begin:flushlogic logic FlushWayEn; @@ -86,10 +93,10 @@ module cacheway import cvw::*; #(parameter cvw_t P, // 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. assign FlushWayEn = FlushWay & SelFlush; - assign SelNonHit = FlushWayEn | SetValid | SelWriteback; + assign SelNonHit = FlushWayEn | SelNotHit2 | SelWriteback; end else begin:flushlogic // no flush operation for read-only caches. assign SelTag = VictimWay; - assign SelNonHit = SetValid; + assign SelNonHit = SelNotHit2; end mux2 #(1) selectedwaymux(HitWay, SelTag, SelNonHit , SelData);