This commit allows CompData_SD be sent when ReadShared hits on UD line and the local cache keeps the line, unless the request doesn't allow SD. Change-Id: I337f24c871cc4c19c5b5fb11f9b35c0a8eb7911c
1710 lines
41 KiB
Plaintext
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 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,SD_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;
|
|
}
|