Files
gem5/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm
Minje Jun e141d9e4d0 mem-ruby: Writeback CHI UD_RU line at local evict
In Ruby CHI protocol UD_RU state means the line is in UD state in
the local cache and the upstream may have it in UD or UC state.
In the previous implementation UD_RU line was just dropped without
WriteBack which can cause loss of dirty data when the upstream has it
in UC state.
This commit fixes it by performing WriteBack when evciting UD_RU line.

Change-Id: I1db9b4f95cc576e71dcef38b01de24775df514ba
2024-02-08 18:47:44 +09:00

1710 lines
41 KiB
Plaintext

/*
* Copyright (c) 2021-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
////////////////////////////////////////////////////////////////////////////
// CHI-cache transition definition
////////////////////////////////////////////////////////////////////////////
// Allocate resources and move to the ready queue
transition({I,SC,UC,SD,UD,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC
BUSY_INTR,BUSY_BLKD}, AllocRequest) {
AllocateTBE_Request;
}
transition({I,SC,UC,SD,UD,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC
BUSY_INTR,BUSY_BLKD}, AllocRequestWithCredit) {
AllocateTBE_Request_WithCredit;
}
transition({I,SC,UC,SD,UD,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC
BUSY_INTR,BUSY_BLKD}, SendRetryAck) {
Send_RetryAck;
Pop_RetryTriggerQueue;
}
transition({I,SC,UC,SD,UD,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC
BUSY_INTR,BUSY_BLKD}, SendPCrdGrant) {
Send_PCrdGrant;
Pop_RetryTriggerQueue;
}
transition({I,SC,UC,SD,UD,UD_T,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC
BUSY_INTR,BUSY_BLKD}, AllocSnoop) {
AllocateTBE_Snoop;
}
transition({I}, AllocDvmSnoop) {
AllocateTBE_DvmSnoop;
}
transition({UD,UD_T,SD,UC,SC,I,BUSY_INTR,BUSY_BLKD}, AllocSeqRequest) {
AllocateTBE_SeqRequest;
}
// You can't allocate a DVM request on the same TBE as another DVM request,
// so we don't need a long "Transition-from" list and we can change the output state.
transition({I}, AllocSeqDvmRequest) {
AllocateTBE_SeqDvmRequest;
}
transition({I,SC,UC,SD,UD,UD_T,RU,RSC,RSD,RUSD,SC_RSC,SD_RSC,SD_RSD,UC_RSC,UC_RU,UD_RU,UD_RSD,UD_RSC,RUSC
BUSY_INTR,BUSY_BLKD}, AllocPfRequest) {
AllocateTBE_PfRequest;
}
transition({BUSY_INTR,BUSY_BLKD}, TagArrayRead) {TagArrayRead} {
Pop_TriggerQueue;
TagArrayRead;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, TagArrayWrite) {TagArrayWrite} {
Pop_TriggerQueue;
TagArrayWrite;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, DataArrayRead) {DataArrayRead} {
Pop_TriggerQueue;
DataArrayRead;
ProcessNextState_ClearPending;
}
// goes to BUSY_INTR as we may need to accept snoops while waiting
// on potential replacement
transition({BUSY_INTR,BUSY_BLKD}, CheckCacheFill, BUSY_INTR) {
CheckCacheFill;
// CheckCacheFill either does Pop_TriggerQueue+ProcessNextState_ClearPending
// or a stall depending on block availability
}
transition({BUSY_INTR,BUSY_BLKD}, DataArrayWrite) {DataArrayWrite} {
Pop_TriggerQueue;
DataArrayWrite;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, DataArrayWriteOnFill) {DataArrayWrite} {
Pop_TriggerQueue;
Profile_Fill;
DataArrayWrite;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, ReadHitPipe) {
Pop_TriggerQueue;
ReadHitPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, ReadMissPipe) {
Pop_TriggerQueue;
ReadMissPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, WriteFEPipe) {
Pop_TriggerQueue;
WriteFEPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, WriteBEPipe) {
Pop_TriggerQueue;
WriteBEPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, FillPipe) {
Pop_TriggerQueue;
FillPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, DelayAtomic) {
Pop_TriggerQueue;
DelayAtomic;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, SnpSharedPipe) {
Pop_TriggerQueue;
SnpSharedPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, SnpInvPipe) {
Pop_TriggerQueue;
SnpInvPipe;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR,BUSY_BLKD}, SnpOncePipe) {
Pop_TriggerQueue;
SnpOncePipe;
ProcessNextState_ClearPending;
}
// ReadShared / ReadNotSharedDirty
transition(I, {ReadShared,ReadNotSharedDirty}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadShared_Miss;
Allocate_DirEntry;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSC,RUSC}, {ReadShared,ReadNotSharedDirty}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadShared_HitUpstream_NoOwner;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,SD,UC,SC}, {ReadShared,ReadNotSharedDirty}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadShared_Hit;
Allocate_DirEntry;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RSC,SD_RSC,UC_RSC,SC_RSC,UD_RSD,SD_RSD}, {ReadShared,ReadNotSharedDirty}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadShared_Hit;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RU,UC_RU,RU,RSD,RUSD}, {ReadShared,ReadNotSharedDirty}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadShared_HitUpstream;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// ReadOnce
transition(I, ReadOnce, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadOnce_Miss;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,SD,UC,SC,UD_RSC,SD_RSC,UC_RSC,SC_RSC,UD_RSD,SD_RSD}, ReadOnce, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadOnce_Hit;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RU,UC_RU,RU,RSD,RUSD,RSC,RUSC}, ReadOnce, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadOnce_HitUpstream;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// ReadUnique
transition(I, {ReadUnique,ReadUnique_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_Miss;
Allocate_DirEntry;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,UC}, {ReadUnique,ReadUnique_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_Hit;
Allocate_DirEntry;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RSC,UC_RSC,UD_RSD}, {ReadUnique,ReadUnique_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_Hit_InvUpstream;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RU,UC_RU,RU,RUSD,RUSC}, {ReadUnique,ReadUnique_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_HitUpstream;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SC,SD}, ReadUnique_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_AutoUpgrade;
Initiate_ReadUnique_Hit;
Allocate_DirEntry;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SC_RSC, SD_RSC, SD_RSD}, ReadUnique_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_AutoUpgrade;
Initiate_ReadUnique_Hit_InvUpstream;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSC,RSD}, ReadUnique_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_AutoUpgrade;
Initiate_ReadUnique_HitUpstream;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SC,SD}, ReadUnique, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_Upgrade;
Allocate_DirEntry;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SC_RSC, SD_RSC, RSC, SD_RSD, RSD}, ReadUnique, BUSY_BLKD) {
Initiate_Request;
Initiate_ReadUnique_Upgrade;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// CleanUnique
transition({I, SC, UC, SD, UD, RU, RSC, RSD, RUSD, RUSC,
SC_RSC, SD_RSD, SD_RSC, UC_RSC, UC_RU, UD_RU, UD_RSD, UD_RSC}, CleanUnique, BUSY_BLKD) {
Initiate_Request;
Initiate_CleanUnique;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({I, SC, UC, SD, UD, RU, RSC, RSD, RUSD, RUSC,
SC_RSC, SD_RSD, SD_RSC, UC_RSC, UC_RU, UD_RU, UD_RSD, UD_RSC},
CleanUnique_Stale, BUSY_BLKD) {
Initiate_Request_Stale;
Initiate_CleanUnique_Stale;
Pop_ReqRdyQueue;
ProcessNextState;
}
// WriteUniqueZero cacheline not present
transition({I,RU,RSC,RSD,RUSD,RUSC},
WriteUniqueZero,
BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_Zero;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// WriteUniqueZero cacheline available
transition({SC,UC,SD,UD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD},
WriteUniqueZero,
BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_Zero;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
// WriteUniquePtl
transition({UD,UD_RSD,UD_RSC,UC,UC_RSC},
{WriteUnique, WriteUniquePtl_PoC, WriteUniqueFull_PoC, WriteUniqueFull_PoC_Alloc},
BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_LocalWrite;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RU,UC_RU},
{WriteUnique, WriteUniquePtl_PoC, WriteUniqueFull_PoC, WriteUniqueFull_PoC_Alloc},
BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_LocalWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SD, SD_RSD, SD_RSC, SC, SC_RSC},
{WriteUniquePtl_PoC, WriteUniqueFull_PoC, WriteUniqueFull_PoC_Alloc},
BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_LocalWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSC,RSD,RUSD,RUSC,RU,I}, WriteUniqueFull_PoC_Alloc, BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_LocalWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SD, SD_RSD, SD_RSC, SC, SC_RSC},
{WriteUnique}, BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_LocalWrite_AfterUpgrade;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSD,RUSD,RUSC,RU}, {WriteUniquePtl_PoC, WriteUniqueFull_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_Writeback;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSC,I}, {WriteUniquePtl_PoC, WriteUniqueFull_PoC}, BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_PartialWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({RSC,RSD,RUSD,RUSC,RU,I}, WriteUnique, BUSY_BLKD) {
Initiate_Request;
Initiate_WriteUnique_Forward;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// AtomicReturn and AtomicNoReturn
transition({I,SC,SC_RSC,SD,SD_RSD,SD_RSC,RSD,RUSD,
UD,UD_RSC,UD_RSD,UD_RU,UC,UC_RSC,UC_RU,RSC,RU}, AtomicReturn, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_Forward;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({I,SC,SC_RSC,SD,SD_RSD,SD_RSC,RSD,RUSD,
UD,UD_RSC,UD_RSD,UD_RU,UC,UC_RSC,UC_RU,RSC,RU}, AtomicNoReturn, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_Forward;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,UD_RU,UD_RSD,UD_RSC,UC,UC_RU,UC_RSC},
AtomicReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_LocalWrite;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,UD_RU,UD_RSD,UD_RSC,UC,UC_RU,UC_RSC},
AtomicNoReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_LocalWrite;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SD, SD_RSD, SD_RSC, SC, SC_RSC, RSC, RSD, RUSC, RUSD, RU},
AtomicReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_LocalWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SD, SD_RSD, SD_RSC, SC, SC_RSC, RSC, RSD, RUSC, RUSD, RU},
AtomicNoReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_LocalWrite;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(I, AtomicReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_Miss;
Allocate_DirEntry;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(I, AtomicNoReturn_PoC, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_Miss;
Allocate_DirEntry;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// Load / Store / Atomic from sequencer & Prefetch from prefetcher
transition({UD,UD_T,SD,UC,SC}, Load, BUSY_BLKD) {
Initiate_Request;
Initiate_LoadHit;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
// Prefetch hits if either this cache or one of its upstream caches has a
// valid block.
// In some states, using the normal hit path for a prefetch will deallocate
// the local cache entry at the end since our data is stale. If the cache is
// inclusive for unique data we need to keep the block, so just bypass the
// normal path.
transition({UD,UD_T,SD,UC,SC,RU,RSC,RSD,RUSC,RUSD,SC_RSC,SD_RSC,SD_RSD,UC_RSC,UC_RU,UD_RU,UD_RSD,UD_RSC}, Prefetch) {
Callback_ExpressPrefetchHit;
Pop_ReqRdyQueue;
}
transition(BUSY_BLKD, LoadHit) {
Pop_TriggerQueue;
Callback_LoadHit;
ProcessNextState_ClearPending;
}
transition({UD,UD_T,UC}, Store, BUSY_BLKD) {
Initiate_Request;
Initiate_StoreHit;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(BUSY_BLKD, StoreHit) {
Pop_TriggerQueue;
Callback_StoreHit;
ProcessNextState_ClearPending;
}
transition(UC, {AtomicLoad,AtomicStore}, BUSY_BLKD) {
Initiate_Request;
Initiate_Atomic_UC;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD,UD_T}, {AtomicLoad,AtomicStore}, BUSY_BLKD) {
Initiate_Request;
Initiate_Atomic_UD;
Profile_Hit;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(BUSY_BLKD, AtomicHit) {
Pop_TriggerQueue;
Callback_AtomicHit;
ProcessNextState_ClearPending;
}
transition(I, {Load,Prefetch}, BUSY_BLKD) {
Initiate_Request;
Initiate_LoadMiss;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(I, Store, BUSY_BLKD) {
Initiate_Request;
Initiate_StoreMiss;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({SD,SC}, Store, BUSY_BLKD) {
Initiate_Request;
Initiate_StoreUpgrade;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// write timeout
transition(UD_T, UseTimeout, UD) {
Unset_Timeout_Cache;
}
transition({BUSY_BLKD,BUSY_INTR}, UseTimeout) {
Unset_Timeout_TBE;
}
transition(I, AtomicLoad, BUSY_BLKD){
Initiate_Request;
Initiate_AtomicReturn_I;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(I, AtomicStore, BUSY_BLKD){
Initiate_Request;
Initiate_AtomicNoReturn_I;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(SD, AtomicLoad, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_SD;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(SC, AtomicLoad, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicReturn_SC;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(SD, AtomicStore, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_SD;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(SC, AtomicStore, BUSY_BLKD) {
Initiate_Request;
Initiate_AtomicNoReturn_SC;
Profile_Miss;
Pop_ReqRdyQueue;
ProcessNextState;
}
// Evict from Upstream
transition({UD_RSC,SD_RSC,UC_RSC,SC_RSC,RSC,RSD,RUSD,RUSC,UD_RSD,SD_RSD}, Evict, BUSY_BLKD) {
Initiate_Request;
Initiate_Evict;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD, UD_RSC, SD_RSC, UC_RSC, SC_RSC, UD_RU, UC_RU, UD_RSD, SD_RSD, RU, RSC, RSD, RUSD, RUSC, SD, UC, SC, I},
Evict_Stale) {
Initiate_Request_Stale;
Send_CompI_Stale;
Finalize_DeallocateRequest;
Pop_ReqRdyQueue;
}
// WriteBack from upstream
transition({UD_RU, UC_RU, RU, UD_RSD, SD_RSD, RSD, RUSD}, {WriteBackFull, WriteCleanFull}, BUSY_BLKD) {
Initiate_Request;
Initiate_CopyBack;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RU, UC_RU, RU}, WriteEvictFull, BUSY_BLKD) {
Initiate_Request;
Initiate_CopyBack;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition({UD_RSC, UC_RSC, SC_RSC, SD_RSC, UD, RU, RSD, RUSD, RUSC, UD_RSD, SD_RSD, RSC, UD_RU, UC_RU, SD, UC, SC, I},
{WriteBackFull_Stale, WriteEvictFull_Stale, WriteCleanFull_Stale}, BUSY_BLKD) {
Initiate_Request_Stale;
Initiate_CopyBack_Stale;
Pop_ReqRdyQueue;
ProcessNextState;
}
// Cache Replacement
// When in UC_RU,UD_RSD,SD_RSD we also just drop the line since an upstream
// cache has an up-to-data line that it will either WriteBack or WriteEvict
transition({SC,UC,SC_RSC,UC_RSC,
UC_RU,UD_RSD,SD_RSD}, LocalHN_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_JustDrop;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition({UD,SD,UD_RU,UD_RSC,SD_RSC}, LocalHN_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_WB;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition(SC, Local_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_Evict;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition({UD,SD,UC}, Local_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_WB;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition({UC_RU,UD_RSD,SD_RSD,SC_RSC,UC_RSC}, Local_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_JustDrop;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition({UD_RU,UD_RSC,SD_RSC}, Local_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_WB;
Profile_Eviction;
Deallocate_CacheBlock;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition({UD_RSC,SD_RSC,UC_RSC,UD_RU,UC_RU,UD_RSD}, Global_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_WB_BackInvalidate;
Profile_Eviction;
Deallocate_CacheBlock;
Deallocate_DirEntry;
Pop_ReplTriggerQueue;
ProcessNextState;
}
transition(SC_RSC, Global_Eviction, BUSY_BLKD) {ReplTBEAvailable} {
Initiate_Replacement;
Initiate_Replacement_Evict_BackInvalidte;
Profile_Eviction;
Deallocate_CacheBlock;
Deallocate_DirEntry;
Pop_ReplTriggerQueue;
ProcessNextState;
}
// This could happen if enqueued the eviction when the line was busy
// or couldn't handle it immediately due to no TBE available
transition({RU,RSC,RSD,RUSC,RUSD,I}, {Local_Eviction, LocalHN_Eviction}) {
Pop_ReplTriggerQueue;
}
transition(I, Global_Eviction) {
Pop_ReplTriggerQueue;
}
// Snoops
// SnpCleanInvalid/SnpUnique/SnpUniqueFwd
// All invalidating snoops have a simular behavior
transition({UD,SD,UC,SC,UD_RSC,SD_RSC,UC_RSC,UD_RU,UC_RU,RU,RUSD,RUSC,RSD,UD_RSD,SD_RSD,SC_RSC,RSC},
{SnpUnique,SnpUniqueFwd,SnpCleanInvalid}, BUSY_BLKD) {
Initiate_Snoop;
Initiate_InvalidationSnoop;
Profile_Eviction;
Pop_SnoopRdyQueue;
ProcessNextState;
}
transition(BUSY_INTR, {SnpUnique,SnpUniqueFwd,SnpCleanInvalid}, BUSY_BLKD) {
Initiate_Snoop_Hazard;
Initiate_InvalidationSnoop;
Profile_Eviction;
Pop_SnoopRdyQueue;
ProcessNextState;
}
// SnpShared / SnpNotSharedDirty
transition({UD,UD_RSC,SD,SD_RSC,UC,UC_RSC,UD_RU,UC_RU,RU,UD_RSD,SD_RSD,RSD,RUSD,RUSC},
{SnpShared,SnpSharedFwd,SnpNotSharedDirtyFwd}, BUSY_BLKD) {
Initiate_Snoop;
Initiate_SnpShared;
Pop_SnoopRdyQueue;
ProcessNextState;
}
transition({SC, SC_RSC, RSC}, {SnpSharedFwd, SnpNotSharedDirtyFwd}, BUSY_BLKD) {
Initiate_Snoop;
Initiate_SnpShared;
Pop_SnoopRdyQueue;
ProcessNextState;
}
transition(BUSY_INTR, {SnpShared,SnpSharedFwd,SnpNotSharedDirtyFwd}, BUSY_BLKD) {
Initiate_Snoop_Hazard;
Initiate_SnpShared;
Pop_SnoopRdyQueue;
ProcessNextState;
}
// SnpOnce
transition({UD,UD_T,UD_RSC,UD_RU,UD_RSD,SD,SD_RSC,SD_RSD,UC,UC_RSC,UC_RU,SC,SC_RSC,RU,RSC,RSD,RUSD,RUSC},
{SnpOnce,SnpOnceFwd}, BUSY_BLKD) {
Initiate_Snoop;
Initiate_SnpOnce;
Pop_SnoopRdyQueue;
ProcessNextState;
}
transition(BUSY_INTR, {SnpOnce,SnpOnceFwd}, BUSY_BLKD) {
Initiate_Snoop_Hazard;
Initiate_SnpOnce;
Pop_SnoopRdyQueue;
ProcessNextState;
}
// Stash
transition({I,SC,UC,SD,UD,RU,RSC,RSD,RUSD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD,RUSC},
{StashOnceShared,StashOnceUnique}, BUSY_BLKD) {
Initiate_Request;
Send_CompI;
Pop_ReqRdyQueue;
ProcessNextState;
}
// Stalls
transition({BUSY_BLKD,BUSY_INTR},
{ReadShared, ReadNotSharedDirty, ReadUnique, ReadUnique_PoC,
ReadOnce, CleanUnique, CleanUnique_Stale,
Load, Store, AtomicLoad, AtomicStore, Prefetch,
WriteBackFull, WriteBackFull_Stale,
WriteEvictFull, WriteEvictFull_Stale,
WriteCleanFull, WriteCleanFull_Stale,
Evict, Evict_Stale,
WriteUnique,WriteUniquePtl_PoC,
WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc,
WriteUniqueZero,
AtomicReturn,AtomicReturn_PoC,
AtomicNoReturn,AtomicNoReturn_PoC,
StashOnceShared,StashOnceUnique}) {
StallRequest;
}
transition({BUSY_BLKD,BUSY_INTR},
{Global_Eviction, Local_Eviction, LocalHN_Eviction}) {
StallLocalEviction;
}
// Kill the timer and try again as a snoop may be pending as well
transition(UD_T, {Global_Eviction, Local_Eviction, LocalHN_Eviction}, UD) {
Unset_Timeout_Cache;
Pop_ReplTriggerQueue;
}
transition(BUSY_BLKD,
{SnpCleanInvalid,SnpShared,SnpUnique,SnpSharedFwd,SnpUniqueFwd,
SnpOnce,SnpOnceFwd,SnpNotSharedDirtyFwd}) {
StallSnoop;
}
transition({BUSY_BLKD,BUSY_INTR}, SnpStalled) {
StallSnoop;
}
transition(UD_T, {SnpCleanInvalid,SnpShared,SnpUnique,SnpSharedFwd,SnpUniqueFwd,
SnpNotSharedDirtyFwd}) {
StallSnoop_NoTBE;
}
transition({BUSY_BLKD,BUSY_INTR}, ActionStalledOnHazard) {
StallActionOnHazard;
}
// Trigger-specifc transitions
transition(BUSY_BLKD, SendWriteBackOrWriteEvict, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_WriteBackOrWriteEvict;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWriteClean, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_WriteCleanFull;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWriteUnique, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_WriteUnique;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendAtomicReturn, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_AtomicReturn;
CheckARComp;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendAtomicReturn_NoWait, BUSY_INTR) {
Pop_TriggerQueue;
Send_AtomicReturn_NoWait;
CheckARComp;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendAtomicNoReturn, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_AtomicNoReturn;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWriteNoSnp, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_WriteNoSnp;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWriteNoSnpPartial, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_WriteNoSnp_Partial;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendEvict, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_Evict;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
// May get here from BUSY_INTR
transition({BUSY_BLKD, BUSY_INTR}, SendCompData, BUSY_BLKD) {
Pop_TriggerQueue;
Send_CompData;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWBData) {
Pop_TriggerQueue;
Send_WBData;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWUData) {
Pop_TriggerQueue;
Send_WUData;
CheckWUComp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendWUDataCB) {
Pop_TriggerQueue;
Callback_WriteUnique;
Send_WUData;
CheckWUComp;
ProcessNextState_ClearPending;
}
transition({BUSY_BLKD,BUSY_INTR}, SendARData) {
Pop_TriggerQueue;
Send_ARData;
ProcessNextState_ClearPending;
}
transition({BUSY_BLKD,BUSY_INTR}, SendANRData) {
Pop_TriggerQueue;
Callback_AtomicNoReturn;
Send_ANRData;
CheckANRComp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendInvSnpResp) {
Pop_TriggerQueue;
Send_InvSnpResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpData) {
Pop_TriggerQueue;
Send_SnpRespData;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpUniqueFwdCompData) {
Pop_TriggerQueue;
Send_CompData_SnpUniqueFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpSharedFwdCompData) {
Pop_TriggerQueue;
Send_CompData_SnpSharedFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpNotSharedDirtyFwdCompData) {
Pop_TriggerQueue;
Send_CompData_SnpNSDFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpOnceFwdCompData) {
Pop_TriggerQueue;
Send_CompData_SnpOnceFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpFwdedData) {
Pop_TriggerQueue;
Send_SnpRespDataFwded;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpFwdedResp) {
Pop_TriggerQueue;
Send_FwdSnpResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompAck) {
Pop_TriggerQueue;
Send_CompAck;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpIResp) {
Pop_TriggerQueue;
Send_SnpRespI;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompIResp) {
Pop_TriggerQueue;
Send_CompI;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompUCResp) {
Pop_TriggerQueue;
Send_CompUC;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompUCRespStale) {
Pop_TriggerQueue;
Send_CompUC_Stale;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendRespSepData) {
Pop_TriggerQueue;
Send_RespSepData;
ProcessNextState_ClearPending;
}
transition({BUSY_INTR, BUSY_BLKD}, WaitCompAck) {
Pop_TriggerQueue;
ExpectCompAck;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, RestoreFromHazard, BUSY_INTR) {
Pop_TriggerQueue;
RestoreFromHazard;
}
transition(BUSY_BLKD, SendReadShared, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_ReadShared;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendReadOnce, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_ReadOnce;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendReadUnique, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_ReadUnique;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCleanUnique, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_CleanUnique;
Profile_OutgoingStart;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendReadNoSnp, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_ReadNoSnp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendReadNoSnpDMT, BUSY_INTR) {DestinationAvailable} {
Pop_TriggerQueue;
Send_ReadNoSnpDMT;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpShared) {
Pop_TriggerQueue;
Send_SnpShared;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpSharedFwdToOwner) {
Pop_TriggerQueue;
Send_SnpSharedFwd_ToOwner;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpSharedFwdToSharer) {
Pop_TriggerQueue;
Send_SnpSharedFwd_ToSharer;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpOnceFwd) {
Pop_TriggerQueue;
Send_SnpOnceFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpOnce) {
Pop_TriggerQueue;
Send_SnpOnce;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpUnique) {
Pop_TriggerQueue;
Send_SnpUnique;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpUniqueRetToSrc) {
Pop_TriggerQueue;
Send_SnpUnique_RetToSrc;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpUniqueFwd) {
Pop_TriggerQueue;
Send_SnpUniqueFwd;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpCleanInvalid) {
Pop_TriggerQueue;
Send_SnpCleanInvalid;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendSnpCleanInvalidNoReq) {
Pop_TriggerQueue;
Send_SnpCleanInvalid_NoReq;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompDBIDResp) {
Pop_TriggerQueue;
Send_CompDBIDResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompDBIDResp_WU) {
Pop_TriggerQueue;
ExpectNCBWrData;
Send_CompDBIDResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendDBIDResp_WUZ) {
Pop_TriggerQueue;
Send_DBIDResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendDBIDResp_WU) {
Pop_TriggerQueue;
ExpectNCBWrData;
Send_DBIDResp;
ProcessNextState_ClearPending;
}
transition({BUSY_BLKD,BUSY_INTR}, SendComp_WU) {
Pop_TriggerQueue;
Send_Comp_WU;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompDBIDResp_ANR) {
Pop_TriggerQueue;
ExpectNCBWrData_A;
Send_CompDBIDResp;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendDBIDResp_AR) {
Pop_TriggerQueue;
ExpectNCBWrData_A;
Send_DBIDResp;
ProcessNextState_ClearPending;
}
transition({BUSY_BLKD,BUSY_INTR}, SendCompData_AR) {
Pop_TriggerQueue;
Send_CompData_AR;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, SendCompDBIDRespStale) {
Pop_TriggerQueue;
Send_CompDBIDResp_Stale;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, MaintainCoherence) {
Pop_TriggerQueue;
Initiate_MaintainCoherence;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, FinishCleanUnique) {
Pop_TriggerQueue;
Finish_CleanUnique;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, FinishCopyBack_Stale) {
Pop_TriggerQueue;
Finish_CopyBack_Stale;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, CheckUpgrade_FromStore) {
Pop_TriggerQueue;
Callback_Miss; // note: Callback happens only if tbe.dataValid
CheckUpgrade_FromStoreOrRU;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, CheckUpgrade_FromCU) {
Pop_TriggerQueue;
CheckUpgrade_FromCU;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, CheckUpgrade_FromRU) {
Pop_TriggerQueue;
CheckUpgrade_FromStoreOrRU;
ProcessNextState_ClearPending;
}
// Generic send/receive transitions
// waiting for data
transition(BUSY_BLKD,
{CBWrData_I,CBWrData_SC,CBWrData_SD_PD,CBWrData_UC,CBWrData_UD_PD}) {
Receive_ReqDataResp;
UpdateDirState_FromReqDataResp;
UpdateDataState_FromReqDataResp;
Pop_DataInQueue;
ProcessNextState;
}
// could be waiting for both data and CompDBIDResp on a WriteUnique
transition({BUSY_BLKD,BUSY_INTR}, NCBWrData) {
Receive_ReqDataResp;
UpdateDataState_FromWUDataResp;
UpdateDataState_FromADataResp;
Pop_DataInQueue;
ProcessNextState;
}
transition(BUSY_BLKD,
{SnpRespData_I_PD,SnpRespData_I,SnpRespData_SC_PD,
SnpRespData_SC,SnpRespData_SD,SnpRespData_UC,SnpRespData_UD,
SnpRespData_SC_Fwded_SC,SnpRespData_SC_Fwded_SD_PD,
SnpRespData_SC_PD_Fwded_SC,SnpRespData_I_Fwded_SD_PD,
SnpRespData_I_PD_Fwded_SC,SnpRespData_I_Fwded_SC}) {
Receive_SnpDataResp;
UpdateDirState_FromSnpDataResp;
UpdateDataState_FromSnpDataResp;
Pop_DataInQueue;
ProcessNextState;
}
transition({BUSY_BLKD,BUSY_INTR}, RespSepData, BUSY_BLKD) {
Receive_RespSepData;
Pop_RespInQueue;
ProcessNextState;
}
transition({BUSY_BLKD,BUSY_INTR}, DataSepResp_UC, BUSY_BLKD) {
Receive_ReqDataResp;
UpdateDataState_FromReqDataResp;
Callback_Miss;
Profile_OutgoingEnd_DataResp;
Pop_DataInQueue;
ProcessNextState;
}
transition({BUSY_BLKD,BUSY_INTR},
{CompData_I,CompData_SC,CompData_SD_PD,CompData_UC,CompData_UD_PD},
BUSY_BLKD) {
Receive_RespSepDataFromCompData;
Receive_ReqDataResp;
UpdateDataState_FromReqDataResp;
Callback_Miss;
Profile_OutgoingEnd_DataResp;
Pop_DataInQueue;
ProcessNextState;
}
transition(BUSY_INTR, ReadReceipt, BUSY_BLKD) {
Receive_ReadReceipt;
Pop_RespInQueue;
ProcessNextState;
}
// Retry handling
transition(BUSY_INTR, {RetryAck, RetryAck_PoC}) {
Receive_RetryAck;
Pop_RespInQueue;
ProcessNextState;
}
transition(BUSY_INTR, {PCrdGrant, PCrdGrant_PoC}) {
Receive_PCrdGrant;
Pop_RespInQueue;
ProcessNextState;
}
// RetryAck/PCrdGrant on BUSY_BLKD is only expected in a PoC/HN when waiting
// for CompAck after sending down a request with DMT enabled. Handle the same
// as BUSY_INTR
transition(BUSY_BLKD, RetryAck_PoC) {
Receive_RetryAck;
Pop_RespInQueue;
ProcessNextState;
}
transition(BUSY_BLKD, PCrdGrant_PoC) {
Receive_PCrdGrant;
Pop_RespInQueue;
ProcessNextState;
}
// RetryAck/PCrdGrant received during a snoop hazard may arrive in both
// BUSY_BLKD and BUSY_INTR
transition({BUSY_INTR,BUSY_BLKD}, {RetryAck_Hazard, RetryAck_PoC_Hazard}) {
Receive_RetryAck_Hazard;
Pop_RespInQueue;
ProcessNextState;
}
transition({BUSY_INTR,BUSY_BLKD}, {PCrdGrant_Hazard, PCrdGrant_PoC_Hazard}) {
Receive_PCrdGrant_Hazard;
Pop_RespInQueue;
ProcessNextState;
}
// Resend the request after RetryAck+PCrdGrant received
transition({BUSY_INTR,BUSY_BLKD}, DoRetry) {
Send_Retry;
Pop_RetryTriggerQueue;
}
transition({BUSY_INTR,BUSY_BLKD}, DoRetry_Hazard) {
Send_Retry_Hazard;
Pop_RetryTriggerQueue;
}
// waiting for completion ack
transition({BUSY_BLKD,BUSY_INTR}, CompAck) {
Receive_ReqResp;
UpdateDirState_FromReqResp;
Pop_RespInQueue;
ProcessNextState;
}
transition(BUSY_BLKD,
{SnpResp_I,SnpResp_SC,
SnpResp_I_Fwded_UC,SnpResp_I_Fwded_UD_PD,
SnpResp_SC_Fwded_SC,SnpResp_SC_Fwded_SD_PD,
SnpResp_UC_Fwded_I,SnpResp_UD_Fwded_I,
SnpResp_SC_Fwded_I,SnpResp_SD_Fwded_I}) {
Receive_SnpResp;
UpdateDirState_FromSnpResp;
Pop_RespInQueue;
ProcessNextState;
}
// waiting for WB or evict ack
transition(BUSY_INTR, Comp_I, BUSY_BLKD) {
Receive_ReqResp;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
ProcessNextState;
}
// currently this happens after a CleanUnique
transition(BUSY_INTR, Comp_UC, BUSY_BLKD) {
Receive_ReqResp;
UpdateDataState_FromCUResp;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
ProcessNextState;
}
// waiting for WB or evict ack
transition(BUSY_INTR, CompDBIDResp, BUSY_BLKD) {
Receive_ReqResp;
Receive_ReqResp_CopyDBID;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
ProcessNextState;
}
// alternative flow for WU with separate Comp
transition({BUSY_INTR,BUSY_BLKD}, DBIDResp, BUSY_BLKD) {
Receive_ReqResp;
Receive_ReqResp_CopyDBID;
Receive_ReqResp_WUNeedComp;
Receive_ReqResp_AR;
Pop_RespInQueue;
ProcessNextState;
}
transition(BUSY_BLKD, Comp) {
Receive_ReqResp_WUComp;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
ProcessNextState;
}
transition(BUSY_BLKD, TX_Data) {
Pop_TriggerQueue;
Send_Data;
ProcessNextState_ClearPending;
}
transition(BUSY_INTR, WriteZero) {
Pop_TriggerQueue;
WriteZero;
ProcessNextState_ClearPending;
}
// Finalization transition
transition({BUSY_BLKD,BUSY_INTR}, Final, *) {
Pop_TriggerQueue;
Finalize_UpdateCacheFromTBE;
Finalize_UpdateDirectoryFromTBE;
Finalize_DeallocateRequest;
}
////////////////////////////////////////////////////////
// DVM transitions
// I, DvmTlbi_Initiate, DvmTlbi_Unconfirmed
// I, DvmSync_Initiate, DvmSync_Unconfirmed
// Sync should expect only DBIDResp,
// but Tlbi could expect both DBIDResp and CompDBIDResp.
// Other CompDBIDResp handlers call a "Receive" action twice - is that relevant?
transition(I, DvmTlbi_Initiate, DvmTlbi_Unconfirmed) {
Initiate_Request_DVM;
Send_DvmTlbi;
Profile_OutgoingStart_DVM;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(I, DvmSync_Initiate, DvmSync_Unsent) {
Initiate_Request_DVM;
Try_Send_DvmSync;
Profile_OutgoingStart_DVM;
Pop_ReqRdyQueue;
ProcessNextState;
}
transition(DvmSync_Unsent, DvmSync_Send, DvmSync_Unconfirmed) {
Pop_TriggerQueue;
Send_DvmSync;
ProcessNextState_ClearPending;
}
// {DvmTlbi_Unconfirmed,DvmSync_Unconfirmed}, RetryAck
// {DvmTlbi_Unconfirmed,DvmSync_Unconfirmed}, PCrdGrant
// See other RetryAck, PCrdGrants
transition({DvmTlbi_Unconfirmed,DvmSync_Unconfirmed}, RetryAck) {
Receive_RetryAck;
Pop_RespInQueue;
ProcessNextState;
}
transition({DvmTlbi_Unconfirmed,DvmSync_Unconfirmed}, PCrdGrant) {
Receive_PCrdGrant;
Pop_RespInQueue;
ProcessNextState;
}
// Resend the request after RetryAck+PCrdGrant received
transition({DvmTlbi_Unconfirmed,DvmSync_Unconfirmed}, DoRetry) {
Send_Retry_DVM;
Pop_RetryTriggerQueue;
ProcessNextState_ClearPending;
}
// DvmTlbi_Unconfirmed, DBIDResp, DvmTlbi_Waiting
// DvmSync_Unconfirmed, DBIDResp, DvmSync_Waiting
// Should both send NCBWrData
transition(DvmTlbi_Unconfirmed, DBIDResp, DvmTlbi_Waiting) {
Receive_ReqResp;
Pop_RespInQueue;
Send_DvmTlbi_NCBWrData;
ExpectComp;
ProcessNextState;
}
transition(DvmSync_Unconfirmed, DBIDResp, DvmSync_Waiting) {
Receive_ReqResp;
Pop_RespInQueue;
Send_DvmSync_NCBWrData;
ExpectComp;
ProcessNextState;
}
// DvmTlbi_Unconfirmed, CompDBIDResp, DvmOp_Finished
// should call ProcessNextState
// {DvmTlbi_Waiting,DvmSync_Waiting}, Comp, DvmOp_Finished
// should call ProcessNextState
transition(DvmTlbi_Unconfirmed, CompDBIDResp, DvmOp_Finished) {
Receive_ReqResp;
Pop_RespInQueue;
Send_DvmTlbi_NCBWrData;
// We got the comp as well, so send the callback
DvmTlbi_CompCallback;
Profile_OutgoingEnd_DVM;
Try_Send_Pending_DvmSync;
ProcessNextState;
}
transition(DvmTlbi_Waiting, Comp, DvmOp_Finished) {
Receive_ReqResp;
Pop_RespInQueue;
DvmTlbi_CompCallback;
Profile_OutgoingEnd_DVM;
Try_Send_Pending_DvmSync;
ProcessNextState;
}
transition(DvmSync_Waiting, Comp, DvmOp_Finished) {
Receive_ReqResp;
Pop_RespInQueue;
DvmSync_CompCallback;
Profile_OutgoingEnd_DVM;
ProcessNextState;
}
// DvmOp_Finished, Final, I
// Should deallocate DvmOp
transition(DvmOp_Finished, Final, I) {
Pop_TriggerQueue; // "Final" is triggered from Trigger queue, so pop that
Finalize_DeallocateDvmRequest;
}
/////////////////////////////////////////////////
// DVM snoops
transition(I, {SnpDvmOpNonSync_P1,SnpDvmOpNonSync_P2}, DvmExtTlbi_Partial) {
// First message has arrived, could be P1 or P2 because either order is allowed
Initiate_DvmSnoop;
Pop_SnoopRdyQueue;
}
transition(I, {SnpDvmOpSync_P1,SnpDvmOpSync_P2}, DvmExtSync_Partial) {
// First message has arrived, could be P1 or P2 because either order is allowed
Initiate_DvmSnoop;
Pop_SnoopRdyQueue;
}
transition(DvmExtTlbi_Partial, {SnpDvmOpNonSync_P1,SnpDvmOpNonSync_P2}, DvmExtTlbi_Executing) {
// TODO - some check that we didn't receive a {P1,P1} or {P2,P2} pair?
// We receive this event directly from the SnpInPort, so pop it
Pop_SnpInPort;
// Triggers SnpResp_I from inside Ruby with a delay
DvmExtTlbi_EnqueueSnpResp;
ProcessNextState;
}
transition(DvmExtSync_Partial, {SnpDvmOpSync_P1,SnpDvmOpSync_P2}, DvmExtSync_Executing) {
// TODO - some check that we didn't receive a {P1,P1} or {P2,P2} pair?
// We receive this event directly from the SnpInPort, so pop it
Pop_SnpInPort;
// Tell the CPU model to perform a Sync
// e.g. flush load-store-queue
DvmExtSync_TriggerCallback;
// We just wait for the CPU to finish
}
transition(DvmExtTlbi_Executing, SendSnpIResp, DvmExtOp_Finished) {
// TLBI snoop response has been triggered after the delay
Pop_TriggerQueue;
// Send the snoop response to the MN
Send_SnpRespI;
// Should trigger Final state
ProcessNextState_ClearPending;
}
transition(DvmExtSync_Executing, DvmSync_ExternCompleted, DvmExtOp_Finished) {
Pop_SeqInPort;
// The CPU model has declared that the Sync is complete
// => send the snoop response to the MN
Send_SnpRespI;
// Should trigger Final state
ProcessNextState_ClearPending;
}
transition(DvmExtOp_Finished, Final, I) {
Pop_TriggerQueue;
Finalize_DeallocateDvmSnoop;
}