Files
gem5/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm
Matt Poremba 53b6e21c63 mem-ruby: Replace SLICC queueMemory calls with enqueue
Calls to queueMemoryRead and queueMemoryWrite do not consider the size
of the queue between ruby directories and DRAMCtrl which causes infinite
buffering in the queued port between the two. This adds a MessageBuffer
in between which uses enqueues in SLICC and is therefore size checked
before any SLICC transaction pushing to the buffer can occur, removing
the infinite buffering between the two.

Change-Id: Iedb9070844e4f6c8532a9c914d126105ec98d0bc
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27427
Tested-by: Gem5 Cloud Project GCB service account <345032938727@cloudbuild.gserviceaccount.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bradford Beckmann <brad.beckmann@amd.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com>
Maintainer: Bradford Beckmann <brad.beckmann@amd.com>
2020-04-08 23:40:57 +00:00

2073 lines
73 KiB
Plaintext

/*
* Copyright (c) 2010-2015 Advanced Micro Devices, Inc.
* All rights reserved.
*
* For use for simulation and test purposes only
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of the copyright holder 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 HOLDER 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.
*/
machine(MachineType:Directory, "AMD_Base-like protocol")
: DirectoryMemory * directory;
CacheMemory * L3CacheMemory;
Cycles response_latency := 5;
Cycles response_latency_regionDir := 1;
Cycles l3_hit_latency := 30;
bool useL3OnWT := "False";
Cycles to_memory_controller_latency := 1;
// From the Cores
MessageBuffer * requestFromCores, network="From", virtual_network="0", vnet_type="request";
MessageBuffer * responseFromCores, network="From", virtual_network="2", vnet_type="response";
MessageBuffer * unblockFromCores, network="From", virtual_network="4", vnet_type="unblock";
// To the Cores
MessageBuffer * probeToCore, network="To", virtual_network="0", vnet_type="request";
MessageBuffer * responseToCore, network="To", virtual_network="2", vnet_type="response";
// From region buffer
MessageBuffer * reqFromRegBuf, network="From", virtual_network="7", vnet_type="request";
// To Region directory
MessageBuffer * reqToRegDir, network="To", virtual_network="5", vnet_type="request";
MessageBuffer * reqFromRegDir, network="From", virtual_network="5", vnet_type="request";
MessageBuffer * unblockToRegDir, network="To", virtual_network="4", vnet_type="unblock";
MessageBuffer * triggerQueue;
MessageBuffer * L3triggerQueue;
MessageBuffer * requestToMemory;
MessageBuffer * responseFromMemory;
{
// STATES
state_declaration(State, desc="Directory states", default="Directory_State_U") {
U, AccessPermission:Backing_Store, desc="unblocked";
BR, AccessPermission:Backing_Store, desc="got CPU read request, blocked while sent to L3";
BW, AccessPermission:Backing_Store, desc="got CPU write request, blocked while sent to L3";
BL, AccessPermission:Busy, desc="got L3 WB request";
// BL is Busy because it's possible for the data only to be in the network
// in the WB, L3 has sent it and gone on with its business in possibly I
// state.
BI, AccessPermission:Backing_Store, desc="Blocked waiting for inv ack from core";
BS_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
BM_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
B_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
BP, AccessPermission:Backing_Store, desc="blocked waiting for probes, no need for memory";
BS_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
BM_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
B_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
BS_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
BM_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
B_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
B, AccessPermission:Backing_Store, desc="sent response, Blocked til ack";
// These are needed for when a private requests was issued before an inv was received
// for writebacks
BS_Pm_BL, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
BM_Pm_BL, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
B_Pm_BL, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
BP_BL, AccessPermission:Backing_Store, desc="blocked waiting for probes, no need for memory";
// for reads
BS_Pm_B, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
BM_Pm_B, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
B_Pm_B, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
BP_B, AccessPermission:Backing_Store, desc="blocked waiting for probes, no need for memory";
}
// Events
enumeration(Event, desc="Directory events") {
// CPU requests
RdBlkS, desc="...";
RdBlkM, desc="...";
RdBlk, desc="...";
WriteThrough, desc="WriteThrough Message";
Atomic, desc="Atomic Message";
RdBlkSP, desc="...";
RdBlkMP, desc="...";
RdBlkP, desc="...";
VicDirtyP, desc="...";
VicCleanP, desc="...";
WriteThroughP, desc="WriteThrough Message";
AtomicP, desc="Atomic Message";
// writebacks
VicDirty, desc="...";
VicClean, desc="...";
CPUData, desc="WB data from CPU";
StaleWB, desc="WB response for a no longer valid request";
// probe responses
CPUPrbResp, desc="Probe Response Msg";
LastCPUPrbResp, desc="Last Probe Response Msg";
ProbeAcksComplete, desc="Probe Acks Complete";
L3Hit, desc="Hit in L3 return data to core";
// Memory Controller
MemData, desc="Fetched data from memory arrives";
WBAck, desc="Writeback Ack from memory arrives";
CoreUnblock, desc="Core received data, unblock";
UnblockWriteThrough, desc="unblock, self triggered";
StaleVicDirty, desc="Core invalidated before VicDirty processed";
StaleVicDirtyP, desc="Core invalidated before VicDirty processed";
// For region protocol
CPUReq, desc="Generic CPU request";
Inv, desc="Region dir needs a block invalidated";
Downgrade, desc="Region dir needs a block downgraded";
// For private accesses (bypassed reg-dir)
CPUReadP, desc="Initial req from core, sent to L3";
CPUWriteP, desc="Initial req from core, sent to L3";
}
enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
L3DataArrayRead, desc="Read the data array";
L3DataArrayWrite, desc="Write the data array";
L3TagArrayRead, desc="Read the data array";
L3TagArrayWrite, desc="Write the data array";
}
// TYPES
// DirectoryEntry
structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") {
State DirectoryState, desc="Directory state";
DataBlock DataBlk, desc="data for the block";
NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore";
}
structure(CacheEntry, desc="...", interface="AbstractCacheEntry") {
DataBlock DataBlk, desc="data for the block";
MachineID LastSender, desc="Mach which this block came from";
}
structure(TBE, desc="...") {
State TBEState, desc="Transient state";
DataBlock DataBlk, desc="data for the block";
DataBlock DataBlkAux, desc="Auxiliary data for the block";
bool Dirty, desc="Is the data dirty?";
int NumPendingAcks, desc="num acks expected";
MachineID OriginalRequestor, desc="Original Requestor";
MachineID WTRequestor, desc="WT Requestor";
bool Cached, desc="data hit in Cache";
bool MemData, desc="Got MemData?",default="false";
bool wtData, desc="Got write through data?",default="false";
bool atomicData, desc="Got Atomic op?",default="false";
Cycles InitialRequestTime, desc="...";
Cycles ForwardRequestTime, desc="...";
Cycles ProbeRequestStartTime, desc="...";
bool DemandRequest, desc="for profiling";
MachineID LastSender, desc="Mach which this block came from";
bool L3Hit, default="false", desc="Was this an L3 hit?";
bool TriggeredAcksComplete, default="false", desc="True if already triggered acks complete";
WriteMask writeMask, desc="outstanding write through mask";
}
structure(TBETable, external="yes") {
TBE lookup(Addr);
void allocate(Addr);
void deallocate(Addr);
bool isPresent(Addr);
}
TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
Tick clockEdge();
Tick cyclesToTicks(Cycles c);
void set_tbe(TBE a);
void unset_tbe();
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
Entry dir_entry := static_cast(Entry, "pointer", directory.lookup(addr));
if (is_valid(dir_entry)) {
//DPRINTF(RubySlicc, "Getting entry %s: %s\n", addr, dir_entry.DataBlk);
return dir_entry;
}
dir_entry := static_cast(Entry, "pointer",
directory.allocate(addr, new Entry));
return dir_entry;
}
DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
TBE tbe := TBEs.lookup(addr);
if (is_valid(tbe) && tbe.MemData) {
DPRINTF(RubySlicc, "Returning DataBlk from TBE %s:%s\n", addr, tbe);
return tbe.DataBlk;
}
DPRINTF(RubySlicc, "Returning DataBlk from Dir %s:%s\n", addr, getDirectoryEntry(addr));
return getDirectoryEntry(addr).DataBlk;
}
State getState(TBE tbe, CacheEntry entry, Addr addr) {
return getDirectoryEntry(addr).DirectoryState;
}
State getStateFromAddr(Addr addr) {
return getDirectoryEntry(addr).DirectoryState;
}
void setState(TBE tbe, CacheEntry entry, Addr addr, State state) {
getDirectoryEntry(addr).DirectoryState := state;
}
AccessPermission getAccessPermission(Addr addr) {
// For this Directory, all permissions are just tracked in Directory, since
// it's not possible to have something in TBE but not Dir, just keep track
// of state all in one place.
if(directory.isPresent(addr)) {
return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
}
return AccessPermission:NotPresent;
}
void functionalRead(Addr addr, Packet *pkt) {
TBE tbe := TBEs.lookup(addr);
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
} else {
functionalMemoryRead(pkt);
}
}
int functionalWrite(Addr addr, Packet *pkt) {
int num_functional_writes := 0;
TBE tbe := TBEs.lookup(addr);
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
}
num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
return num_functional_writes;
}
void setAccessPermission(CacheEntry entry, Addr addr, State state) {
getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
}
void recordRequestType(RequestType request_type, Addr addr) {
if (request_type == RequestType:L3DataArrayRead) {
L3CacheMemory.recordRequestType(CacheRequestType:DataArrayRead, addr);
} else if (request_type == RequestType:L3DataArrayWrite) {
L3CacheMemory.recordRequestType(CacheRequestType:DataArrayWrite, addr);
} else if (request_type == RequestType:L3TagArrayRead) {
L3CacheMemory.recordRequestType(CacheRequestType:TagArrayRead, addr);
} else if (request_type == RequestType:L3TagArrayWrite) {
L3CacheMemory.recordRequestType(CacheRequestType:TagArrayWrite, addr);
}
}
bool checkResourceAvailable(RequestType request_type, Addr addr) {
if (request_type == RequestType:L3DataArrayRead) {
return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
} else if (request_type == RequestType:L3DataArrayWrite) {
return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
} else if (request_type == RequestType:L3TagArrayRead) {
return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
} else if (request_type == RequestType:L3TagArrayWrite) {
return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
} else {
error("Invalid RequestType type in checkResourceAvailable");
return true;
}
}
// ** OUT_PORTS **
out_port(probeNetwork_out, NBProbeRequestMsg, probeToCore);
out_port(responseNetwork_out, ResponseMsg, responseToCore);
out_port(requestNetworkReg_out, CPURequestMsg, reqToRegDir);
out_port(regAckNetwork_out, UnblockMsg, unblockToRegDir);
out_port(triggerQueue_out, TriggerMsg, triggerQueue);
out_port(L3TriggerQueue_out, TriggerMsg, L3triggerQueue);
out_port(memQueue_out, MemoryMsg, requestToMemory);
// ** IN_PORTS **
// Trigger Queue
in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=7) {
if (triggerQueue_in.isReady(clockEdge())) {
peek(triggerQueue_in, TriggerMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == TriggerType:AcksComplete) {
trigger(Event:ProbeAcksComplete, in_msg.addr, entry, tbe);
} else if (in_msg.Type == TriggerType:UnblockWriteThrough) {
trigger(Event:UnblockWriteThrough, in_msg.addr, entry, tbe);
} else {
error("Unknown trigger msg");
}
}
}
}
in_port(L3TriggerQueue_in, TriggerMsg, L3triggerQueue, rank=6) {
if (L3TriggerQueue_in.isReady(clockEdge())) {
peek(L3TriggerQueue_in, TriggerMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == TriggerType:L3Hit) {
trigger(Event:L3Hit, in_msg.addr, entry, tbe);
} else {
error("Unknown trigger msg");
}
}
}
}
// Unblock Network
in_port(unblockNetwork_in, UnblockMsg, unblockFromCores, rank=5) {
if (unblockNetwork_in.isReady(clockEdge())) {
peek(unblockNetwork_in, UnblockMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
trigger(Event:CoreUnblock, in_msg.addr, entry, tbe);
}
}
}
// Core response network
in_port(responseNetwork_in, ResponseMsg, responseFromCores, rank=4) {
if (responseNetwork_in.isReady(clockEdge())) {
peek(responseNetwork_in, ResponseMsg) {
DPRINTF(RubySlicc, "core responses %s\n", in_msg);
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
if (is_valid(tbe) && tbe.NumPendingAcks == 1
&& tbe.TriggeredAcksComplete == false) {
trigger(Event:LastCPUPrbResp, in_msg.addr, entry, tbe);
} else {
trigger(Event:CPUPrbResp, in_msg.addr, entry, tbe);
}
} else if (in_msg.Type == CoherenceResponseType:CPUData) {
trigger(Event:CPUData, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceResponseType:StaleNotif) {
trigger(Event:StaleWB, in_msg.addr, entry, tbe);
} else {
error("Unexpected response type");
}
}
}
}
// off-chip memory request/response is done
in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=3) {
if (memQueue_in.isReady(clockEdge())) {
peek(memQueue_in, MemoryMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
trigger(Event:MemData, in_msg.addr, entry, tbe);
DPRINTF(RubySlicc, "%s\n", in_msg);
} else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
trigger(Event:WBAck, in_msg.addr, entry, tbe); // ignore WBAcks, don't care about them.
} else {
DPRINTF(RubySlicc, "%s\n", in_msg.Type);
error("Invalid message");
}
}
}
}
in_port(regBuf_in, CPURequestMsg, reqFromRegBuf, rank=2) {
if (regBuf_in.isReady(clockEdge())) {
peek(regBuf_in, CPURequestMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == CoherenceRequestType:ForceInv) {
trigger(Event:Inv, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:ForceDowngrade) {
trigger(Event:Downgrade, in_msg.addr, entry, tbe);
} else {
error("Bad request from region buffer");
}
}
}
}
in_port(regDir_in, CPURequestMsg, reqFromRegDir, rank=1) {
if (regDir_in.isReady(clockEdge())) {
peek(regDir_in, CPURequestMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Type == CoherenceRequestType:RdBlk) {
trigger(Event:RdBlk, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
trigger(Event:RdBlkS, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
trigger(Event:RdBlkM, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:Atomic) {
trigger(Event:Atomic, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:WriteThrough) {
trigger(Event:WriteThrough, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:VicDirty) {
if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
DPRINTF(RubySlicc, "Dropping VicDirty for address %s\n", in_msg.addr);
trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
} else {
trigger(Event:VicDirty, in_msg.addr, entry, tbe);
}
} else if (in_msg.Type == CoherenceRequestType:VicClean) {
if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
DPRINTF(RubySlicc, "Dropping VicClean for address %s\n", in_msg.addr);
trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
} else {
trigger(Event:VicClean, in_msg.addr, entry, tbe);
}
} else {
error("Bad message type fwded from Region Dir");
}
}
}
}
in_port(requestNetwork_in, CPURequestMsg, requestFromCores, rank=0) {
if (requestNetwork_in.isReady(clockEdge())) {
peek(requestNetwork_in, CPURequestMsg) {
TBE tbe := TBEs.lookup(in_msg.addr);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
if (in_msg.Private) {
// Bypass the region dir
if (in_msg.Type == CoherenceRequestType:RdBlk) {
trigger(Event:RdBlkP, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
trigger(Event:RdBlkSP, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
trigger(Event:RdBlkMP, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:Atomic) {
trigger(Event:AtomicP, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:WriteThrough) {
trigger(Event:WriteThroughP, in_msg.addr, entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:VicDirty) {
if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
DPRINTF(RubySlicc, "Dropping VicDirtyP for address %s\n", in_msg.addr);
trigger(Event:StaleVicDirtyP, in_msg.addr, entry, tbe);
} else {
DPRINTF(RubySlicc, "Got VicDirty from %s on %s\n", in_msg.Requestor, in_msg.addr);
trigger(Event:VicDirtyP, in_msg.addr, entry, tbe);
}
} else if (in_msg.Type == CoherenceRequestType:VicClean) {
if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
DPRINTF(RubySlicc, "Dropping VicCleanP for address %s\n", in_msg.addr);
trigger(Event:StaleVicDirtyP, in_msg.addr, entry, tbe);
} else {
DPRINTF(RubySlicc, "Got VicClean from %s on %s\n", in_msg.Requestor, in_msg.addr);
trigger(Event:VicCleanP, in_msg.addr, entry, tbe);
}
} else {
error("Bad message type for private access");
}
} else {
trigger(Event:CPUReq, in_msg.addr, entry, tbe);
}
}
}
}
// Actions
action(s_sendResponseS, "s", desc="send Shared response") {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(tbe.OriginalRequestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := false;
out_msg.State := CoherenceState:Shared;
out_msg.InitialRequestTime := tbe.InitialRequestTime;
out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := tbe.DemandRequest;
out_msg.L3Hit := tbe.L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
action(es_sendResponseES, "es", desc="send Exclusive or Shared response") {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(tbe.OriginalRequestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := tbe.Dirty;
if (tbe.Cached) {
out_msg.State := CoherenceState:Shared;
} else {
out_msg.State := CoherenceState:Exclusive;
}
out_msg.InitialRequestTime := tbe.InitialRequestTime;
out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := tbe.DemandRequest;
out_msg.L3Hit := tbe.L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
action(m_sendResponseM, "m", desc="send Modified response") {
if (tbe.wtData) {
enqueue(triggerQueue_out, TriggerMsg, 1) {
out_msg.addr := address;
out_msg.Type := TriggerType:UnblockWriteThrough;
}
} else {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(tbe.OriginalRequestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := tbe.Dirty;
out_msg.State := CoherenceState:Modified;
out_msg.CtoD := false;
out_msg.InitialRequestTime := tbe.InitialRequestTime;
out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := tbe.DemandRequest;
out_msg.L3Hit := tbe.L3Hit;
if (tbe.atomicData) {
out_msg.WTRequestor := tbe.WTRequestor;
}
DPRINTF(RubySlicc, "%s\n", out_msg);
}
if (tbe.atomicData) {
enqueue(triggerQueue_out, TriggerMsg, 1) {
out_msg.addr := address;
out_msg.Type := TriggerType:UnblockWriteThrough;
}
}
}
}
action(sb_sendResponseSBypass, "sb", desc="send Shared response") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := false;
out_msg.State := CoherenceState:Shared;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := false;
out_msg.L3Hit := tbe.L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(esb_sendResponseESBypass, "esb", desc="send Exclusive or Shared response") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := tbe.Dirty;
if (tbe.Cached || in_msg.ForceShared) {
out_msg.State := CoherenceState:Shared;
} else {
out_msg.State := CoherenceState:Exclusive;
}
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := false;
out_msg.L3Hit := tbe.L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(mbwt_sendResponseWriteThroughBypass, "mbwt", desc="send write through response") {
peek(requestNetwork_in, CPURequestMsg) {
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysWBAck;
out_msg.Destination.add(in_msg.Requestor);
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.DemandRequest := false;
}
} else {
assert(in_msg.Type == CoherenceRequestType:Atomic);
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := in_msg.Dirty;
out_msg.State := CoherenceState:Modified;
out_msg.CtoD := false;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := false;
out_msg.L3Hit := tbe.L3Hit;
out_msg.WTRequestor := in_msg.WTRequestor;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
enqueue(triggerQueue_out, TriggerMsg, 1) {
out_msg.addr := address;
out_msg.Type := TriggerType:UnblockWriteThrough;
}
}
}
action(mb_sendResponseMBypass, "mb", desc="send Modified response") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
if (tbe.L3Hit) {
out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
} else {
out_msg.Sender := machineID;
}
out_msg.Destination.add(in_msg.Requestor);
out_msg.DataBlk := tbe.DataBlk;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.Dirty := tbe.Dirty;
out_msg.State := CoherenceState:Modified;
out_msg.CtoD := false;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.OriginalResponder := tbe.LastSender;
out_msg.DemandRequest := false;
out_msg.L3Hit := tbe.L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(c_sendResponseCtoD, "c", desc="send CtoD Ack") {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
out_msg.Sender := machineID;
out_msg.Destination.add(tbe.OriginalRequestor);
out_msg.MessageSize := MessageSizeType:Response_Control;
out_msg.Dirty := false;
out_msg.State := CoherenceState:Modified;
out_msg.CtoD := true;
out_msg.InitialRequestTime := tbe.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
out_msg.DemandRequest := tbe.DemandRequest;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
action(cp_sendResponseCtoDP, "cp", desc="send CtoD Ack") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysResp;
out_msg.Sender := machineID;
out_msg.Destination.add(in_msg.Requestor);
out_msg.MessageSize := MessageSizeType:Response_Control;
out_msg.Dirty := false;
out_msg.State := CoherenceState:Modified;
out_msg.CtoD := true;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.DemandRequest := false;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
}
action(w_sendResponseWBAck, "w", desc="send WB Ack") {
peek(regDir_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysWBAck;
out_msg.Destination.add(in_msg.Requestor);
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := in_msg.ForwardRequestTime;
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.DemandRequest := false;
}
}
}
action(wp_sendResponseWBAckP, "wp", desc="send WB Ack") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysWBAck;
out_msg.Destination.add(in_msg.Requestor);
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
out_msg.InitialRequestTime := in_msg.InitialRequestTime;
out_msg.ForwardRequestTime := curCycle();
out_msg.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
out_msg.DemandRequest := false;
}
}
}
action(wc_sendResponseWBAck, "wc", desc="send WB Ack for cancel") {
peek(responseNetwork_in, ResponseMsg) {
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:NBSysWBAck;
out_msg.Destination.add(in_msg.Sender);
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
action(ra_ackRegionDir, "ra", desc="Ack region dir") {
peek(regDir_in, CPURequestMsg) {
if (in_msg.NoAckNeeded == false) {
enqueue(responseNetwork_out, ResponseMsg, response_latency_regionDir) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:DirReadyAck;
out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
}
}
action(l_queueMemRdReq, "lr", desc="Read data from memory") {
peek(regDir_in, CPURequestMsg) {
if (L3CacheMemory.isTagPresent(address)) {
enqueue(L3TriggerQueue_out, TriggerMsg, l3_hit_latency) {
out_msg.addr := address;
out_msg.Type := TriggerType:L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
tbe.DataBlk := entry.DataBlk;
tbe.LastSender := entry.LastSender;
tbe.L3Hit := true;
tbe.MemData := true;
DPRINTF(RubySlicc, "L3 data is %s\n", entry.DataBlk);
L3CacheMemory.deallocate(address);
} else {
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
}
}
action(lrp_queueMemRdReqP, "lrp", desc="Read data from memory") {
peek(requestNetwork_in, CPURequestMsg) {
if (L3CacheMemory.isTagPresent(address)) {
enqueue(L3TriggerQueue_out, TriggerMsg, l3_hit_latency) {
out_msg.addr := address;
out_msg.Type := TriggerType:L3Hit;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
tbe.DataBlk := entry.DataBlk;
tbe.LastSender := entry.LastSender;
tbe.L3Hit := true;
tbe.MemData := true;
DPRINTF(RubySlicc, "L3 data is %s\n", entry.DataBlk);
L3CacheMemory.deallocate(address);
} else {
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := address;
out_msg.Type := MemoryRequestType:MEMORY_READ;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
}
}
action(dcr_probeInvCoreData, "dcr", desc="probe inv cores, return data") {
peek(regBuf_in, CPURequestMsg) {
enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := ProbeRequestType:PrbInv;
out_msg.ReturnData := true;
out_msg.MessageSize := MessageSizeType:Control;
out_msg.Destination := in_msg.Sharers;
tbe.NumPendingAcks := tbe.NumPendingAcks + in_msg.Sharers.count();
DPRINTF(RubySlicc, "%s\n", out_msg);
APPEND_TRANSITION_COMMENT(" dcr: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
tbe.ProbeRequestStartTime := curCycle();
}
}
}
action(ddr_probeDownCoreData, "ddr", desc="probe inv cores, return data") {
peek(regBuf_in, CPURequestMsg) {
enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := ProbeRequestType:PrbDowngrade;
out_msg.ReturnData := true;
out_msg.MessageSize := MessageSizeType:Control;
out_msg.Destination := in_msg.Sharers;
tbe.NumPendingAcks := tbe.NumPendingAcks + in_msg.Sharers.count();
DPRINTF(RubySlicc, "%s\n", out_msg);
APPEND_TRANSITION_COMMENT(" dcr: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
tbe.ProbeRequestStartTime := curCycle();
}
}
}
action(sc_probeShrCoreData, "sc", desc="probe shared cores, return data") {
peek(requestNetwork_in, CPURequestMsg) { // not the right network?
enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := ProbeRequestType:PrbDowngrade;
out_msg.ReturnData := true;
out_msg.MessageSize := MessageSizeType:Control;
out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
tbe.NumPendingAcks := tbe.NumPendingAcks +machineCount(MachineType:CorePair) - 1;
out_msg.Destination.broadcast(MachineType:TCP);
tbe.NumPendingAcks := tbe.NumPendingAcks + machineCount(MachineType:TCP);
out_msg.Destination.broadcast(MachineType:SQC);
tbe.NumPendingAcks := tbe.NumPendingAcks + machineCount(MachineType:SQC);
out_msg.Destination.remove(in_msg.Requestor);
DPRINTF(RubySlicc, "%s\n", (out_msg));
APPEND_TRANSITION_COMMENT(" sc: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
tbe.ProbeRequestStartTime := curCycle();
}
}
}
action(ic_probeInvCore, "ic", desc="probe invalidate core, no return data needed") {
peek(requestNetwork_in, CPURequestMsg) { // not the right network?
enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := ProbeRequestType:PrbInv;
out_msg.ReturnData := false;
out_msg.MessageSize := MessageSizeType:Control;
out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
tbe.NumPendingAcks := tbe.NumPendingAcks +machineCount(MachineType:CorePair) - 1;
out_msg.Destination.broadcast(MachineType:TCP);
tbe.NumPendingAcks := tbe.NumPendingAcks + machineCount(MachineType:TCP);
out_msg.Destination.broadcast(MachineType:SQC);
tbe.NumPendingAcks := tbe.NumPendingAcks + machineCount(MachineType:SQC);
out_msg.Destination.remove(in_msg.Requestor);
APPEND_TRANSITION_COMMENT(" ic: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
DPRINTF(RubySlicc, "%s\n", out_msg);
tbe.ProbeRequestStartTime := curCycle();
}
}
}
action(d_writeDataToMemory, "d", desc="Write data to memory") {
peek(responseNetwork_in, ResponseMsg) {
getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Writing Data: %s to address %s\n", in_msg.DataBlk,
in_msg.addr);
}
}
action(t_allocateTBE, "t", desc="allocate TBE Entry") {
check_allocate(TBEs);
peek(regDir_in, CPURequestMsg) {
TBEs.allocate(address);
set_tbe(TBEs.lookup(address));
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
tbe.writeMask.clear();
tbe.writeMask.orMask(in_msg.writeMask);
tbe.wtData := true;
tbe.WTRequestor := in_msg.WTRequestor;
tbe.LastSender := in_msg.Requestor;
}
if (in_msg.Type == CoherenceRequestType:Atomic) {
tbe.writeMask.clear();
tbe.writeMask.orMask(in_msg.writeMask);
tbe.atomicData := true;
tbe.WTRequestor := in_msg.WTRequestor;
tbe.LastSender := in_msg.Requestor;
}
tbe.DataBlk := getDirectoryEntry(address).DataBlk; // Data only for WBs
tbe.Dirty := false;
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
tbe.DataBlk.copyPartial(in_msg.DataBlk,tbe.writeMask);
tbe.Dirty := false;
}
tbe.OriginalRequestor := in_msg.Requestor;
tbe.NumPendingAcks := 0;
tbe.Cached := in_msg.ForceShared;
tbe.InitialRequestTime := in_msg.InitialRequestTime;
tbe.ForwardRequestTime := curCycle();
tbe.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
tbe.DemandRequest := in_msg.DemandRequest;
}
}
action(tp_allocateTBEP, "tp", desc="allocate TBE Entry") {
check_allocate(TBEs);
peek(requestNetwork_in, CPURequestMsg) {
TBEs.allocate(address);
set_tbe(TBEs.lookup(address));
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
tbe.writeMask.clear();
tbe.writeMask.orMask(in_msg.writeMask);
tbe.wtData := true;
tbe.WTRequestor := in_msg.WTRequestor;
tbe.LastSender := in_msg.Requestor;
}
if (in_msg.Type == CoherenceRequestType:Atomic) {
tbe.writeMask.clear();
tbe.writeMask.orMask(in_msg.writeMask);
tbe.atomicData := true;
tbe.WTRequestor := in_msg.WTRequestor;
tbe.LastSender := in_msg.Requestor;
}
tbe.DataBlk := getDirectoryEntry(address).DataBlk; // Data only for WBs
tbe.Dirty := false;
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
tbe.DataBlk.copyPartial(in_msg.DataBlk,tbe.writeMask);
tbe.Dirty := false;
}
tbe.OriginalRequestor := in_msg.Requestor;
tbe.NumPendingAcks := 0;
tbe.Cached := in_msg.ForceShared;
tbe.InitialRequestTime := in_msg.InitialRequestTime;
tbe.ForwardRequestTime := curCycle();
tbe.ProbeRequestStartTime := in_msg.ProbeRequestStartTime;
tbe.DemandRequest := false;
}
}
action(sa_setAcks, "sa", desc="setAcks") {
peek(regDir_in, CPURequestMsg) {
tbe.NumPendingAcks := in_msg.Acks;
APPEND_TRANSITION_COMMENT(" waiting for acks ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
}
}
action(tr_allocateTBE, "tr", desc="allocate TBE Entry for Region inv") {
check_allocate(TBEs);
TBEs.allocate(address);
set_tbe(TBEs.lookup(address));
tbe.NumPendingAcks := 0;
}
action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
TBEs.deallocate(address);
unset_tbe();
}
action(wdp_writeBackDataPrivate, "wdp", desc="Write back data if needed") {
peek(requestNetwork_in, CPURequestMsg) {
if (in_msg.Type == CoherenceRequestType:WriteThrough) {
tbe.DataBlkAux := getDirectoryEntry(address).DataBlk;
tbe.DataBlkAux.copyPartial(in_msg.DataBlk,in_msg.writeMask);
getDirectoryEntry(address).DataBlk := tbe.DataBlkAux;
} else{
assert(in_msg.Type == CoherenceRequestType:Atomic);
tbe.DataBlkAux.atomicPartial(getDirectoryEntry(address).DataBlk,in_msg.writeMask);
getDirectoryEntry(address).DataBlk := tbe.DataBlkAux;
}
}
}
action(wd_writeBackData, "wd", desc="Write back data if needed") {
if (tbe.wtData) {
DataBlock tmp := getDirectoryEntry(address).DataBlk;
tmp.copyPartial(tbe.DataBlk,tbe.writeMask);
tbe.DataBlk := tmp;
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
} else if (tbe.atomicData) {
tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask);
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
} else if (tbe.Dirty == true) {
APPEND_TRANSITION_COMMENT(" Wrote data back ");
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
}
}
action(wdi_writeBackDataInv, "wdi", desc="Write back inv data if needed") {
// Kind of opposite from above...?
if (tbe.Dirty == true) {
getDirectoryEntry(address).DataBlk := tbe.DataBlk;
APPEND_TRANSITION_COMMENT("Writing dirty data to dir");
DPRINTF(RubySlicc, "Data %s: %s\n", address, tbe.DataBlk);
} else {
APPEND_TRANSITION_COMMENT("NOT!!! Writing dirty data to dir");
}
}
action(wdt_writeBackDataInvNoTBE, "wdt", desc="Write back inv data if needed no TBE") {
// Kind of opposite from above...?
peek(responseNetwork_in, ResponseMsg) {
if (in_msg.Dirty == true) {
getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
APPEND_TRANSITION_COMMENT("Writing dirty data to dir");
DPRINTF(RubySlicc, "Data %s: %s\n", address, in_msg.DataBlk);
} else {
APPEND_TRANSITION_COMMENT("NOT!!! Writing dirty data to dir");
}
}
}
action(mt_writeMemDataToTBE, "mt", desc="write Mem data to TBE") {
peek(memQueue_in, MemoryMsg) {
if (tbe.Dirty == false) {
tbe.DataBlk := getDirectoryEntry(address).DataBlk;
}
tbe.MemData := true;
}
}
action(ml_writeL3DataToTBE, "ml", desc="write L3 data to TBE") {
assert(tbe.Dirty == false);
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
tbe.DataBlk := entry.DataBlk;
tbe.LastSender := entry.LastSender;
tbe.L3Hit := true;
tbe.MemData := true;
}
action(y_writeProbeDataToTBE, "y", desc="write Probe Data to TBE") {
peek(responseNetwork_in, ResponseMsg) {
if (in_msg.Dirty) {
DPRINTF(RubySlicc, "Got dirty data for %s from %s\n", address, in_msg.Sender);
DPRINTF(RubySlicc, "Data is %s\n", in_msg.DataBlk);
if (tbe.wtData) {
DataBlock tmp := in_msg.DataBlk;
tmp.copyPartial(tbe.DataBlk,tbe.writeMask);
tbe.DataBlk := tmp;
} else if (tbe.Dirty) {
if(tbe.atomicData == false && tbe.wtData == false) {
DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender);
assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data
}
} else {
tbe.DataBlk := in_msg.DataBlk;
tbe.Dirty := in_msg.Dirty;
tbe.LastSender := in_msg.Sender;
}
}
if (in_msg.Hit) {
tbe.Cached := true;
}
}
}
action(yc_writeCPUDataToTBE, "yc", desc="write CPU Data to TBE") {
peek(responseNetwork_in, ResponseMsg) {
if (in_msg.Dirty) {
DPRINTF(RubySlicc, "Got dirty data for %s from %s\n", address, in_msg.Sender);
DPRINTF(RubySlicc, "Data is %s\n", in_msg.DataBlk);
if (tbe.Dirty) {
DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender);
assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data
}
tbe.DataBlk := in_msg.DataBlk;
tbe.Dirty := false;
tbe.LastSender := in_msg.Sender;
}
}
}
action(x_decrementAcks, "x", desc="decrement Acks pending") {
if (tbe.NumPendingAcks > 0) {
tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
} else {
APPEND_TRANSITION_COMMENT(" Double ack! ");
}
assert(tbe.NumPendingAcks >= 0);
APPEND_TRANSITION_COMMENT(" Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
}
action(o_checkForCompletion, "o", desc="check for ack completion") {
if (tbe.NumPendingAcks == 0 && tbe.TriggeredAcksComplete == false) {
enqueue(triggerQueue_out, TriggerMsg, 1) {
out_msg.addr := address;
out_msg.Type := TriggerType:AcksComplete;
}
tbe.TriggeredAcksComplete := true;
}
APPEND_TRANSITION_COMMENT(" Check: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
}
action(ont_checkForCompletionNoTrigger, "ont", desc="check for ack completion, no trigger") {
if (tbe.NumPendingAcks == 0 && tbe.TriggeredAcksComplete == false) {
tbe.TriggeredAcksComplete := true;
}
APPEND_TRANSITION_COMMENT(" Check: Acks remaining: ");
APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
}
action(rvp_removeVicDirtyIgnore, "rvp", desc="Remove ignored core") {
peek(requestNetwork_in, CPURequestMsg) {
getDirectoryEntry(address).VicDirtyIgnore.remove(in_msg.Requestor);
}
}
action(rv_removeVicDirtyIgnore, "rv", desc="Remove ignored core") {
peek(regDir_in, CPURequestMsg) {
getDirectoryEntry(address).VicDirtyIgnore.remove(in_msg.Requestor);
}
}
action(r_sendRequestToRegionDir, "r", desc="send request to Region Directory") {
peek(requestNetwork_in, CPURequestMsg) {
enqueue(requestNetworkReg_out, CPURequestMsg, 1) {
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
DPRINTF(RubySlicc, "out dest: %s\n", mapAddressToMachine(address, MachineType:RegionDir));
}
}
}
action(ai_ackInvalidate, "ai", desc="Ack to let the reg-dir know that the inv is ordered") {
peek(regBuf_in, CPURequestMsg) {
enqueue(regAckNetwork_out, UnblockMsg, 1) {
out_msg.addr := address;
out_msg.Destination.add(in_msg.Requestor);
out_msg.MessageSize := MessageSizeType:Response_Control;
DPRINTF(RubySlicc, "ai out_msg: %s\n", out_msg);
}
}
}
action(aic_ackInvalidate, "aic", desc="Ack to let the reg-dir know that the inv is ordered") {
peek(responseNetwork_in, ResponseMsg) {
if (in_msg.NoAckNeeded == false) {
enqueue(regAckNetwork_out, UnblockMsg, 1) {
out_msg.addr := address;
if (machineIDToMachineType(in_msg.Sender) == MachineType:CorePair) {
out_msg.Destination.add(createMachineID(MachineType:RegionBuffer, intToID(0)));
} else {
out_msg.Destination.add(createMachineID(MachineType:RegionBuffer, intToID(1)));
}
out_msg.MessageSize := MessageSizeType:Response_Control;
DPRINTF(RubySlicc, "ai out_msg: %s\n", out_msg);
out_msg.wasValid := in_msg.isValid;
}
}
}
}
action(al_allocateL3Block, "al", desc="allocate the L3 block on WB") {
peek(responseNetwork_in, ResponseMsg) {
if (L3CacheMemory.isTagPresent(address)) {
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
entry.DataBlk := in_msg.DataBlk;
entry.LastSender := in_msg.Sender;
} else {
if (L3CacheMemory.cacheAvail(address) == false) {
Addr victim := L3CacheMemory.cacheProbe(address);
CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
L3CacheMemory.lookup(victim));
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := victim;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Data;
out_msg.DataBlk := victim_entry.DataBlk;
}
L3CacheMemory.deallocate(victim);
}
assert(L3CacheMemory.cacheAvail(address));
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
entry.DataBlk := in_msg.DataBlk;
entry.LastSender := in_msg.Sender;
}
}
}
action(alwt_allocateL3BlockOnWT, "alwt", desc="allocate the L3 block on WT") {
if ((tbe.wtData || tbe.atomicData) && useL3OnWT) {
if (L3CacheMemory.isTagPresent(address)) {
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
entry.DataBlk := tbe.DataBlk;
entry.LastSender := tbe.LastSender;
} else {
if (L3CacheMemory.cacheAvail(address) == false) {
Addr victim := L3CacheMemory.cacheProbe(address);
CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
L3CacheMemory.lookup(victim));
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := victim;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Data;
out_msg.DataBlk := victim_entry.DataBlk;
}
L3CacheMemory.deallocate(victim);
}
assert(L3CacheMemory.cacheAvail(address));
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
entry.DataBlk := tbe.DataBlk;
entry.LastSender := tbe.LastSender;
}
}
}
action(ali_allocateL3Block, "ali", desc="allocate the L3 block on ForceInv") {
if (tbe.Dirty == true) {
if (L3CacheMemory.isTagPresent(address)) {
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
entry.DataBlk := tbe.DataBlk;
entry.LastSender := tbe.LastSender;
} else {
if (L3CacheMemory.cacheAvail(address) == false) {
Addr victim := L3CacheMemory.cacheProbe(address);
CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
L3CacheMemory.lookup(victim));
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := victim;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Data;
out_msg.DataBlk := victim_entry.DataBlk;
}
L3CacheMemory.deallocate(victim);
}
assert(L3CacheMemory.cacheAvail(address));
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
entry.DataBlk := tbe.DataBlk;
entry.LastSender := tbe.LastSender;
}
}
}
action(ali_allocateL3BlockNoTBE, "alt", desc="allocate the L3 block on ForceInv no TBE") {
peek(responseNetwork_in, ResponseMsg) {
if (in_msg.Dirty) {
if (L3CacheMemory.isTagPresent(address)) {
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
APPEND_TRANSITION_COMMENT(" ali wrote data to L3 (hit) ");
entry.DataBlk := in_msg.DataBlk;
entry.LastSender := in_msg.Sender;
} else {
if (L3CacheMemory.cacheAvail(address) == false) {
Addr victim := L3CacheMemory.cacheProbe(address);
CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
L3CacheMemory.lookup(victim));
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := victim;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Data;
out_msg.DataBlk := victim_entry.DataBlk;
}
L3CacheMemory.deallocate(victim);
}
assert(L3CacheMemory.cacheAvail(address));
CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
APPEND_TRANSITION_COMMENT(" ali wrote data to L3 ");
entry.DataBlk := in_msg.DataBlk;
entry.LastSender := in_msg.Sender;
}
}
}
}
action(dl_deallocateL3, "dl", desc="deallocate the L3 block") {
L3CacheMemory.deallocate(address);
}
action(p_popRequestQueue, "p", desc="pop request queue") {
requestNetwork_in.dequeue(clockEdge());
}
action(prd_popRegionQueue, "prd", desc="pop request queue") {
regDir_in.dequeue(clockEdge());
}
action(prb_popRegionBufQueue, "prb", desc="pop request queue") {
regBuf_in.dequeue(clockEdge());
}
action(pr_popResponseQueue, "pr", desc="pop response queue") {
responseNetwork_in.dequeue(clockEdge());
}
action(pm_popMemQueue, "pm", desc="pop mem queue") {
memQueue_in.dequeue(clockEdge());
}
action(pt_popTriggerQueue, "pt", desc="pop trigger queue") {
triggerQueue_in.dequeue(clockEdge());
}
action(ptl_popTriggerQueue, "ptl", desc="pop L3 trigger queue") {
L3TriggerQueue_in.dequeue(clockEdge());
}
action(pu_popUnblockQueue, "pu", desc="pop unblock queue") {
unblockNetwork_in.dequeue(clockEdge());
}
action(yy_recycleResponseQueue, "yy", desc="recycle response queue") {
responseNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
}
action(ww_stallAndWaitRegRequestQueue, "ww", desc="recycle region dir request queue") {
stall_and_wait(regDir_in, address);
}
action(st_stallAndWaitRequest, "st", desc="Stall and wait on the address") {
stall_and_wait(requestNetwork_in, address);
}
action(wa_wakeUpDependents, "wa", desc="Wake up any requests waiting for this address") {
wakeUpBuffers(address);
}
action(wa_wakeUpAllDependents, "waa", desc="Wake up any requests waiting for this region") {
wakeUpAllBuffers();
}
action(z_stall, "z", desc="...") {
}
// TRANSITIONS
// transitions from U
transition({BR, BW, BL, BI, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {Inv, Downgrade}) {
ww_stallAndWaitRegRequestQueue;
}
transition(U, Inv, BI){L3TagArrayRead} {
tr_allocateTBE;
dcr_probeInvCoreData; // only need to invalidate sharers
ai_ackInvalidate;
prb_popRegionBufQueue;
}
transition(U, Downgrade, BI){L3TagArrayRead} {
tr_allocateTBE;
ddr_probeDownCoreData; // only need to invalidate sharers
ai_ackInvalidate;
prb_popRegionBufQueue;
}
// The next 2 transistions are needed in the event that an invalidation
// is waiting for its ack from the core, but the event makes it through
// the region directory before the acks. This wouldn't be needed if
// we waited to ack the region dir until the directory got all the acks
transition({BR, BW, BI, BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {RdBlkS, RdBlkM, RdBlk, WriteThrough, Atomic}) {
ww_stallAndWaitRegRequestQueue;
}
transition({BR, BW, BI, BL, BS_M, BM_M, B_M, BS_PM, BM_PM, B_PM, B, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, {RdBlkSP, RdBlkMP, RdBlkP}) {
st_stallAndWaitRequest;
}
transition({BR, BW, BI, BL, BS_M, BM_M, B_M, BS_PM, BM_PM, B_PM, B, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, {WriteThroughP,AtomicP}) {
st_stallAndWaitRequest;
}
transition(U, {RdBlkS}, BS_PM) {L3TagArrayRead} {
t_allocateTBE;
l_queueMemRdReq;
sa_setAcks;
o_checkForCompletion;
ra_ackRegionDir;
prd_popRegionQueue;
}
transition(U, WriteThrough, BM_PM){L3TagArrayRead} {
t_allocateTBE;
w_sendResponseWBAck;
l_queueMemRdReq;
sa_setAcks;
o_checkForCompletion;
ra_ackRegionDir;
prd_popRegionQueue;
}
transition(U, {RdBlkM,Atomic}, BM_PM){L3TagArrayRead} {
t_allocateTBE;
l_queueMemRdReq;
sa_setAcks;
o_checkForCompletion;
ra_ackRegionDir;
prd_popRegionQueue;
}
transition(U, RdBlk, B_PM){L3TagArrayRead} {
t_allocateTBE;
l_queueMemRdReq;
sa_setAcks;
o_checkForCompletion;
ra_ackRegionDir;
prd_popRegionQueue;
}
transition(U, {RdBlkSP}, BS_M) {L3TagArrayRead} {
tp_allocateTBEP;
lrp_queueMemRdReqP;
p_popRequestQueue;
}
transition(U, WriteThroughP, BM_M) {L3TagArrayRead} {
tp_allocateTBEP;
wp_sendResponseWBAckP;
lrp_queueMemRdReqP;
p_popRequestQueue;
}
transition(U, {RdBlkMP,AtomicP}, BM_M) {L3TagArrayRead} {
tp_allocateTBEP;
lrp_queueMemRdReqP;
p_popRequestQueue;
}
transition(U, RdBlkP, B_M) {L3TagArrayRead} {
tp_allocateTBEP;
lrp_queueMemRdReqP;
p_popRequestQueue;
}
transition(U, VicDirtyP, BL) {L3TagArrayRead} {
tp_allocateTBEP;
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(U, VicCleanP, BL) {L3TagArrayRead} {
tp_allocateTBEP;
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BM_Pm, RdBlkSP, BM_Pm_B) {L3DataArrayWrite} {
sb_sendResponseSBypass;
p_popRequestQueue;
}
transition(BS_Pm, RdBlkSP, BS_Pm_B) {L3DataArrayWrite} {
sb_sendResponseSBypass;
p_popRequestQueue;
}
transition(B_Pm, RdBlkSP, B_Pm_B) {L3DataArrayWrite} {
sb_sendResponseSBypass;
p_popRequestQueue;
}
transition(BP, RdBlkSP, BP_B) {L3DataArrayWrite} {
sb_sendResponseSBypass;
p_popRequestQueue;
}
transition(BM_Pm, RdBlkMP, BM_Pm_B) {L3DataArrayWrite} {
mb_sendResponseMBypass;
p_popRequestQueue;
}
transition(BS_Pm, RdBlkMP, BS_Pm_B) {L3DataArrayWrite} {
mb_sendResponseMBypass;
p_popRequestQueue;
}
transition(B_Pm, RdBlkMP, B_Pm_B) {L3DataArrayWrite} {
mb_sendResponseMBypass;
p_popRequestQueue;
}
transition(BP, RdBlkMP, BP_B) {L3DataArrayWrite} {
mb_sendResponseMBypass;
p_popRequestQueue;
}
transition(BM_Pm, {WriteThroughP,AtomicP}, BM_Pm_B) {L3DataArrayWrite} {
wdp_writeBackDataPrivate;
mbwt_sendResponseWriteThroughBypass;
p_popRequestQueue;
}
transition(BS_Pm, {WriteThroughP,AtomicP}, BS_Pm_B) {L3DataArrayWrite} {
wdp_writeBackDataPrivate;
mbwt_sendResponseWriteThroughBypass;
p_popRequestQueue;
}
transition(B_Pm, {WriteThroughP,AtomicP}, B_Pm_B) {L3DataArrayWrite} {
wdp_writeBackDataPrivate;
mbwt_sendResponseWriteThroughBypass;
p_popRequestQueue;
}
transition(BP, {WriteThroughP,AtomicP}, BP_B) {L3DataArrayWrite} {
wdp_writeBackDataPrivate;
mbwt_sendResponseWriteThroughBypass;
p_popRequestQueue;
}
transition(BM_Pm, RdBlkP, BM_Pm_B) {L3DataArrayWrite} {
esb_sendResponseESBypass;
p_popRequestQueue;
}
transition(BS_Pm, RdBlkP, BS_Pm_B) {L3DataArrayWrite} {
esb_sendResponseESBypass;
p_popRequestQueue;
}
transition(B_Pm, RdBlkP, B_Pm_B) {L3DataArrayWrite}{
esb_sendResponseESBypass;
p_popRequestQueue;
}
transition(BP, RdBlkP, BP_B) {L3DataArrayWrite}{
esb_sendResponseESBypass;
p_popRequestQueue;
}
transition(BM_Pm_B, CoreUnblock, BM_Pm) {
wa_wakeUpDependents;
pu_popUnblockQueue;
}
transition(BS_Pm_B, CoreUnblock, BS_Pm) {
wa_wakeUpDependents;
pu_popUnblockQueue;
}
transition(B_Pm_B, CoreUnblock, B_Pm) {
wa_wakeUpDependents;
pu_popUnblockQueue;
}
transition(BP_B, CoreUnblock, BP) {
wa_wakeUpDependents;
pu_popUnblockQueue;
}
transition(BM_Pm_B, UnblockWriteThrough, BM_Pm) {
wa_wakeUpDependents;
pt_popTriggerQueue;
}
transition(BS_Pm_B, UnblockWriteThrough, BS_Pm) {
wa_wakeUpDependents;
pt_popTriggerQueue;
}
transition(B_Pm_B, UnblockWriteThrough, B_Pm) {
wa_wakeUpDependents;
pt_popTriggerQueue;
}
transition(BP_B, UnblockWriteThrough, BP) {
wa_wakeUpDependents;
pt_popTriggerQueue;
}
transition(BM_Pm, VicDirtyP, BM_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BS_Pm, VicDirtyP, BS_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(B_Pm, VicDirtyP, B_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BP, VicDirtyP, BP_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BM_Pm, VicCleanP, BM_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BS_Pm, VicCleanP, BS_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(B_Pm, VicCleanP, B_Pm_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BP, VicCleanP, BP_BL) {
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition(BM_Pm_BL, CPUData, BM_Pm) {
yc_writeCPUDataToTBE;
d_writeDataToMemory;
wa_wakeUpDependents;
pr_popResponseQueue;
}
transition(BS_Pm_BL, CPUData, BS_Pm) {
yc_writeCPUDataToTBE;
d_writeDataToMemory;
wa_wakeUpDependents;
pr_popResponseQueue;
}
transition(B_Pm_BL, CPUData, B_Pm) {
yc_writeCPUDataToTBE;
d_writeDataToMemory;
wa_wakeUpDependents;
pr_popResponseQueue;
}
transition(BP_BL, CPUData, BP) {
yc_writeCPUDataToTBE;
d_writeDataToMemory;
wa_wakeUpDependents;
pr_popResponseQueue;
}
transition({BR, BW, BL}, {VicDirtyP, VicCleanP}) {
st_stallAndWaitRequest;
}
transition({BR, BW, BL}, {VicDirty, VicClean}) {
ww_stallAndWaitRegRequestQueue;
}
transition(BL, CPUData, U) {L3TagArrayWrite, L3DataArrayWrite} {
dt_deallocateTBE;
d_writeDataToMemory;
al_allocateL3Block;
wa_wakeUpDependents;
pr_popResponseQueue;
}
transition(BL, StaleWB, U) {L3TagArrayWrite} {
dt_deallocateTBE;
wa_wakeUpAllDependents;
pr_popResponseQueue;
}
transition({BI, B, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, {VicDirty, VicClean}) {
ww_stallAndWaitRegRequestQueue;
}
transition({BI, B, BS_M, BM_M, B_M, BS_PM, BM_PM, B_PM, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, {VicDirtyP, VicCleanP}) {
st_stallAndWaitRequest;
}
transition({U, BR, BW, BL, BI, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, WBAck) {
pm_popMemQueue;
}
transition({U, BR, BW, BL, BI, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, StaleVicDirtyP) {
rvp_removeVicDirtyIgnore;
wp_sendResponseWBAckP;
p_popRequestQueue;
}
transition({U, BR, BW, BL, BI, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B, BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, StaleVicDirty) {
rv_removeVicDirtyIgnore;
w_sendResponseWBAck;
prd_popRegionQueue;
}
transition(U, VicDirty, BL) {L3TagArrayRead} {
t_allocateTBE;
ra_ackRegionDir;
w_sendResponseWBAck;
prd_popRegionQueue;
}
transition(U, VicClean, BL) {L3TagArrayRead} {
t_allocateTBE;
ra_ackRegionDir;
w_sendResponseWBAck;
prd_popRegionQueue;
}
transition({B, BR}, CoreUnblock, U) {
wa_wakeUpDependents;
pu_popUnblockQueue;
}
transition({B, BR}, UnblockWriteThrough, U) {
wa_wakeUpDependents;
pt_popTriggerQueue;
}
transition(BS_M, MemData, B) {L3TagArrayWrite, L3DataArrayWrite} {
mt_writeMemDataToTBE;
s_sendResponseS;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
pm_popMemQueue;
}
transition(BM_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
mt_writeMemDataToTBE;
m_sendResponseM;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
pm_popMemQueue;
}
transition(B_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
mt_writeMemDataToTBE;
es_sendResponseES;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
pm_popMemQueue;
}
transition(BS_PM, MemData, BS_Pm) {} {
mt_writeMemDataToTBE;
wa_wakeUpDependents;
pm_popMemQueue;
}
transition(BM_PM, MemData, BM_Pm){} {
mt_writeMemDataToTBE;
wa_wakeUpDependents;
pm_popMemQueue;
}
transition(B_PM, MemData, B_Pm){} {
mt_writeMemDataToTBE;
wa_wakeUpDependents;
pm_popMemQueue;
}
transition(BS_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} {
s_sendResponseS;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
ptl_popTriggerQueue;
}
transition(BM_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} {
m_sendResponseM;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
ptl_popTriggerQueue;
}
transition(B_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} {
es_sendResponseES;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
ptl_popTriggerQueue;
}
transition(BS_PM, L3Hit, BS_Pm) {
wa_wakeUpDependents;
ptl_popTriggerQueue;
}
transition(BM_PM, L3Hit, BM_Pm) {
wa_wakeUpDependents;
ptl_popTriggerQueue;
}
transition(B_PM, L3Hit, B_Pm) {
wa_wakeUpDependents;
ptl_popTriggerQueue;
}
transition({BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, BP, BI}, CPUPrbResp) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
pr_popResponseQueue;
}
transition({B, B_M, BS_M, BM_M}, {CPUPrbResp, LastCPUPrbResp}) {
z_stall;
}
transition({BS_Pm_BL, BM_Pm_BL, B_Pm_BL, BP_BL, BS_Pm_B, BM_Pm_B, B_Pm_B, BP_B}, {CPUPrbResp, LastCPUPrbResp}) {
// recycling because PrbResponse and data come on the same network
yy_recycleResponseQueue;
}
transition(U, {CPUPrbResp, LastCPUPrbResp}) {L3TagArrayRead, L3DataArrayWrite} {
aic_ackInvalidate;
wdt_writeBackDataInvNoTBE;
ali_allocateL3BlockNoTBE;
pr_popResponseQueue;
}
transition(BL, {CPUPrbResp, LastCPUPrbResp}) {} {
aic_ackInvalidate;
y_writeProbeDataToTBE;
wdi_writeBackDataInv;
ali_allocateL3Block;
pr_popResponseQueue;
}
transition(BS_PM, LastCPUPrbResp, BS_M) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
pr_popResponseQueue;
}
transition(BS_PM, ProbeAcksComplete, BS_M) {} {
pt_popTriggerQueue;
}
transition(BM_PM, LastCPUPrbResp, BM_M) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
pr_popResponseQueue;
}
transition(BM_PM, ProbeAcksComplete, BM_M) {} {
pt_popTriggerQueue;
}
transition(B_PM, LastCPUPrbResp, B_M) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
pr_popResponseQueue;
}
transition(B_PM, ProbeAcksComplete, B_M){} {
pt_popTriggerQueue;
}
transition(BS_Pm, LastCPUPrbResp, B) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
s_sendResponseS;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pr_popResponseQueue;
}
transition(BS_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
s_sendResponseS;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pt_popTriggerQueue;
}
transition(BM_Pm, LastCPUPrbResp, B) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
m_sendResponseM;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pr_popResponseQueue;
}
transition(BM_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
m_sendResponseM;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pt_popTriggerQueue;
}
transition(B_Pm, LastCPUPrbResp, B) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
es_sendResponseES;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pr_popResponseQueue;
}
transition(B_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
es_sendResponseES;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
ali_allocateL3Block;
dt_deallocateTBE;
pt_popTriggerQueue;
}
transition(BP, LastCPUPrbResp, B) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
c_sendResponseCtoD;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
pr_popResponseQueue;
}
transition(BP, ProbeAcksComplete, B){L3TagArrayWrite, L3TagArrayWrite} {
c_sendResponseCtoD;
wd_writeBackData;
alwt_allocateL3BlockOnWT;
dt_deallocateTBE;
pt_popTriggerQueue;
}
transition(BI, LastCPUPrbResp, B) {
aic_ackInvalidate;
y_writeProbeDataToTBE;
x_decrementAcks;
ont_checkForCompletionNoTrigger;
wa_wakeUpDependents;
wdi_writeBackDataInv;
ali_allocateL3Block;
dt_deallocateTBE;
pr_popResponseQueue;
}
transition(BI, ProbeAcksComplete, U) {L3TagArrayWrite, L3DataArrayWrite}{
wa_wakeUpDependents;
wdi_writeBackDataInv;
ali_allocateL3Block;
dt_deallocateTBE;
pt_popTriggerQueue;
}
}