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