blob: d591af3781a41e58aabc7e9fbddbd7aab1e7be40 [file] [log] [blame]
/*
* Copyright (c) 2021 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}, 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;
}
// 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;
}
// Load / Store 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,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(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;
}
// 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 UD_RU,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,
UD_RU,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_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({UD_RU,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_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;
}
// Stalls
transition({BUSY_BLKD,BUSY_INTR},
{ReadShared, ReadNotSharedDirty, ReadUnique, ReadUnique_PoC,
ReadOnce, CleanUnique, CleanUnique_Stale,
Load, Store, Prefetch,
WriteBackFull, WriteBackFull_Stale,
WriteEvictFull, WriteEvictFull_Stale,
WriteCleanFull, WriteCleanFull_Stale,
Evict, Evict_Stale,
WriteUnique,WriteUniquePtl_PoC,
WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc}) {
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, 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, 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_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, SendCompDBIDRespStale) {
Pop_TriggerQueue;
Send_CompDBIDResp_Stale;
ProcessNextState_ClearPending;
}
transition(BUSY_BLKD, MaintainCoherence) {
Pop_TriggerQueue;
Initiate_MaitainCoherence;
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;
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,
{CompDBIDResp,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;
}
// alternative flow for WU with separate Comp
transition(BUSY_INTR, DBIDResp, BUSY_BLKD) {
Receive_ReqResp;
Receive_ReqResp_WUNeedComp;
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;
}
// 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;
}