From 3fc6bb0c40a44c50eaba12d96dedec5fc1c098ec Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Tue, 11 Apr 2023 16:59:11 -0700 Subject: [PATCH 01/20] Exclude (FlushStage & SetValidWay) condition for RO caches Spent a long time trying to find a way to see if this condition was possible, only to become relativly convinced that it isn't. Basically, since RO cache writes only happen after a long period of stall for the bus access, there's no way a flushD can be active at the same time as a RO cache write. TrapM causes a FlushD, but interrupts are gated by the "commited" logic and the exception pipeline stalls. I feel like its worth keeping the logic to be safe so I've chosen to exclude it rather than explicitely remove it. --- src/cache/cacheway.sv | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 174b82c59..568e626e5 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -101,14 +101,21 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, if (!READ_ONLY_CACHE) begin assign SetDirtyWay = SetDirty & SelData; assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; + assign SetValidEN = SetValidWay & ~FlushStage; end else begin + // Don't cover FlushStage assertion during SetValidWay. + // it's not explicitely gated anywhere, but for read-only caches, + // there's no way that a FlushD can happen during the write stage + // of a fetch. + // coverage off -item e 1 -fecexprrow 4 assign SelectedWriteWordEn = SetValidWay & ~FlushStage; + // coverage off -item e 1 -fecexprrow 4 + assign SetValidEN = SetValidWay & ~FlushStage; end // If writing the whole line set all write enables to 1, else only set the correct word. assign FinalByteMask = SetValidWay ? '1 : LineByteMask; // OR - assign SetValidEN = SetValidWay & ~FlushStage; ///////////////////////////////////////////////////////////////////////////////////////////// // Tag Array From 6dce58125b6c7459b627071711cf6885deaa1b9b Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Tue, 11 Apr 2023 17:10:09 -0700 Subject: [PATCH 02/20] Remove FlushStage Logic from CacheLRU For coverage. LRUWriteEn is gated by FlushStage in cache.sv, so removing the signal completely avoids future confusion. Update cache.sv to reflect cacheLRU edit. --- src/cache/cache.sv | 2 +- src/cache/cacheLRU.sv | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cache/cache.sv b/src/cache/cache.sv index c01c714b1..9854152e2 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -122,7 +122,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // Select victim way for associative caches if(NUMWAYS > 1) begin:vict cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMLINES) cacheLRU( - .clk, .reset, .CacheEn, .FlushStage, .HitWay, .ValidWay, .VictimWay, .CacheSet, .LRUWriteEn(LRUWriteEn & ~FlushStage), + .clk, .reset, .CacheEn, .HitWay, .ValidWay, .VictimWay, .CacheSet, .LRUWriteEn(LRUWriteEn & ~FlushStage), .SetValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache, .FlushCache); end else assign VictimWay = 1'b1; // one hot. diff --git a/src/cache/cacheLRU.sv b/src/cache/cacheLRU.sv index 1e7101365..d8de983f7 100644 --- a/src/cache/cacheLRU.sv +++ b/src/cache/cacheLRU.sv @@ -32,8 +32,7 @@ module cacheLRU #(parameter NUMWAYS = 4, SETLEN = 9, OFFSETLEN = 5, NUMLINES = 128) ( input logic clk, - input logic reset, - input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations) + input logic reset, 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] ValidWay, // Which ways for a particular set are valid, ignores tag @@ -134,11 +133,9 @@ module cacheLRU always_ff @(posedge clk) begin if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; if(CacheEn) begin - // if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; - if (LRUWriteEn & ~FlushStage) begin + if(LRUWriteEn) LRUMemory[PAdr] <= NextLRU; - end - if(LRUWriteEn & ~FlushStage & (PAdr == CacheSet)) + if(LRUWriteEn & (PAdr == CacheSet)) CurrLRU <= #1 NextLRU; else CurrLRU <= #1 LRUMemory[CacheSet]; From 214abc7006e48eb2340aa56f00a088354d0c6bcb Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Tue, 11 Apr 2023 23:05:04 -0700 Subject: [PATCH 03/20] Make AdrSelMux and CacheBusAdrMux mux2 if READ_ONLY_CACHE Some address options are only used in the D$ case. --- src/cache/cache.sv | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cache/cache.sv b/src/cache/cache.sv index 9854152e2..19cc84c51 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -73,7 +73,6 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE logic SelAdr; - logic [1:0] AdrSelMuxSel; logic [SETLEN-1:0] CacheSet; logic [LINELEN-1:0] LineWriteData; logic ClearDirty, SetDirty, SetValid; @@ -109,10 +108,18 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // and FlushAdr when handling D$ flushes // The icache must update to the newest PCNextF on flush as it is probably a trap. Trap // sets PCNextF to XTVEC and the icache must start reading the instruction. - assign AdrSelMuxSel = {SelFlush, ((SelAdr | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))}; - mux3 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr, + if (!READ_ONLY_CACHE) begin + logic [1:0] AdrSelMuxSel; + assign AdrSelMuxSel = {SelFlush, SelAdr | SelHPTW}; + mux3 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr, AdrSelMuxSel, CacheSet); - + end + else begin + logic AdrSelMuxSel; + assign AdrSelMuxSel = ((SelAdr | SelHPTW) & ~FlushStage); + mux2 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], + AdrSelMuxSel, CacheSet); + end // Array of cache ways, along with victim, hit, dirty, and read merging logic cacheway #(NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0]( .clk, .reset, .CacheEn, .CacheSet, .PAdr, .LineWriteData, .LineByteMask, @@ -152,11 +159,14 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE .PAdr(WordOffsetAddr), .ReadDataLine, .ReadDataWord); // Bus address for fetch, writeback, or flush writeback - mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), - .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); - + if (!READ_ONLY_CACHE) + mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), + .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), + .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), + .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); + else + assign CacheBusAdr = {PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}; + ///////////////////////////////////////////////////////////////////////////////////////////// // Write Path ///////////////////////////////////////////////////////////////////////////////////////////// From 1ce2ab5daa7cd8d7b708894d6443bc00916c6905 Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Tue, 11 Apr 2023 23:05:56 -0700 Subject: [PATCH 04/20] Coverage and readability improvements to LRUUpdate logic The genvar stuff was switched to readable names to make it easier to understand for the first time. In the LRUUpdate logic for loop, a special case was added for simpler logic in the case of the root node, to hit coverage. --- src/cache/cacheLRU.sv | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/cache/cacheLRU.sv b/src/cache/cacheLRU.sv index d8de983f7..5f1c199a9 100644 --- a/src/cache/cacheLRU.sv +++ b/src/cache/cacheLRU.sv @@ -89,16 +89,26 @@ module cacheLRU assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{WayEncoded[row]}}; end - genvar r, a, s; + genvar node; assign LRUUpdate[NUMWAYS-2] = '1; - for(s = NUMWAYS-2; s >= NUMWAYS/2; s--) begin : enables - localparam p = NUMWAYS - s - 1; - localparam g = log2(p); - localparam t0 = s - p; - localparam t1 = t0 - 1; - localparam r = LOGNUMWAYS - g; - assign LRUUpdate[t0] = LRUUpdate[s] & ~WayEncoded[r]; - assign LRUUpdate[t1] = LRUUpdate[s] & WayEncoded[r]; + for(node = NUMWAYS-2; node >= NUMWAYS/2; node--) begin : enables + localparam ctr = NUMWAYS - node - 1; + localparam ctr_depth = log2(ctr); + localparam lchild = node - ctr; + localparam rchild = lchild - 1; + localparam r = LOGNUMWAYS - ctr_depth; + + // the child node will be updated if its parent was updated and + // the WayEncoded bit was the correct value. + // The if statement is only there for coverage since LRUUpdate[root] is always 1. + if (node == NUMWAYS-2) begin + assign LRUUpdate[lchild] = ~WayEncoded[r]; + assign LRUUpdate[rchild] = WayEncoded[r]; + end + else begin + assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r]; + assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r]; + end end // The root node of the LRU tree will always be selected in LRUUpdate. No mux needed. @@ -106,15 +116,15 @@ module cacheLRU mux2 #(1) LRUMuxes[NUMWAYS-3:0](CurrLRU[NUMWAYS-3:0], ~WayExpanded[NUMWAYS-3:0], LRUUpdate[NUMWAYS-3:0], NextLRU[NUMWAYS-3:0]); // Compute next victim way. - for(s = NUMWAYS-2; s >= NUMWAYS/2; s--) begin - localparam t0 = 2*s - NUMWAYS; + for(node = NUMWAYS-2; node >= NUMWAYS/2; node--) begin + localparam t0 = 2*node - NUMWAYS; localparam t1 = t0 + 1; - assign Intermediate[s] = CurrLRU[s] ? Intermediate[t0] : Intermediate[t1]; + assign Intermediate[node] = CurrLRU[node] ? Intermediate[t0] : Intermediate[t1]; end - for(s = NUMWAYS/2-1; s >= 0; s--) begin - localparam int0 = (NUMWAYS/2-1-s)*2; + for(node = NUMWAYS/2-1; node >= 0; node--) begin + localparam int0 = (NUMWAYS/2-1-node)*2; localparam int1 = int0 + 1; - assign Intermediate[s] = CurrLRU[s] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0]; + assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0]; end logic [NUMWAYS-1:0] FirstZero; From 729f81a0df9de145ec82ac3780809d2ff8fdead2 Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Wed, 12 Apr 2023 00:48:06 -0700 Subject: [PATCH 05/20] refactor cachefsm to get full coverage I had to exclude i$ states in coverage-exclusions-rv64gc.do, but it's referred to by scope, which should be pretty robust --- sim/coverage-exclusions-rv64gc.do | 6 + src/cache/cachefsm.sv | 195 +++++++++++++++++++----------- 2 files changed, 128 insertions(+), 73 deletions(-) diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index d58e4c514..3e880b502 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -32,6 +32,12 @@ # This is ugly to exlcude the whole file - is there a better option? // coverage off isn't working coverage exclude -srcfile lzc.sv +# Exclude D$ states from coverage in the I$ instance of cachefsm. +# This is cleaner than trying to set an I$-specific pragma in cachefsm.sv +# Also exclude the write line to ready transition for the I$ since we can't get a flush +# during this operation. +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY ###################### # Toggle exclusions diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index d1d54097e..a42176325 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -86,18 +86,25 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( statetype CurrState, NextState; - assign AMO = CacheAtomic[1] & (&CacheRW); - assign StoreAMO = AMO | CacheRW[0]; + // no atomic operations on i$ + if (!READ_ONLY_CACHE) begin + assign AMO = CacheAtomic[1] & (&CacheRW); + assign StoreAMO = AMO | CacheRW[0]; + assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache; + assign AnyUpdateHit = StoreAMO & CacheHit; + assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); + assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; // for performance counter + end + else begin + assign AnyMiss = CacheRW[1] & ~CacheHit & ~InvalidateCache; + assign AnyUpdateHit = 0; // todo clear all RO cache of usage of this logic + assign AnyHit = CacheRW[1] & CacheHit; + assign CacheAccess = CacheRW[1] & CurrState == STATE_READY; // for performance counter + end - assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache; - assign AnyUpdateHit = (StoreAMO) & CacheHit; - assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); + assign CacheMiss = CacheAccess & ~CacheHit; // for performance counter assign FlushFlag = FlushAdrFlag & FlushWayFlag; - // outputs for the performance counters. - assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; - assign CacheMiss = CacheAccess & ~CacheHit; - // special case on reset. When the fsm first exists reset the // PCNextF will no longer be pointing to the correct address. // But PCF will be the reset vector. @@ -106,77 +113,119 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( always_ff @(posedge clk) if (reset | FlushStage) CurrState <= #1 STATE_READY; else CurrState <= #1 NextState; - - always_comb begin - NextState = STATE_READY; - case (CurrState) - STATE_READY: if(InvalidateCache) NextState = STATE_READY; - else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; - else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; - else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK; - else NextState = STATE_READY; - STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; - else NextState = STATE_FETCH; - STATE_WRITE_LINE: NextState = STATE_READ_HOLD; - STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; - else NextState = STATE_READY; - STATE_WRITEBACK: 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. - STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; - else if (FlushFlag) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH; - STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; - else if(CacheBusAck) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH_WRITEBACK; - default: NextState = STATE_READY; - endcase - end + + // seperating NextState logic by ro vs rw cache results in code duplication but this is needed to hit coverage. + if (!READ_ONLY_CACHE) + always_comb begin + NextState = STATE_READY; + case (CurrState) + STATE_READY: if(InvalidateCache) NextState = STATE_READY; + else if(FlushCache) NextState = STATE_FLUSH; + else if(AnyMiss & ~LineDirty) NextState = STATE_FETCH; + else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK; + else NextState = STATE_READY; + STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; + else NextState = STATE_FETCH; + STATE_WRITE_LINE: NextState = STATE_READ_HOLD; + STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; + else NextState = STATE_READY; + STATE_WRITEBACK: 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. + STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; + else if (FlushFlag) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH; + STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; + else if(CacheBusAck) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH_WRITEBACK; + default: NextState = STATE_READY; + endcase + end // always_comb + else // READ_ONLY_CACHE + always_comb begin + NextState = STATE_READY; + case (CurrState) + STATE_READY: if(InvalidateCache) NextState = STATE_READY; + else if(AnyMiss) NextState = STATE_FETCH; + else NextState = STATE_READY; + STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; + else NextState = STATE_FETCH; + STATE_WRITE_LINE: NextState = STATE_READ_HOLD; + STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; + else NextState = STATE_READY; + default: NextState = STATE_READY; + endcase // case (CurrState) + end // always_comb // com back to CPU - assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD); - assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | - (CurrState == STATE_FETCH) | - (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_FLUSH) | + if (!READ_ONLY_CACHE) begin + assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | + (CurrState == STATE_FETCH) | + (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_FLUSH) | + (CurrState == STATE_FLUSH_WRITEBACK); + assign CacheCommitted = CurrState != STATE_READY; + assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // changes if store delay hazard removed + (CurrState == STATE_FETCH) | + (CurrState == STATE_WRITEBACK) | + (CurrState == STATE_WRITE_LINE) | + resetDelay; + assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) | + (CurrState == STATE_WRITE_LINE & (StoreAMO)); + assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) | + (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 + assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | + (CurrState == STATE_READY & AnyMiss & LineDirty); + + assign SelFlush = (CurrState == STATE_READY & FlushCache) | + (CurrState == STATE_FLUSH) | (CurrState == STATE_FLUSH_WRITEBACK); + assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) | + (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); + assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) | + (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); + assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) | + (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); + // Bus interface controls + assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | + (CurrState == STATE_FETCH & ~CacheBusAck) | + (CurrState == STATE_WRITEBACK & CacheBusAck); + assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | + (CurrState == STATE_WRITEBACK & ~CacheBusAck) | + (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck); + // write enable internal to cache + assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; + end + else begin + assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | + (CurrState == STATE_FETCH) | + (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. + assign CacheCommitted = (CurrState != STATE_READY) & ~(CurrState == STATE_READ_HOLD); + assign SelAdr = (CurrState == STATE_READY & AnyMiss) | // changes if store delay hazard removed + (CurrState == STATE_FETCH) | + (CurrState == STATE_WRITE_LINE) | + resetDelay; + assign SetDirty = 0; + assign ClearDirty = 0; + assign SelWriteback = 0; + assign SelFlush = 0; + assign FlushAdrCntEn = 0; + assign FlushWayCntEn = 0; + assign FlushCntRst = 0; + assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss) | + (CurrState == STATE_FETCH & ~CacheBusAck); + assign CacheBusRW[0] = 0; + assign CacheEn = (~Stall | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; + end // else: (READ_ONLY_CACHE) + // write enables internal to cache assign SetValid = CurrState == STATE_WRITE_LINE; - assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) | - (CurrState == STATE_WRITE_LINE & (StoreAMO)); - assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) | - (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. assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) | (CurrState == STATE_WRITE_LINE); - // Flush and eviction controls - assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | - (CurrState == STATE_READY & AnyMiss & LineDirty); - - assign SelFlush = (CurrState == STATE_READY & FlushCache) | - (CurrState == STATE_FLUSH) | - (CurrState == STATE_FLUSH_WRITEBACK); - assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) | - (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); - assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); - assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); - // Bus interface controls - assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | - (CurrState == STATE_FETCH & ~CacheBusAck) | - (CurrState == STATE_WRITEBACK & CacheBusAck); - assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | - (CurrState == STATE_WRITEBACK & ~CacheBusAck) | - (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck); - - assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // changes if store delay hazard removed - (CurrState == STATE_FETCH) | - (CurrState == STATE_WRITEBACK) | - (CurrState == STATE_WRITE_LINE) | - resetDelay; - assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD; - assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; endmodule // cachefsm From d60e3aaf5314acdfdaba6c61c6c00f15c4647c9c Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Wed, 12 Apr 2023 00:53:22 -0700 Subject: [PATCH 06/20] only assign ClearDirtyWay for read-write caches --- src/cache/cacheway.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 568e626e5..106905939 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -97,9 +97,9 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, ///////////////////////////////////////////////////////////////////////////////////////////// assign SetValidWay = SetValid & SelData; - assign ClearDirtyWay = ClearDirty & SelData; if (!READ_ONLY_CACHE) begin assign SetDirtyWay = SetDirty & SelData; + assign ClearDirtyWay = ClearDirty & SelData; assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; assign SetValidEN = SetValidWay & ~FlushStage; end From 800f0245f3514e2e0a8c747ff94951ae6d535e52 Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Wed, 12 Apr 2023 13:32:36 -0700 Subject: [PATCH 07/20] Cachefsm gate LRUWriteEn with ~FlushStage --- src/cache/cache.sv | 2 +- src/cache/cachefsm.sv | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cache/cache.sv b/src/cache/cache.sv index 2d90e98e8..ea7504f23 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -129,7 +129,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // Select victim way for associative caches if(NUMWAYS > 1) begin:vict cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMLINES) cacheLRU( - .clk, .reset, .CacheEn, .FlushStage, .HitWay, .ValidWay, .VictimWay, .CacheSet, .LRUWriteEn, + .clk, .reset, .CacheEn, .HitWay, .ValidWay, .VictimWay, .CacheSet, .LRUWriteEn, .SetValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache, .FlushCache); end else assign VictimWay = 1'b1; // one hot. diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index a42176325..c5e261f27 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -224,8 +224,9 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( // write enables internal to cache assign SetValid = CurrState == STATE_WRITE_LINE; + // coverage off -item e 1 -fecexprrow 8 assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) | - (CurrState == STATE_WRITE_LINE); + (CurrState == STATE_WRITE_LINE) & ~FlushStage; assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD; endmodule // cachefsm From a3d9e11b0fd9109bec2fc57567490b620bc16253 Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Wed, 12 Apr 2023 15:57:45 -0700 Subject: [PATCH 08/20] cachefsm exclude icache logic without code reuse --- sim/coverage-exclusions-rv64gc.do | 34 ++++- src/cache/cachefsm.sv | 198 ++++++++++++------------------ 2 files changed, 105 insertions(+), 127 deletions(-) diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index 3e880b502..eb10505eb 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -27,17 +27,41 @@ # This file should be a last resort. It's preferable to put # // coverage off # statements inline with the code whenever possible. +# a hack to describe coverage exclusions without hardcoding linenumbers: +do GetLineNum.do # LZA (i<64) statement confuses coverage tool # This is ugly to exlcude the whole file - is there a better option? // coverage off isn't working coverage exclude -srcfile lzc.sv -# Exclude D$ states from coverage in the I$ instance of cachefsm. -# This is cleaner than trying to set an I$-specific pragma in cachefsm.sv -# Also exclude the write line to ready transition for the I$ since we can't get a flush -# during this operation. -coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK +### Exclude D$ states and logic for the I$ instance +# This is cleaner than trying to set an I$-specific pragma in cachefsm.sv (which would exclude it for the D$ instance too) +# Also exclude the write line to ready transition for the I$ since we can't get a flush during this operation. +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK STATE_WRITEBACK coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY +# exclude unused transitions from case statement. Unfortunately the whole branch needs to be excluded I think. Expression coverage should still work. +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache state-case"] -item b 1 +# exclude branch/condition coverage: LineDirty if statement +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache FETCHStatement"] -item bc 1 +# exclude the unreachable logic +set start [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-start: icache case"] +set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache case"] +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $start-$end +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache WRITEBACKStatement"] +# exclude Atomic Operation logic +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache storeAMO"] -item e 1 -fecexprrow 6 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache storeAMO1"] -item e 1 -fecexprrow 2-4 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache AnyUpdateHit"] -item e 1 -fecexprrow 2 +# cache write logic +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheW"] -item e 1 -fecexprrow 4 +# output signal logic +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache StallStates"] -item e 1 -fecexprrow 8 12 14 +set start [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-start: icache flushdirtycontrols"] +set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache flushdirtycontrols"] +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $start-$end +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusW"] +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache SelAdrCauses"] -item e 1 -fecexprrow 4 10 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusRCauses"] -item e 1 -fecexprrow 1-2 12 ###################### # Toggle exclusions diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index c5e261f27..fc31aec4b 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -86,25 +86,18 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( statetype CurrState, NextState; - // no atomic operations on i$ - if (!READ_ONLY_CACHE) begin - assign AMO = CacheAtomic[1] & (&CacheRW); - assign StoreAMO = AMO | CacheRW[0]; - assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache; - assign AnyUpdateHit = StoreAMO & CacheHit; - assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); - assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; // for performance counter - end - else begin - assign AnyMiss = CacheRW[1] & ~CacheHit & ~InvalidateCache; - assign AnyUpdateHit = 0; // todo clear all RO cache of usage of this logic - assign AnyHit = CacheRW[1] & CacheHit; - assign CacheAccess = CacheRW[1] & CurrState == STATE_READY; // for performance counter - end + assign AMO = CacheAtomic[1] & (&CacheRW); + assign StoreAMO = AMO | CacheRW[0]; - assign CacheMiss = CacheAccess & ~CacheHit; // for performance counter + assign AnyMiss = (StoreAMO | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: icache storeAMO + assign AnyUpdateHit = (StoreAMO) & CacheHit; // exclusion-tag: icache storeAMO1 + assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit assign FlushFlag = FlushAdrFlag & FlushWayFlag; + // outputs for the performance counters. + assign CacheAccess = (AMO | CacheRW[1] | CacheRW[0]) & CurrState == STATE_READY; // exclusion-tag: icache CacheW + assign CacheMiss = CacheAccess & ~CacheHit; + // special case on reset. When the fsm first exists reset the // PCNextF will no longer be pointing to the correct address. // But PCF will be the reset vector. @@ -113,120 +106,81 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( always_ff @(posedge clk) if (reset | FlushStage) CurrState <= #1 STATE_READY; else CurrState <= #1 NextState; - - // seperating NextState logic by ro vs rw cache results in code duplication but this is needed to hit coverage. - if (!READ_ONLY_CACHE) - always_comb begin - NextState = STATE_READY; - case (CurrState) - STATE_READY: if(InvalidateCache) NextState = STATE_READY; - else if(FlushCache) NextState = STATE_FLUSH; - else if(AnyMiss & ~LineDirty) NextState = STATE_FETCH; - else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK; - else NextState = STATE_READY; - STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; - else NextState = STATE_FETCH; - STATE_WRITE_LINE: NextState = STATE_READ_HOLD; - STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; - else NextState = STATE_READY; - STATE_WRITEBACK: 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. - STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; - else if (FlushFlag) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH; - STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; - else if(CacheBusAck) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH_WRITEBACK; - default: NextState = STATE_READY; - endcase - end // always_comb - else // READ_ONLY_CACHE - always_comb begin - NextState = STATE_READY; - case (CurrState) - STATE_READY: if(InvalidateCache) NextState = STATE_READY; - else if(AnyMiss) NextState = STATE_FETCH; - else NextState = STATE_READY; - STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; - else NextState = STATE_FETCH; - STATE_WRITE_LINE: NextState = STATE_READ_HOLD; - STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; - else NextState = STATE_READY; - default: NextState = STATE_READY; - endcase // case (CurrState) - end // always_comb + + always_comb begin + NextState = STATE_READY; + case (CurrState) // exclusion-tag: icache state-case + STATE_READY: if(InvalidateCache) NextState = STATE_READY; + 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 & LineDirty) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement + else NextState = STATE_READY; + STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; + 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) 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. + STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; + else if (FlushFlag) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH; + STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; + else if(CacheBusAck) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH_WRITEBACK; + // exclusion-tag-end: icache case + default: NextState = STATE_READY; + endcase + end // com back to CPU - if (!READ_ONLY_CACHE) begin - assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | - (CurrState == STATE_FETCH) | - (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_FLUSH) | - (CurrState == STATE_FLUSH_WRITEBACK); - assign CacheCommitted = CurrState != STATE_READY; - assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // changes if store delay hazard removed - (CurrState == STATE_FETCH) | - (CurrState == STATE_WRITEBACK) | - (CurrState == STATE_WRITE_LINE) | - resetDelay; - assign SetDirty = (CurrState == STATE_READY & AnyUpdateHit) | - (CurrState == STATE_WRITE_LINE & (StoreAMO)); - assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) | - (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 - assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | - (CurrState == STATE_READY & AnyMiss & LineDirty); - - assign SelFlush = (CurrState == STATE_READY & FlushCache) | - (CurrState == STATE_FLUSH) | + assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD); + assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | // exclusion-tag: icache StallStates + (CurrState == STATE_FETCH) | + (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_FLUSH) | (CurrState == STATE_FLUSH_WRITEBACK); - assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) | - (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); - assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); - assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); - // Bus interface controls - assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | - (CurrState == STATE_FETCH & ~CacheBusAck) | - (CurrState == STATE_WRITEBACK & CacheBusAck); - assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | - (CurrState == STATE_WRITEBACK & ~CacheBusAck) | - (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck); - // write enable internal to cache - assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; - end - else begin - assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | - (CurrState == STATE_FETCH) | - (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. - assign CacheCommitted = (CurrState != STATE_READY) & ~(CurrState == STATE_READ_HOLD); - assign SelAdr = (CurrState == STATE_READY & AnyMiss) | // changes if store delay hazard removed - (CurrState == STATE_FETCH) | - (CurrState == STATE_WRITE_LINE) | - resetDelay; - assign SetDirty = 0; - assign ClearDirty = 0; - assign SelWriteback = 0; - assign SelFlush = 0; - assign FlushAdrCntEn = 0; - assign FlushWayCntEn = 0; - assign FlushCntRst = 0; - assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss) | - (CurrState == STATE_FETCH & ~CacheBusAck); - assign CacheBusRW[0] = 0; - assign CacheEn = (~Stall | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; - end // else: (READ_ONLY_CACHE) - // write enables internal to cache assign SetValid = CurrState == STATE_WRITE_LINE; // 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 + (CurrState == STATE_WRITE_LINE & (StoreAMO)); + assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(StoreAMO)) | // 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 + assign SelWriteback = (CurrState == STATE_WRITEBACK & ~CacheBusAck) | + (CurrState == STATE_READY & AnyMiss & LineDirty); + + assign SelFlush = (CurrState == STATE_READY & FlushCache) | + (CurrState == STATE_FLUSH) | + (CurrState == STATE_FLUSH_WRITEBACK); + assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) | + (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); + assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) | + (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); + assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) | + (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); + // exclusion-tag-end: icache flushdirtycontrols + // Bus interface controls + assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses + (CurrState == STATE_FETCH & ~CacheBusAck) | + (CurrState == STATE_WRITEBACK & CacheBusAck); + assign CacheBusRW[0] = (CurrState == STATE_READY & AnyMiss & LineDirty) | // exclusion-tag: icache CacheBusW + (CurrState == STATE_WRITEBACK & ~CacheBusAck) | + (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck); + + assign SelAdr = (CurrState == STATE_READY & (StoreAMO | AnyMiss)) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed + (CurrState == STATE_FETCH) | + (CurrState == STATE_WRITEBACK) | + (CurrState == STATE_WRITE_LINE) | + resetDelay; assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD; + assign CacheEn = (~Stall | FlushCache | AnyMiss) | (CurrState != STATE_READY) | reset | InvalidateCache; endmodule // cachefsm From 92cd0cb6ab2467bfea758db2891005fb48e05c7d Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Wed, 12 Apr 2023 15:58:38 -0700 Subject: [PATCH 09/20] track GetLinenum.do (tcl procedure to find line numbers to exclude) --- sim/GetLineNum.do | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 sim/GetLineNum.do diff --git a/sim/GetLineNum.do b/sim/GetLineNum.do new file mode 100644 index 000000000..4d38d9121 --- /dev/null +++ b/sim/GetLineNum.do @@ -0,0 +1,18 @@ +# Alec Vercruysse +# 2023-04-12 +# Note that the target string is regex, and needs to be double-escaped. +# e.g. to match a (, you need \\(. +proc GetLineNum {fname target} { + set f [open $fname] + set linectr 1 + while {[gets $f line] != -1} { + if {[regexp $target $line]} { + close $f + return $linectr + } + incr linectr + } + close $f + return -code error \ + "target string not found" +} From 0862688168cf070ccf1e84f09230f8240f36ef30 Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Thu, 13 Apr 2023 19:06:09 -0700 Subject: [PATCH 10/20] testbench code visual improvements --- testbench/testbench.sv | 464 ++++++++++++++++++++--------------------- 1 file changed, 232 insertions(+), 232 deletions(-) diff --git a/testbench/testbench.sv b/testbench/testbench.sv index b3c0efeab..94f8d501b 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -52,29 +52,29 @@ module testbench; string tests[]; logic [3:0] dummy; - logic [`AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; + logic [`AHBW-1:0] HRDATAEXT; + logic HREADYEXT, HRESPEXT; logic [`PA_BITS-1:0] HADDR; - logic [`AHBW-1:0] HWDATA; - logic [`XLEN/8-1:0] HWSTRB; - logic HWRITE; - logic [2:0] HSIZE; - logic [2:0] HBURST; - logic [3:0] HPROT; - logic [1:0] HTRANS; - logic HMASTLOCK; - logic HCLK, HRESETn; - logic [`XLEN-1:0] PCW; + logic [`AHBW-1:0] HWDATA; + logic [`XLEN/8-1:0] HWSTRB; + logic HWRITE; + logic [2:0] HSIZE; + logic [2:0] HBURST; + logic [3:0] HPROT; + logic [1:0] HTRANS; + logic HMASTLOCK; + logic HCLK, HRESETn; + logic [`XLEN-1:0] PCW; - string ProgramAddrMapFile, ProgramLabelMapFile; - integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; + string ProgramAddrMapFile, ProgramLabelMapFile; + integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; - logic DCacheFlushDone, DCacheFlushStart; + logic DCacheFlushDone, DCacheFlushStart; logic riscofTest; logic StartSample, EndSample; flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); // check assertions for a legal configuration riscvassertions riscvassertions(); @@ -149,7 +149,7 @@ module testbench; end end - string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile; + string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile; integer outputFilePointer; logic [31:0] GPIOIN, GPIOOUT, GPIOEN; @@ -160,16 +160,16 @@ module testbench; logic SDCCmdOut; logic SDCCmdOE; logic [3:0] SDCDatIn; - tri1 [3:0] SDCDat; + tri1 [3:0] SDCDat; tri1 SDCCmd; logic HREADY; logic HSELEXT; - logic InitializingMemories; + logic InitializingMemories; integer ResetCount, ResetThreshold; - logic InReset; - logic Begin; + logic InReset; + logic BeginSample; // instantiate device to be tested assign GPIOIN = 0; @@ -225,13 +225,14 @@ module testbench; totalerrors = 0; testadr = 0; testadrNoBase = 0; - // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests and tests[0] == "2" refers to WallyRiscvArchTests + // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests + // and tests[0] == "2" refers to WallyRiscvArchTests riscofTest = tests[0] == "1" | tests[0] == "2"; // fill memory with defined values to reduce Xs in simulation // Quick note the memory will need to be initialized. The C library does not - // guarantee the initialized reads. For example a strcmp can read 6 byte - // strings, but uses a load double to read them in. If the last 2 bytes are - // not initialized the compare results in an 'x' which propagates through + // guarantee the initialized reads. For example a strcmp can read 6 byte + // strings, but uses a load double to read them in. If the last 2 bytes are + // not initialized the compare results in an 'x' which propagates through // the design. if (TEST == "coremark") for (i=MemStartAddr; i Date: Thu, 13 Apr 2023 21:01:57 -0700 Subject: [PATCH 13/20] Some cleanup --- src/cache/cache.sv | 18 +++++++++--------- src/cache/cacheLRU.sv | 4 ++-- src/cache/cachefsm.sv | 4 ++-- src/cache/subcachelineread.sv | 5 ++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/cache/cache.sv b/src/cache/cache.sv index 4721eb167..ebee8f4f1 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// cache +// cache.sv // // Written: Ross Thompson ross1728@gmail.com // Created: 7 July 2021 @@ -167,22 +167,22 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // Adjust byte mask from word to cache line onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded)); for(index = 0; index < 2**LOGCWPL; index++) begin - assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0; + assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0; end assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1. // 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])); + 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])); 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 LineByteMask = '1; + // No need for this mux if the cache does not handle writes. + assign LineWriteData = FetchBuffer; + assign LineByteMask = '1; end ///////////////////////////////////////////////////////////////////////////////////////////// // Flush logic @@ -203,8 +203,8 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE assign FlushWayFlag = FlushWay[NUMWAYS-1]; end // block: flushlogic else begin:flushlogic - assign FlushWayFlag = 0; - assign FlushAdrFlag = 0; + assign FlushWayFlag = 0; + assign FlushAdrFlag = 0; end ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cache/cacheLRU.sv b/src/cache/cacheLRU.sv index 1e7101365..87d9f072a 100644 --- a/src/cache/cacheLRU.sv +++ b/src/cache/cacheLRU.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// dcache (data cache) +// cacheLRU.sv // // Written: Ross Thompson ross1728@gmail.com // Created: 20 July 2021 @@ -37,7 +37,7 @@ module cacheLRU 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] ValidWay, // Which ways for a particular set are valid, ignores tag - input logic [SETLEN-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr + input logic [SETLEN-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr input logic [SETLEN-1:0] PAdr, // Physical address input logic LRUWriteEn, // Update the LRU state input logic SetValid, // Set the dirty bit in the selected way and set diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index 2a5cb8235..525d7524f 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -1,11 +1,11 @@ /////////////////////////////////////////// -// dcache (data cache) fsm +// cachefsm.sv // // Written: Ross Thompson ross1728@gmail.com // Created: 25 August 2021 // Modified: 20 January 2023 // -// Purpose: Controller for the dcache fsm +// Purpose: Controller for the cache fsm // // Documentation: RISC-V System on Chip Design Chapter 7 (Figure 7.14 and Table 7.1) // diff --git a/src/cache/subcachelineread.sv b/src/cache/subcachelineread.sv index 58d022a71..ea305fb6c 100644 --- a/src/cache/subcachelineread.sv +++ b/src/cache/subcachelineread.sv @@ -1,11 +1,11 @@ /////////////////////////////////////////// -// subcachelineread +// subcachelineread.sv // // Written: Ross Thompson ross1728@gmail.com // Created: 4 February 2022 // Modified: 20 January 2023 // -// Purpose: Muxes the cache line downto the word size. Also include possilbe save/restore registers/muxes. +// Purpose: Muxes the cache line down to the word size. Also include possible save/restore registers/muxes. // // Documentation: RISC-V System on Chip Design Chapter 7 @@ -31,7 +31,6 @@ module subcachelineread #(parameter LINELEN, WORDLEN, parameter MUXINTERVAL )( // The number of bits between mux. Set to 16 for I$ to support compressed. Set to `LLEN for D$ - input logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1 : 0] PAdr, // Physical address input logic [LINELEN-1:0] ReadDataLine,// Read data of the whole cacheline output logic [WORDLEN-1:0] ReadDataWord // read data of selected word. From 94b686fcf6eccafd5754a3824774d4a028d37c9e Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Thu, 13 Apr 2023 21:02:15 -0700 Subject: [PATCH 14/20] More changes --- src/ebu/ahbcacheinterface.sv | 28 +++++++++--------- src/ebu/ahbinterface.sv | 16 +++++------ src/ebu/buscachefsm.sv | 30 ++++++++++---------- src/ebu/controllerinput.sv | 36 +++++++++++------------ src/ebu/ebufsmarb.sv | 6 ++-- src/fpu/fdivsqrt/fdivsqrtexpcalc.sv | 44 ++++++++++++++--------------- 6 files changed, 80 insertions(+), 80 deletions(-) diff --git a/src/ebu/ahbcacheinterface.sv b/src/ebu/ahbcacheinterface.sv index e2e7d3696..38b1e6879 100644 --- a/src/ebu/ahbcacheinterface.sv +++ b/src/ebu/ahbcacheinterface.sv @@ -38,27 +38,27 @@ module ahbcacheinterface #( )( input logic HCLK, HRESETn, // bus interface controls - input logic HREADY, // AHB peripheral ready + input logic HREADY, // AHB peripheral ready output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic HWRITE, // AHB 0: Read operation 1: Write operation output logic [2:0] HSIZE, // AHB transaction width output logic [2:0] HBURST, // AHB burst length // bus interface buses - input logic [`AHBW-1:0] HRDATA, // AHB read data + input logic [`AHBW-1:0] HRDATA, // AHB read data output logic [`PA_BITS-1:0] HADDR, // AHB address output logic [`AHBW-1:0] HWDATA, // AHB write data output logic [`AHBW/8-1:0] HWSTRB, // AHB byte mask // cache interface - input logic [`PA_BITS-1:0] CacheBusAdr, // Address of cache line - input logic [`LLEN-1:0] CacheReadDataWordM, // one word of cache line during a writeback - input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$ - input logic Cacheable, // Memory operation is cachable - input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch - output logic CacheBusAck, // Handshack to $ indicating bus transaction completed - output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus - output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase - output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr + input logic [`PA_BITS-1:0] CacheBusAdr, // Address of cache line + input logic [`LLEN-1:0] CacheReadDataWordM, // One word of cache line during a writeback + input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$ + input logic Cacheable, // Memory operation is cachable + input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch + output logic CacheBusAck, // Handshake to $ indicating bus transaction completed + output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus + output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase + output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr // uncached interface input logic [`PA_BITS-1:0] PAdr, // Physical address of uncached memory operation @@ -77,7 +77,7 @@ module ahbcacheinterface #( logic [`PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA - logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s + logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s logic [`AHBW-1:0] PreHWDATA; // AHB Address phase write data genvar index; @@ -107,7 +107,7 @@ module ahbcacheinterface #( end else assign CacheReadDataWordAHB = CacheReadDataWordM[`AHBW-1:0]; mux2 #(`AHBW) HWDATAMux(.d0(CacheReadDataWordAHB), .d1(WriteDataM[`AHBW-1:0]), - .s(~(CacheableOrFlushCacheM)), .y(PreHWDATA)); + .s(~(CacheableOrFlushCacheM)), .y(PreHWDATA)); flopen #(`AHBW) wdreg(HCLK, HREADY, PreHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec // *** bummer need a second byte mask for bus as it is AHBW rather than LLEN. @@ -119,5 +119,5 @@ module ahbcacheinterface #( buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm( .HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat, .CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed, - .HREADY, .HTRANS, .HWRITE, .HBURST); + .HREADY, .HTRANS, .HWRITE, .HBURST); endmodule diff --git a/src/ebu/ahbinterface.sv b/src/ebu/ahbinterface.sv index 579791032..1a9308dd4 100644 --- a/src/ebu/ahbinterface.sv +++ b/src/ebu/ahbinterface.sv @@ -32,21 +32,21 @@ module ahbinterface #( parameter LSU = 0 // 1: LSU bus width is `XLEN, 0: IFU bus width is 32 bits )( - input logic HCLK, HRESETn, + input logic HCLK, HRESETn, // bus interface - input logic HREADY, // AHB peripheral ready + input logic HREADY, // AHB peripheral ready output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic HWRITE, // AHB 0: Read operation 1: Write operation - input logic [`XLEN-1:0] HRDATA, // AHB read data + input logic [`XLEN-1:0] HRDATA, // AHB read data output logic [`XLEN-1:0] HWDATA, // AHB write data output logic [`XLEN/8-1:0] HWSTRB, // AHB byte mask // lsu/ifu interface - input logic Stall, // Core pipeline is stalled - input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting - input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write - input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word - input logic [`XLEN-1:0] WriteData, // IEU write data for a store + input logic Stall, // Core pipeline is stalled + input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting + input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write + input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word + input logic [`XLEN-1:0] WriteData, // IEU write data for a store output logic BusStall, // Bus is busy with an in flight memory operation output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt output logic [(LSU ? `XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus diff --git a/src/ebu/buscachefsm.sv b/src/ebu/buscachefsm.sv index e0efcf3a3..7456cac8b 100644 --- a/src/ebu/buscachefsm.sv +++ b/src/ebu/buscachefsm.sv @@ -40,29 +40,29 @@ module buscachefsm #( input logic HRESETn, // IEU interface - input logic Stall, // Core pipeline is stalled - input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting - input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write - output logic BusStall, // Bus is busy with an in flight memory operation - output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt + input logic Stall, // Core pipeline is stalled + input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting + input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write + output logic BusStall, // Bus is busy with an in flight memory operation + output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt // ahb cache interface locals. - output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA + output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA // cache interface - input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch - output logic CacheBusAck, // Handshack to $ indicating bus transaction completed + input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch + output logic CacheBusAck, // Handshack to $ indicating bus transaction completed // lsu interface output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase output logic [AHBWLOGBWPL-1:0] BeatCountDelayed, // Beat within the cache line in the second (Data) cache stage - output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr + output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr // BUS interface - input logic HREADY, // AHB peripheral ready - output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - output logic HWRITE, // AHB 0: Read operation 1: Write operation - output logic [2:0] HBURST // AHB burst length + input logic HREADY, // AHB peripheral ready + output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + output logic HWRITE, // AHB 0: Read operation 1: Write operation + output logic [2:0] HBURST // AHB burst length ); typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype; @@ -78,8 +78,8 @@ module buscachefsm #( logic CacheAccess; always_ff @(posedge HCLK) - if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE; - else CurrState <= #1 NextState; + if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE; + else CurrState <= #1 NextState; always_comb begin case(CurrState) diff --git a/src/ebu/controllerinput.sv b/src/ebu/controllerinput.sv index a8c8e8308..6e3c27d3b 100644 --- a/src/ebu/controllerinput.sv +++ b/src/ebu/controllerinput.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// controller input stage +// controllerinput.sv // // Written: Ross Thompson ross1728@gmail.com // Created: August 31, 2022 @@ -36,26 +36,26 @@ module controllerinput #( parameter SAVE_ENABLED = 1 // 1: Save manager inputs if Save = 1, 0: Don't save inputs )( - input logic HCLK, - input logic HRESETn, - input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs - input logic Restore, // Restore a saved manager inputs when it is finally granted - input logic Disable, // Supress HREADY to the non-granted manager + input logic HCLK, + input logic HRESETn, + input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs + input logic Restore, // Restore a saved manager inputs when it is finally granted + input logic Disable, // Suppress HREADY to the non-granted manager output logic Request, // This manager is making a request // controller input - input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation - input logic [2:0] HSIZEIn, // Manager input. AHB transaction width - input logic [2:0] HBURSTIn, // Manager input. AHB burst length - input logic [`PA_BITS-1:0] HADDRIn, // Manager input. AHB address - output logic HREADYOut, // Indicate to manager the peripherial is not busy and another manager does not have priority + input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation + input logic [2:0] HSIZEIn, // Manager input. AHB transaction width + input logic [2:0] HBURSTIn, // Manager input. AHB burst length + input logic [`PA_BITS-1:0] HADDRIn, // Manager input. AHB address + output logic HREADYOut, // Indicate to manager the peripheral is not busy and another manager does not have priority // controller output - output logic [1:0] HTRANSOut, // Aribrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - output logic HWRITEOut, // Aribrated manager transaction. AHB 0: Read operation 1: Write operation - output logic [2:0] HSIZEOut, // Aribrated manager transaction. AHB transaction width - output logic [2:0] HBURSTOut, // Aribrated manager transaction. AHB burst length - output logic [`PA_BITS-1:0] HADDROut, // Aribrated manager transaction. AHB address - input logic HREADYIn // Peripherial ready + output logic [1:0] HTRANSOut, // Arbitrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + output logic HWRITEOut, // Arbitrated manager transaction. AHB 0: Read operation 1: Write operation + output logic [2:0] HSIZEOut, // Arbitrated manager transaction. AHB transaction width + output logic [2:0] HBURSTOut, // Arbitrated manager transaction. AHB burst length + output logic [`PA_BITS-1:0] HADDROut, // Arbitrated manager transaction. AHB address + input logic HREADYIn // Peripheral ready ); logic HWRITESave; diff --git a/src/ebu/ebufsmarb.sv b/src/ebu/ebufsmarb.sv index ec1a3d674..a61a3961f 100644 --- a/src/ebu/ebufsmarb.sv +++ b/src/ebu/ebufsmarb.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// ebufsmarb +// ebufsmarb.sv // // Written: Ross Thompson ross1728@gmail.com // Created: 23 January 2023 @@ -55,7 +55,7 @@ module ebufsmarb ( logic IFUReqD; // 1 cycle delayed IFU request. Part of arbitration logic FinalBeat, FinalBeatD; // Indicates the last beat of a burst logic BeatCntEn; - logic [3:0] BeatCount; // Position within a burst transfer + logic [3:0] BeatCount; // Position within a burst transfer logic BeatCntReset; logic [3:0] Threshold; // Number of beats derived from HBURST @@ -86,7 +86,7 @@ module ebufsmarb ( // Controller 1 (LSU) // When both the IFU and LSU request at the same time, the FSM will go into the arbitrate state. // Once the LSU request is done the fsm returns to IDLE. To prevent the LSU from regaining - // priority and re issuing the same memroy operation, the delayed IFUReqD squashes the LSU request. + // priority and re-issuing the same memory operation, the delayed IFUReqD squashes the LSU request. // This is necessary because the pipeline is stalled for the entire duration of both transactions, // and the LSU memory request will stil be active. flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqD); diff --git a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv index 482fed842..aa8ae051d 100644 --- a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// fdivsqrtpreproc.sv +// fdivsqrtexpcalc.sv // // Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu // Modified:13 January 2022 @@ -30,11 +30,11 @@ module fdivsqrtexpcalc( input logic [`FMTBITS-1:0] Fmt, - input logic [`NE-1:0] Xe, Ye, - input logic Sqrt, - input logic XZero, - input logic [`DIVBLEN:0] ell, m, - output logic [`NE+1:0] Qe + input logic [`NE-1:0] Xe, Ye, + input logic Sqrt, + input logic XZero, + input logic [`DIVBLEN:0] ell, m, + output logic [`NE+1:0] Qe ); logic [`NE-2:0] Bias; logic [`NE+1:0] SXExp; @@ -42,28 +42,28 @@ module fdivsqrtexpcalc( logic [`NE+1:0] DExp; if (`FPSIZES == 1) begin - assign Bias = (`NE-1)'(`BIAS); + assign Bias = (`NE-1)'(`BIAS); end else if (`FPSIZES == 2) begin - assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1); + assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1); end else if (`FPSIZES == 3) begin - always_comb - case (Fmt) - `FMT: Bias = (`NE-1)'(`BIAS); - `FMT1: Bias = (`NE-1)'(`BIAS1); - `FMT2: Bias = (`NE-1)'(`BIAS2); - default: Bias = 'x; - endcase + always_comb + case (Fmt) + `FMT: Bias = (`NE-1)'(`BIAS); + `FMT1: Bias = (`NE-1)'(`BIAS1); + `FMT2: Bias = (`NE-1)'(`BIAS2); + default: Bias = 'x; + endcase end else if (`FPSIZES == 4) begin - always_comb - case (Fmt) - 2'h3: Bias = (`NE-1)'(`Q_BIAS); - 2'h1: Bias = (`NE-1)'(`D_BIAS); - 2'h0: Bias = (`NE-1)'(`S_BIAS); - 2'h2: Bias = (`NE-1)'(`H_BIAS); - endcase + always_comb + case (Fmt) + 2'h3: Bias = (`NE-1)'(`Q_BIAS); + 2'h1: Bias = (`NE-1)'(`D_BIAS); + 2'h0: Bias = (`NE-1)'(`S_BIAS); + 2'h2: Bias = (`NE-1)'(`H_BIAS); + endcase end assign SXExp = {2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - (`NE+2)'(`BIAS); assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias}; From 28dd41291a85b41cf1666890922a9c2db5ed4cf6 Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Thu, 13 Apr 2023 21:02:30 -0700 Subject: [PATCH 15/20] More cleanup --- src/fpu/fdivsqrt/fdivsqrtfgen2.sv | 2 +- src/fpu/fdivsqrt/fdivsqrtfgen4.sv | 2 +- src/fpu/fdivsqrt/fdivsqrtfsm.sv | 34 ++++++++++++++-------------- src/fpu/fdivsqrt/fdivsqrtiter.sv | 8 +++---- src/fpu/fdivsqrt/fdivsqrtpostproc.sv | 2 +- src/fpu/fdivsqrt/fdivsqrtqsel2.sv | 2 +- src/fpu/fdivsqrt/fdivsqrtstage4.sv | 6 ++--- src/fpu/fdivsqrt/fdivsqrtuotfc2.sv | 6 ++--- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/fpu/fdivsqrt/fdivsqrtfgen2.sv b/src/fpu/fdivsqrt/fdivsqrtfgen2.sv index 9c13a91da..250fb4fbd 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfgen2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfgen2.sv @@ -29,7 +29,7 @@ `include "wally-config.vh" module fdivsqrtfgen2 ( - input logic up, uz, + input logic up, uz, input logic [`DIVb+3:0] C, U, UM, output logic [`DIVb+3:0] F ); diff --git a/src/fpu/fdivsqrt/fdivsqrtfgen4.sv b/src/fpu/fdivsqrt/fdivsqrtfgen4.sv index 975d58ebd..a07e504f4 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfgen4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfgen4.sv @@ -29,7 +29,7 @@ `include "wally-config.vh" module fdivsqrtfgen4 ( - input logic [3:0] udigit, + input logic [3:0] udigit, input logic [`DIVb+3:0] C, U, UM, output logic [`DIVb+3:0] F ); diff --git a/src/fpu/fdivsqrt/fdivsqrtfsm.sv b/src/fpu/fdivsqrt/fdivsqrtfsm.sv index 4cfede605..559e4b775 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfsm.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfsm.sv @@ -29,24 +29,24 @@ `include "wally-config.vh" module fdivsqrtfsm( - input logic clk, - input logic reset, + input logic clk, + input logic reset, input logic [`FMTBITS-1:0] FmtE, - input logic XInfE, YInfE, - input logic XZeroE, YZeroE, - input logic XNaNE, YNaNE, - input logic FDivStartE, IDivStartE, - input logic XsE, - input logic SqrtE, - input logic StallM, - input logic FlushE, - input logic WZeroE, - input logic IntDivE, - input logic [`DIVBLEN:0] nE, - input logic ISpecialCaseE, - output logic IFDivStartE, - output logic FDivBusyE, FDivDoneE, - output logic SpecialCaseM + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, + input logic FDivStartE, IDivStartE, + input logic XsE, + input logic SqrtE, + input logic StallM, + input logic FlushE, + input logic WZeroE, + input logic IntDivE, + input logic [`DIVBLEN:0] nE, + input logic ISpecialCaseE, + output logic IFDivStartE, + output logic FDivBusyE, FDivDoneE, + output logic SpecialCaseM ); typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; diff --git a/src/fpu/fdivsqrt/fdivsqrtiter.sv b/src/fpu/fdivsqrt/fdivsqrtiter.sv index 7de120eda..ec15423e4 100644 --- a/src/fpu/fdivsqrt/fdivsqrtiter.sv +++ b/src/fpu/fdivsqrt/fdivsqrtiter.sv @@ -29,10 +29,10 @@ `include "wally-config.vh" module fdivsqrtiter( - input logic clk, - input logic IFDivStartE, - input logic FDivBusyE, - input logic SqrtE, + input logic clk, + input logic IFDivStartE, + input logic FDivBusyE, + input logic SqrtE, input logic [`DIVb+3:0] X, input logic [`DIVb-1:0] DPreproc, output logic [`DIVb-1:0] D, diff --git a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv index 7b92f8c83..b8575f7fe 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv @@ -112,7 +112,7 @@ module fdivsqrtpostproc( // Select quotient or remainder and do normalization shift mux2 #(`DIVBLEN+1) normshiftmux(((`DIVBLEN+1)'(`DIVb) - (nM * (`DIVBLEN+1)'(`LOGR))), (mM + (`DIVBLEN+1)'(`DIVa)), RemOpM, NormShiftM); - mux2 #(`DIVb+4) presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM); + mux2 #(`DIVb+4) presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM); assign PreIntResultM = $signed(PreResultM >>> NormShiftM); // special case logic diff --git a/src/fpu/fdivsqrt/fdivsqrtqsel2.sv b/src/fpu/fdivsqrt/fdivsqrtqsel2.sv index fd0a2a469..18c577b97 100644 --- a/src/fpu/fdivsqrt/fdivsqrtqsel2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtqsel2.sv @@ -30,7 +30,7 @@ module fdivsqrtqsel2 ( input logic [3:0] ps, pc, - output logic up, uz, un + output logic up, uz, un ); logic [3:0] p, g; diff --git a/src/fpu/fdivsqrt/fdivsqrtstage4.sv b/src/fpu/fdivsqrt/fdivsqrtstage4.sv index ee92d263b..f2ff3734b 100644 --- a/src/fpu/fdivsqrt/fdivsqrtstage4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtstage4.sv @@ -31,7 +31,7 @@ module fdivsqrtstage4 ( input logic [`DIVb-1:0] D, input logic [`DIVb+3:0] DBar, D2, DBar2, - input logic [`DIVb:0] U,UM, + input logic [`DIVb:0] U,UM, input logic [`DIVb+3:0] WS, WC, input logic [`DIVb+1:0] C, input logic SqrtE, j1, @@ -58,8 +58,8 @@ module fdivsqrtstage4 ( // 0000 = 0 // 0010 = -1 // 0001 = -2 - assign Smsbs = U[`DIVb:`DIVb-4]; - assign Dmsbs = D[`DIVb-1:`DIVb-3]; + assign Smsbs = U[`DIVb:`DIVb-4]; + assign Dmsbs = D[`DIVb-1:`DIVb-3]; assign WCmsbs = WC[`DIVb+3:`DIVb-4]; assign WSmsbs = WS[`DIVb+3:`DIVb-4]; diff --git a/src/fpu/fdivsqrt/fdivsqrtuotfc2.sv b/src/fpu/fdivsqrt/fdivsqrtuotfc2.sv index 65b8940ac..33956a0fd 100644 --- a/src/fpu/fdivsqrt/fdivsqrtuotfc2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtuotfc2.sv @@ -32,10 +32,10 @@ // Unified OTFC, Radix 2 // /////////////////////////////// module fdivsqrtuotfc2( - input logic up, un, + input logic up, un, input logic [`DIVb+1:0] C, - input logic [`DIVb:0] U, UM, - output logic [`DIVb:0] UNext, UMNext + input logic [`DIVb:0] U, UM, + output logic [`DIVb:0] UNext, UMNext ); // The on-the-fly converter transfers the divsqrt // bits to the quotient as they come. From 95223bf11c3b40b8b700958df145376c61e47065 Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Thu, 13 Apr 2023 21:34:50 -0700 Subject: [PATCH 16/20] More cleanup --- src/fpu/fdivsqrt/fdivsqrtuotfc4.sv | 2 +- src/generic/lzc.sv | 2 +- src/generic/onehotdecoder.sv | 2 +- src/hazard/hazard.sv | 14 +++++++------- src/ieu/bmu/byte.sv | 2 +- src/ieu/bmu/cnt.sv | 4 ++-- src/ieu/bmu/ext.sv | 2 +- src/ieu/bmu/popcnt.sv | 2 +- src/ieu/ieu.sv | 2 +- src/ieu/shifter.sv | 6 +++--- src/ifu/bpred/bpred.sv | 26 +++++++++++++------------- src/ifu/bpred/btb.sv | 22 +++++++++++----------- 12 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/fpu/fdivsqrt/fdivsqrtuotfc4.sv b/src/fpu/fdivsqrt/fdivsqrtuotfc4.sv index a1416384b..57298b4c8 100644 --- a/src/fpu/fdivsqrt/fdivsqrtuotfc4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtuotfc4.sv @@ -29,7 +29,7 @@ `include "wally-config.vh" module fdivsqrtuotfc4( - input logic [3:0] udigit, + input logic [3:0] udigit, input logic [`DIVb:0] U, UM, input logic [`DIVb:0] C, output logic [`DIVb:0] UNext, UMNext diff --git a/src/generic/lzc.sv b/src/generic/lzc.sv index 9b7c841b2..7314b29e9 100644 --- a/src/generic/lzc.sv +++ b/src/generic/lzc.sv @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module lzc #(parameter WIDTH = 1) ( - input logic [WIDTH-1:0] num, // number to count the leading zeroes of + input logic [WIDTH-1:0] num, // number to count the leading zeroes of output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes ); diff --git a/src/generic/onehotdecoder.sv b/src/generic/onehotdecoder.sv index 6334e91f8..5e8f01c26 100644 --- a/src/generic/onehotdecoder.sv +++ b/src/generic/onehotdecoder.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// oneHotDecoder.sv +// onehotdecoder.sv // // Written: ross1728@gmail.com July 09, 2021 // Modified: diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 224ff8b37..51f2ccf40 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -30,13 +30,13 @@ module hazard ( // Detect hazards - input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, - input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD, - input logic LSUStallM, IFUStallF, - input logic FCvtIntStallD, FPUStallD, - input logic DivBusyE, FDivBusyE, - input logic EcallFaultM, BreakpointFaultM, - input logic wfiM, IntPendingM, + input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, + input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD, + input logic LSUStallM, IFUStallF, + input logic FCvtIntStallD, FPUStallD, + input logic DivBusyE, FDivBusyE, + input logic EcallFaultM, BreakpointFaultM, + input logic wfiM, IntPendingM, // Stall & flush outputs output logic StallF, StallD, StallE, StallM, StallW, output logic FlushD, FlushE, FlushM, FlushW diff --git a/src/ieu/bmu/byte.sv b/src/ieu/bmu/byte.sv index db7a3b45c..32031059a 100644 --- a/src/ieu/bmu/byte.sv +++ b/src/ieu/bmu/byte.sv @@ -31,7 +31,7 @@ module byteUnit #(parameter WIDTH=32) ( input logic [WIDTH-1:0] A, // Operands - input logic ByteSelect, // LSB of Immediate + input logic ByteSelect, // LSB of Immediate output logic [WIDTH-1:0] ByteResult); // rev8, orcb result logic [WIDTH-1:0] OrcBResult, Rev8Result; diff --git a/src/ieu/bmu/cnt.sv b/src/ieu/bmu/cnt.sv index 75ace3ac7..a1f82eb7e 100644 --- a/src/ieu/bmu/cnt.sv +++ b/src/ieu/bmu/cnt.sv @@ -32,8 +32,8 @@ module cnt #(parameter WIDTH = 32) ( input logic [WIDTH-1:0] A, RevA, // Operands - input logic [1:0] B, // Last 2 bits of immediate - input logic W64, // Indicates word operation + input logic [1:0] B, // Last 2 bits of immediate + input logic W64, // Indicates word operation output logic [WIDTH-1:0] CntResult // count result ); diff --git a/src/ieu/bmu/ext.sv b/src/ieu/bmu/ext.sv index 12e690436..438addaa8 100644 --- a/src/ieu/bmu/ext.sv +++ b/src/ieu/bmu/ext.sv @@ -32,7 +32,7 @@ module ext #(parameter WIDTH = 32) ( input logic [WIDTH-1:0] A, // Operands - input logic [1:0] ExtSelect, // B[2], B[0] of immediate + input logic [1:0] ExtSelect, // B[2], B[0] of immediate output logic [WIDTH-1:0] ExtResult); // Extend Result logic [WIDTH-1:0] sexthResult, zexthResult, sextbResult; diff --git a/src/ieu/bmu/popcnt.sv b/src/ieu/bmu/popcnt.sv index 8732f29f2..7701c0d65 100644 --- a/src/ieu/bmu/popcnt.sv +++ b/src/ieu/bmu/popcnt.sv @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module popcnt #(parameter WIDTH = 32) ( - input logic [WIDTH-1:0] num, // number to count total ones + input logic [WIDTH-1:0] num, // number to count total ones output logic [$clog2(WIDTH):0] PopCnt // the total number of ones ); diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index d5b3e8f40..02fa1dd7c 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -29,7 +29,7 @@ `include "wally-config.vh" module ieu ( - input logic clk, reset, + input logic clk, reset, // Decode stage signals input logic [31:0] InstrD, // Instruction input logic IllegalIEUFPUInstrD, // Illegal instruction diff --git a/src/ieu/shifter.sv b/src/ieu/shifter.sv index 5227ee3bd..11ae1cf0a 100644 --- a/src/ieu/shifter.sv +++ b/src/ieu/shifter.sv @@ -35,9 +35,9 @@ module shifter ( input logic Right, Rotate, W64, SubArith, // Shift right, rotate, W64-type operation, arithmetic shift output logic [`XLEN-1:0] Y); // Shifted result - logic [2*`XLEN-2:0] Z, ZShift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits - logic [`LOG_XLEN-1:0] TruncAmt, Offset; // Shift amount adjusted for RV64, right-shift amount - logic Sign; // Sign bit for sign extension + logic [2*`XLEN-2:0] Z, ZShift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits + logic [`LOG_XLEN-1:0] TruncAmt, Offset; // Shift amount adjusted for RV64, right-shift amount + logic Sign; // Sign bit for sign extension assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension if (`XLEN==32) begin // rv32 diff --git a/src/ifu/bpred/bpred.sv b/src/ifu/bpred/bpred.sv index e74d19870..881150b3f 100644 --- a/src/ifu/bpred/bpred.sv +++ b/src/ifu/bpred/bpred.sv @@ -48,25 +48,25 @@ module bpred ( input logic [`XLEN-1:0] PCE, // Execution stage instruction address input logic [`XLEN-1:0] PCM, // Memory stage instruction address - input logic [31:0] PostSpillInstrRawF, // Instruction + input logic [31:0] PostSpillInstrRawF, // Instruction // Branch and jump outcome - input logic InstrValidD, InstrValidE, + input logic InstrValidD, InstrValidE, input logic BranchD, BranchE, input logic JumpD, JumpE, - input logic PCSrcE, // Executation stage branch is taken - input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address - input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address - input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) + input logic PCSrcE, // Executation stage branch is taken + input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address + input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address + input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as call, return, jr (not return), j, br // Report branch prediction status - output logic BPWrongE, // Prediction is wrong - output logic BPWrongM, // Prediction is wrong + output logic BPWrongE, // Prediction is wrong + output logic BPWrongM, // Prediction is wrong output logic BPDirPredWrongM, // Prediction direction is wrong - output logic BTAWrongM, // Prediction target wrong + output logic BTAWrongM, // Prediction target wrong output logic RASPredPCWrongM, // RAS prediction is wrong - output logic IClassWrongM // Class prediction is wrong + output logic IClassWrongM // Class prediction is wrong ); logic [1:0] BPDirPredF; @@ -187,7 +187,7 @@ module bpred ( // Correct branch/jump target. mux2 #(`XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE); - // If the fence/csrw was predicted as a taken branch then we select PCF, rather PCE. + // If the fence/csrw was predicted as a taken branch then we select PCF, rather than PCE. // Effectively this is PCM+4 or the non-existant PCLinkM if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE); else assign NextValidPCE = PCE; @@ -201,11 +201,11 @@ module bpred ( // 3. target ras (ras target wrong / class[2]) // 4. direction (br dir wrong / class[0]) - // Unforuantely we can't use PCD to infer the correctness of the BTB or RAS because the class prediction + // Unfortunately we can't use PCD to infer the correctness of the BTB or RAS because the class prediction // could be wrong or the fall through address selected for branch predict not taken. // By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of // both without the above inaccuracies. - // **** use BPBTAWrongM from BTB. + // **** use BPBTAWrongM from BTB. assign BTAWrongE = (BPBTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE; assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE; diff --git a/src/ifu/bpred/btb.sv b/src/ifu/bpred/btb.sv index 90246e0ea..2689b4128 100644 --- a/src/ifu/bpred/btb.sv +++ b/src/ifu/bpred/btb.sv @@ -1,7 +1,7 @@ /////////////////////////////////////////// // btb.sv // -// Written: Ross Thomposn ross1728@gmail.com +// Written: Ross Thompson ross1728@gmail.com // Created: February 15, 2021 // Modified: 24 January 2023 // @@ -34,19 +34,19 @@ module btb #(parameter Depth = 10 ) ( input logic clk, input logic reset, input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW, - input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM,// PC at various stages - output logic [`XLEN-1:0] BPBTAF, // BTB's guess at PC + input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, // PC at various stages + output logic [`XLEN-1:0] BPBTAF, // BTB's guess at PC output logic [`XLEN-1:0] BPBTAD, output logic [`XLEN-1:0] BPBTAE, - output logic [3:0] BTBIClassF, // BTB's guess at instruction class + output logic [3:0] BTBIClassF, // BTB's guess at instruction class // update - input logic IClassWrongM, // BTB's instruction class guess was wrong + input logic IClassWrongM, // BTB's instruction class guess was wrong input logic IClassWrongE, - input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb - input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb - input logic [3:0] InstrClassD, // Instruction class to insert into btb - input logic [3:0] InstrClassE, // Instruction class to insert into btb - input logic [3:0] InstrClassM, // Instruction class to insert into btb + input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb + input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb + input logic [3:0] InstrClassD, // Instruction class to insert into btb + input logic [3:0] InstrClassE, // Instruction class to insert into btb + input logic [3:0] InstrClassM, // Instruction class to insert into btb input logic [3:0] InstrClassW ); @@ -73,7 +73,7 @@ module btb #(parameter Depth = 10 ) ( // must output a valid PC and valid bit during reset. Because only PCF, not PCNextF is reset, PCNextF is invalid // during reset. The BTB must produce a non X PC1NextF to allow the simulation to run. - // While thie mux could be included in IFU it is not necessary for the IROM/I$/bus. + // While the mux could be included in IFU it is not necessary for the IROM/I$/bus. // For now it is optimal to leave it here. assign ResetPC = `RESET_VECTOR; assign PCNextFIndex = reset ? ResetPC[Depth+1:2] : {PCNextF[Depth+1] ^ PCNextF[1], PCNextF[Depth:2]}; From 34aedc4f798c05116f164c5213762849aab06630 Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Fri, 14 Apr 2023 14:14:34 -0700 Subject: [PATCH 17/20] indent fix --- src/generic/lzc.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generic/lzc.sv b/src/generic/lzc.sv index 7314b29e9..daf2bf077 100644 --- a/src/generic/lzc.sv +++ b/src/generic/lzc.sv @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module lzc #(parameter WIDTH = 1) ( - input logic [WIDTH-1:0] num, // number to count the leading zeroes of + input logic [WIDTH-1:0] num, // number to count the leading zeroes of output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes ); From 5952a4b0a30313a786b826c211535ac5772a9d12 Mon Sep 17 00:00:00 2001 From: Limnanthes Serafini Date: Fri, 14 Apr 2023 14:15:52 -0700 Subject: [PATCH 18/20] Final small fix --- src/generic/lzc.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generic/lzc.sv b/src/generic/lzc.sv index daf2bf077..aa5381a22 100644 --- a/src/generic/lzc.sv +++ b/src/generic/lzc.sv @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module lzc #(parameter WIDTH = 1) ( - input logic [WIDTH-1:0] num, // number to count the leading zeroes of + input logic [WIDTH-1:0] num, // number to count the leading zeroes of output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes ); From 862d1e01163611ec5337bc471cda4b5a450de47b Mon Sep 17 00:00:00 2001 From: Alec Vercruysse Date: Fri, 14 Apr 2023 16:54:55 -0700 Subject: [PATCH 19/20] replace instances of code duplication for i$ exclusions w/commands --- sim/coverage-exclusions-rv64gc.do | 11 +++++++++++ src/cache/cache.sv | 28 +++++++++------------------- src/cache/cacheway.sv | 20 ++++---------------- src/generic/mux.sv | 2 +- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index eb10505eb..374c4b917 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -62,6 +62,17 @@ coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $sta coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusW"] coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache SelAdrCauses"] -item e 1 -fecexprrow 4 10 coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusRCauses"] -item e 1 -fecexprrow 1-2 12 +# cache.sv AdrSelMux and CacheBusAdrMux, excluding unhit Flush branch +coverage exclude -scope /dut/core/ifu/bus/icache/icache/AdrSelMux -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheBusAdrMux -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 3 +# CacheWay Dirty logic. -scope does not accept wildcards. +set numcacheways 4 +for {set i 0} {$i < $numcacheways} {incr i} { + coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: icache SetDirtyWay"] -item e 1 + coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: icache SelectedWiteWordEn"] -item e 1 -fecexprrow 4 6 + # below: flushD can't go high during an icache write b/c of pipeline stall + coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: icache SetValidEN"] -item e 1 -fecexprrow 4 +} ###################### # Toggle exclusions diff --git a/src/cache/cache.sv b/src/cache/cache.sv index ea7504f23..57ff20ab3 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -73,6 +73,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE logic SelAdr; + logic [1:0] AdrSelMuxSel; logic [SETLEN-1:0] CacheSet; logic [LINELEN-1:0] LineWriteData; logic ClearDirty, SetDirty, SetValid; @@ -108,18 +109,10 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // and FlushAdr when handling D$ flushes // The icache must update to the newest PCNextF on flush as it is probably a trap. Trap // sets PCNextF to XTVEC and the icache must start reading the instruction. - if (!READ_ONLY_CACHE) begin - logic [1:0] AdrSelMuxSel; - assign AdrSelMuxSel = {SelFlush, SelAdr | SelHPTW}; - mux3 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr, + assign AdrSelMuxSel = {SelFlush, ((SelAdr | SelHPTW) & ~((READ_ONLY_CACHE == 1) & FlushStage))}; + mux3 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], FlushAdr, AdrSelMuxSel, CacheSet); - end - else begin - logic AdrSelMuxSel; - assign AdrSelMuxSel = ((SelAdr | SelHPTW) & ~FlushStage); - mux2 #(SETLEN) AdrSelMux(NextSet[SETTOP-1:OFFSETLEN], PAdr[SETTOP-1:OFFSETLEN], - AdrSelMuxSel, CacheSet); - end + // Array of cache ways, along with victim, hit, dirty, and read merging logic cacheway #(NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0]( .clk, .reset, .CacheEn, .CacheSet, .PAdr, .LineWriteData, .LineByteMask, @@ -159,14 +152,11 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE .PAdr(WordOffsetAddr), .ReadDataLine, .ReadDataWord); // Bus address for fetch, writeback, or flush writeback - if (!READ_ONLY_CACHE) - mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), - .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); - else - assign CacheBusAdr = {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}}}), + .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), + .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); + ///////////////////////////////////////////////////////////////////////////////////////////// // Write Path ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 106905939..77e844b20 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -97,22 +97,10 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, ///////////////////////////////////////////////////////////////////////////////////////////// assign SetValidWay = SetValid & SelData; - if (!READ_ONLY_CACHE) begin - assign SetDirtyWay = SetDirty & SelData; - assign ClearDirtyWay = ClearDirty & SelData; - assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; - assign SetValidEN = SetValidWay & ~FlushStage; - end - else begin - // Don't cover FlushStage assertion during SetValidWay. - // it's not explicitely gated anywhere, but for read-only caches, - // there's no way that a FlushD can happen during the write stage - // of a fetch. - // coverage off -item e 1 -fecexprrow 4 - assign SelectedWriteWordEn = SetValidWay & ~FlushStage; - // coverage off -item e 1 -fecexprrow 4 - assign SetValidEN = SetValidWay & ~FlushStage; - end + assign SetDirtyWay = SetDirty & SelData; // exclusion-tag: icache SetDirtyWay + assign ClearDirtyWay = ClearDirty & SelData; + assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn + assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: icache SetValidEN // If writing the whole line set all write enables to 1, else only set the correct word. assign FinalByteMask = SetValidWay ? '1 : LineByteMask; // OR diff --git a/src/generic/mux.sv b/src/generic/mux.sv index 636c19c9f..223d41afc 100644 --- a/src/generic/mux.sv +++ b/src/generic/mux.sv @@ -40,7 +40,7 @@ module mux3 #(parameter WIDTH = 8) ( input logic [1:0] s, output logic [WIDTH-1:0] y); - assign y = s[1] ? d2 : (s[0] ? d1 : d0); + assign y = s[1] ? d2 : (s[0] ? d1 : d0); // exclusion-tag: mux3 endmodule module mux4 #(parameter WIDTH = 8) ( From 34dd481f93b222d5835e4e9b8732272727432d02 Mon Sep 17 00:00:00 2001 From: Diego Herrera Vicioso Date: Sat, 15 Apr 2023 23:13:39 -0700 Subject: [PATCH 20/20] Added test coverage for reads to HPM counters and added exclusions for impossible cases in rv64gc --- src/privileged/csrsr.sv | 3 +++ src/privileged/trap.sv | 3 +++ tests/coverage/priv.S | 59 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/privileged/csrsr.sv b/src/privileged/csrsr.sv index 94c72a134..60968a68b 100644 --- a/src/privileged/csrsr.sv +++ b/src/privileged/csrsr.sv @@ -198,9 +198,12 @@ module csrsr ( STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED; STATUS_MBE <= #1 nextMBE; STATUS_SBE <= #1 nextSBE; + // coverage off + // MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc end else if (WriteMSTATUSHM) begin STATUS_MBE <= #1 CSRWriteValM[5] & `BIGENDIAN_SUPPORTED; STATUS_SBE <= #1 CSRWriteValM[4] & `S_SUPPORTED & `BIGENDIAN_SUPPORTED; + // coverage on end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits STATUS_MXR_INT <= #1 CSRWriteValM[19]; STATUS_SUM_INT <= #1 CSRWriteValM[18]; diff --git a/src/privileged/trap.sv b/src/privileged/trap.sv index bc1f329df..96b404ef9 100644 --- a/src/privileged/trap.sv +++ b/src/privileged/trap.sv @@ -81,11 +81,14 @@ module trap ( /////////////////////////////////////////// assign BothInstrAccessFaultM = InstrAccessFaultM | HPTWInstrAccessFaultM; + // coverage off -item e 1 -fecexprrow 2 + // excludes InstrMisalignedFaultM from coverage of this line, since misaligned instructions cannot occur in rv64gc. assign ExceptionM = InstrMisalignedFaultM | BothInstrAccessFaultM | IllegalInstrFaultM | LoadMisalignedFaultM | StoreAmoMisalignedFaultM | InstrPageFaultM | LoadPageFaultM | StoreAmoPageFaultM | BreakpointFaultM | EcallFaultM | LoadAccessFaultM | StoreAmoAccessFaultM; + // coverage on assign TrapM = ExceptionM | InterruptM; assign RetM = mretM | sretM; diff --git a/tests/coverage/priv.S b/tests/coverage/priv.S index 6ab5951b4..94b7cd0ef 100644 --- a/tests/coverage/priv.S +++ b/tests/coverage/priv.S @@ -142,6 +142,65 @@ main: # Test writes to floating point CSRs csrw frm, t0 csrw fflags, t0 + + # CSRC MCOUNTEREN Register + # Go to machine mode + li a0, 3 + ecall + # Activate HPM3 + li t0, -1 + csrw mcounteren, t0 + csrw scounteren, t0 + + # Go to supervisor + li a0, 1 + ecall + #try to write to HPMs + csrw 333, t0 + #go to user mode + li a0, 0 + ecall + csrr t0, hpmcounter22 + + # setting registers bits to 0 + li a0, 3 # back to machine mode + ecall + li t0, 0 + csrw mcounteren, t0 + csrw scounteren, t0 + + # Write to satp when status.TVM is 1 from machine mode + bseti t0, zero, 20 + csrs mstatus, t0 + + csrw satp, t0 + + + + # Test checking privilege for reading counters (using counter 22 as an example) + + # Go to machine mode + li a0, 3 + ecall + + # Set SCOUNTEREN to all 0s, MCOUNTEREN to all 1s + li t0, 0 + csrw scounteren, t0 + li t1, -1 + csrw mcounteren, t1 + + # Go to supervisor mode + li a0, 1 + ecall + + # try to read from HPM22 + csrr t0, hpmcounter22 + + # go to user mode + li a0, 0 + ecall + + csrr t0, hpmcounter22 j done