IFGX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner/exclusive. No other on-chip invs needed";
IFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner";
ISFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner, local sharers exist";
- IFGXX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner but may need acks from other sharers";
- OLSF, AccessPermission:Busy, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
+ IFGXX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner, waiting for data and acks from other sharers";
+ IFGXXD, AccessPermission:Read_Only, desc="Blocked, was IFGXX and received data, still waiting for acks";
+ OLSF, AccessPermission:Read_Only, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
- // writebacks
+ // Writebacks
+ // Notice we still have a valid copy of the block in some states
ILOW, AccessPermission:Busy, desc="local WB request, was ILO";
ILOXW, AccessPermission:Busy, desc="local WB request, was ILOX";
ILOSW, AccessPermission:Busy, desc="local WB request, was ILOS";
ILOSXW, AccessPermission:Busy, desc="local WB request, was ILOSX";
- SLSW, AccessPermission:Busy, desc="local WB request, was SLS";
- OLSW, AccessPermission:Busy, desc="local WB request, was OLS";
ILSW, AccessPermission:Busy, desc="local WB request, was ILS";
IW, AccessPermission:Busy, desc="local WB request from only sharer, was ILS";
- OW, AccessPermission:Busy, desc="local WB request from only sharer, was OLS";
- SW, AccessPermission:Busy, desc="local WB request from only sharer, was SLS";
- OXW, AccessPermission:Busy, desc="local WB request from only sharer, was OLSX";
- OLSXW, AccessPermission:Busy, desc="local WB request from sharer, was OLSX";
ILXW, AccessPermission:Busy, desc="local WB request, was ILX";
+ SLSW, AccessPermission:Read_Only, desc="local WB request, was SLS";
+ OLSW, AccessPermission:Read_Only, desc="local WB request, was OLS";
+ OW, AccessPermission:Read_Only, desc="local WB request from only sharer, was OLS";
+ SW, AccessPermission:Read_Only, desc="local WB request from only sharer, was SLS";
+ OXW, AccessPermission:Read_Only, desc="local WB request from only sharer, was OLSX";
+ OLSXW, AccessPermission:Read_Only, desc="local WB request from sharer, was OLSX";
IFLS, AccessPermission:Busy, desc="Blocked, forwarded local GETS to _some_ local sharer";
IFLO, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner";
IFLOSX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner w/ other sharers, chip is exclusive";
IFLXO, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner with other sharers, chip is exclusive";
+ // Some states hold valid data while waiting for acks
IGS, AccessPermission:Busy, desc="Semi-blocked, issued local GETS to directory";
IGM, AccessPermission:Busy, desc="Blocked, issued local GETX to directory. Need global acks and data";
IGMLS, AccessPermission:Busy, desc="Blocked, issued local GETX to directory but may need to INV local sharers";
- IGMO, AccessPermission:Busy, desc="Blocked, have data for local GETX but need all acks";
+ IGMO, AccessPermission:Read_Only, desc="Blocked, have data for local GETX but need all acks";
+ IGMOU, AccessPermission:Busy, desc="Blocked, responded to GETX, waiting unblock";
IGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner with possible local sharer, may need to INV";
OGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, may need to INV";
- IGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
+ IGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
+ IGMIOFD, AccessPermission:Read_Only, desc="Blocked, was IGMIOF but received data, still waiting acks";
IGMIOFS, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETS";
OGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, waiting for global acks, got Fwd_GETX";
+ // Have valid data in some of these transient states
II, AccessPermission:Busy, desc="Blocked, handling invalidations";
MM, AccessPermission:Busy, desc="Blocked, was M satisfying local GETX";
SS, AccessPermission:Busy, desc="Blocked, was S satisfying local GETS";
OO, AccessPermission:Busy, desc="Blocked, was O satisfying local GETS";
- OLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
- OLSXS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
- SLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
+ OLSS, AccessPermission:Read_Only, desc="Blocked, satisfying local GETS";
+ OLSXS, AccessPermission:Read_Only, desc="Blocked, satisfying local GETS";
+ SLSS, AccessPermission:Read_Only, desc="Blocked, satisfying local GETS";
- OI, AccessPermission:Busy, desc="Blocked, doing writeback, was O";
- MI, AccessPermission:Busy, desc="Blocked, doing writeback, was M";
+ // Have valid data in most of this states
+ OI, AccessPermission:Read_Only, desc="Blocked, doing writeback, was O";
+ MI, AccessPermission:Read_Write, desc="Blocked, doing writeback, was M";
MII, AccessPermission:Busy, desc="Blocked, doing writeback, was M, got Fwd_GETX";
- OLSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS";
- ILSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
+ OLSI, AccessPermission:Read_Only, desc="Blocked, doing writeback, was OLS";
+ ILSI, AccessPermission:Read_Only, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
// DMA blocking states
ILOSD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
AccessPermission getAccessPermission(Addr addr) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
- DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
+ DPRINTF(RubySlicc, "%s,%s\n", tbe.TBEState, L2Cache_State_to_permission(tbe.TBEState));
return L2Cache_State_to_permission(tbe.TBEState);
}
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
- DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
+ DPRINTF(RubySlicc, "%s,%s\n", cache_entry.CacheState, L2Cache_State_to_permission(cache_entry.CacheState));
return L2Cache_State_to_permission(cache_entry.CacheState);
}
void functionalRead(Addr addr, Packet *pkt) {
TBE tbe := TBEs[addr];
+ Entry cache_entry := getCacheEntry(addr);
if(is_valid(tbe)) {
testAndRead(addr, tbe.DataBlk, pkt);
+ } else if (is_valid(cache_entry)) {
+ testAndRead(addr, cache_entry.DataBlk, pkt);
} else {
- testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
+ error("Block not present!");
}
}
if(is_valid(tbe)) {
num_functional_writes := num_functional_writes +
testAndWrite(addr, tbe.DataBlk, pkt);
- return num_functional_writes;
}
- num_functional_writes := num_functional_writes +
- testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
+ Entry cache_entry := getCacheEntry(addr);
+ if (is_valid(cache_entry)) {
+ num_functional_writes := num_functional_writes +
+ testAndWrite(addr, cache_entry.DataBlk, pkt);
+ }
+
return num_functional_writes;
}
// TRANSITIONS
//*****************************************************
- transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_PUTO, L1_PUTS, L1_PUTS_only, L1_PUTX}) {
+ transition({II, IFGX, IFGS, ISFGS, IFGXX, IFGXXD, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMOU, IGMIO, OGMIO, IGMIOF, IGMIOFD, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_PUTO, L1_PUTS, L1_PUTS_only, L1_PUTX}) {
st_stallAndWaitL1RequestQueue;
}
- transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_GETX, L1_GETS}) {
+ transition({II, IFGX, IFGS, ISFGS, IFGXX, IFGXXD, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMOU, IGMIO, OGMIO, IGMIOF, IGMIOFD, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_GETX, L1_GETS}) {
st_stallAndWaitL1RequestQueue;
}
- transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, ILXW, OW, SW, OXW, OLSXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, IGMLS, IGMO, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, L2_Replacement) {
+ transition({IFGX, IFGS, ISFGS, IFGXX, IFGXXD, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, ILXW, OW, SW, OXW, OLSXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, IGMLS, IGMO, IGMOU, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, L2_Replacement) {
zz_recycleL1RequestQueue;
}
- transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Fwd_GETX, Fwd_GETS, Fwd_DMA}) {
+ transition({IFGX, IFGS, ISFGS, IFGXX, IFGXXD, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Fwd_GETX, Fwd_GETS, Fwd_DMA}) {
zz_recycleGlobalRequestQueue;
}
- transition({OGMIO, IGMIO, IGMO}, Fwd_DMA) {
+ transition({OGMIO, IGMIO, IGMO, IGMOU}, Fwd_DMA) {
zz_recycleGlobalRequestQueue;
}
- transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Inv}) {
+ transition({IFGX, IFGS, ISFGS, IFGXX, IFGXXD, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Inv}) {
zz_recycleGlobalRequestQueue;
}
}
- transition(IFGXX, IntAck) {
+ transition({IFGXX, IFGXXD}, IntAck) {
m_decrementNumberOfMessagesInt;
o_checkForIntCompletion;
n_popResponseQueue;
}
- transition(IFGXX, Data_Exclusive) {
+ transition(IFGXX, Data_Exclusive, IFGXXD) {
i_copyDataToTBE;
m_decrementNumberOfMessagesInt;
o_checkForIntCompletion;
n_popResponseQueue;
}
- transition(IFGXX, All_Acks, I) {
+ transition(IFGXXD, All_Acks, I) {
c_sendDataFromTBEToFwdGETX;
gg_clearLocalSharers;
removeFromDir;
n_popTriggerQueue;
}
- // transition(IGMLS, ExtAck, IGMO) {
transition(IGMLS, ExtAck) {
m_decrementNumberOfMessagesExt;
o_checkForExtCompletion;
n_popTriggerQueue;
}
- transition(IGMIOF, IntAck) {
+ transition({IGMIOF, IGMIOFD}, IntAck) {
m_decrementNumberOfMessagesInt;
o_checkForIntCompletion;
n_popResponseQueue;
}
- transition(IGMIOF, Data_Exclusive) {
+ transition(IGMIOF, Data_Exclusive, IGMIOFD) {
i_copyDataToTBE;
m_decrementNumberOfMessagesInt;
o_checkForIntCompletion;
n_popResponseQueue;
}
- transition(IGMIOF, All_Acks, IGM) {
+ transition(IGMIOFD, All_Acks, IGM) {
gg_clearLocalSharers;
c_sendDataFromTBEToFwdGETX;
n_popTriggerQueue;
}
- transition(IGMIO, All_Acks, IGMO) {
+ transition(IGMIO, All_Acks, IGMOU) {
hh_countLocalSharersExceptL1GETXRequestorInTBE;
ee_issueLocalInvExceptL1RequestorInTBE;
k_forwardLocalGETXToLocalOwner;
n_popTriggerQueue;
}
- transition(OGMIO, All_Acks, IGMO) {
+ transition(OGMIO, All_Acks, IGMOU) {
ee_issueLocalInvExceptL1RequestorInTBE;
c_sendDataFromTBEToL1GETX;
n_popTriggerQueue;
wa_wakeUpDependents;
}
- transition(IGMO, All_Acks) {
+ transition(IGMO, All_Acks, IGMOU) {
c_sendDataFromTBEToL1GETX;
n_popTriggerQueue;
}
- transition(IGMO, Exclusive_Unblock, ILX) {
+ transition(IGMOU, Exclusive_Unblock, ILX) {
g_recordLocalExclusive;
f_sendExclusiveUnblock;
s_deallocateTBE;
MessageBuffer * requestToMemory;
MessageBuffer * responseFromMemory;
+
+ MessageBuffer * triggerQueue;
{
// STATES
state_declaration(State, desc="Directory states", default="Directory_State_I") {
// Base states
I, AccessPermission:Read_Write, desc="Invalid";
- S, AccessPermission:Read_Only, desc="Shared";
+ S, AccessPermission:Read_Write, desc="Shared";
O, AccessPermission:Maybe_Stale, desc="Owner";
M, AccessPermission:Maybe_Stale, desc="Modified";
- IS, AccessPermission:Busy, desc="Blocked, was in idle";
+ // Transient states
+ // The memory has valid data in some of these
+ IS_M, AccessPermission:Read_Write, desc="Blocked, was in I, waiting for mem";
+ IS, AccessPermission:Read_Write, desc="Blocked, was in I, data forwarded";
SS, AccessPermission:Read_Only, desc="Blocked, was in shared";
OO, AccessPermission:Busy, desc="Blocked, was in owned";
MO, AccessPermission:Busy, desc="Blocked, going to owner or maybe modified";
- MM, AccessPermission:Busy, desc="Blocked, going to modified";
+ MM_M, AccessPermission:Read_Only, desc="Blocked, fetching from memory, going to MM";
+ MM, AccessPermission:Busy, desc="Blocked, req or mem data forwarded, going to modified";
MI, AccessPermission:Busy, desc="Blocked on a writeback";
MIS, AccessPermission:Busy, desc="Blocked on a writeback, but don't remove from sharers when received";
OS, AccessPermission:Busy, desc="Blocked on a writeback";
OSS, AccessPermission:Busy, desc="Blocked on a writeback, but don't remove from sharers when received";
- XI_M, AccessPermission:Busy, desc="Blocked, going to I, waiting for the memory controller";
- XI_M_U, AccessPermission:Busy, desc="Blocked, going to XI_U, waiting for the memory controller";
- XI_U, AccessPermission:Busy, desc="Blocked, going to I, waiting for an unblock";
- OI_D, AccessPermission:Busy, desc="In O, going to I, waiting for data";
+ // We have valid data in a TBE
+ WBI, AccessPermission:Read_Only, desc="Sent writeback, waiting for memory; will be I";
+ WBS, AccessPermission:Read_Only, desc="Sent writeback, waiting for memory; will be S";
+ XI_M, AccessPermission:Read_Only, desc="Blocked, going to I, waiting for the memory controller";
+ XI_M_U, AccessPermission:Read_Only, desc="Blocked, going to XI_U, waiting for the memory controller";
+ XI_U, AccessPermission:Read_Only, desc="Blocked, going to I, waiting for an unblock";
+ OI_D, AccessPermission:Busy, desc="In O, going to I, waiting for data";
OD, AccessPermission:Busy, desc="In O, waiting for dma ack from L2";
MD, AccessPermission:Busy, desc="In M, waiting for dma ack from L2";
}
DMA_WRITE_PARTIAL, desc="DMA Write partial line";
DMA_ACK, desc="DMA Ack";
Data, desc="Data to directory";
+ All_Acks, desk="All pending acks, unblocks, etc have been received";
}
// TYPES
int Len, desc="Length of request";
DataBlock DataBlk, desc="DataBlk";
MachineID Requestor, desc="original requestor";
+ bool WaitingWBAck, desc="DataBlk WB request sent, but no ack from mem yet";
+ bool WaitingDMAAck, desc="DMA ack sent, waiting for unblock";
}
structure(TBETable, external = "yes") {
if (directory.isPresent(addr)) {
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
if (is_valid(dir_entry)) {
- DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(dir_entry.DirectoryState));
+ DPRINTF(RubySlicc, "%s,%s\n", dir_entry.DirectoryState, Directory_State_to_permission(dir_entry.DirectoryState));
return Directory_State_to_permission(dir_entry.DirectoryState);
} else {
- DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(State:I));
+ DPRINTF(RubySlicc, "%s,%s\n", State:I, Directory_State_to_permission(State:I));
return Directory_State_to_permission(State:I);
}
}
}
void functionalRead(Addr addr, Packet *pkt) {
- functionalMemoryRead(pkt);
+ TBE tbe := TBEs[addr];
+ if (is_valid(tbe) && tbe.WaitingWBAck) {
+ testAndRead(addr, tbe.DataBlk, pkt);
+ } else {
+ functionalMemoryRead(pkt);
+ }
}
int functionalWrite(Addr addr, Packet *pkt) {
int num_functional_writes := 0;
+ TBE tbe := TBEs[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;
}
// For inserting internal unblocks only
out_port(unblockNetwork_out_internal, ResponseMsg, responseToDir);
+ out_port(triggerQueue_out, TriggerMsg, triggerQueue);
+
// ** IN_PORTS **
+ // Trigger Queue
+ in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=3) {
+ if (triggerQueue_in.isReady(clockEdge())) {
+ peek(triggerQueue_in, TriggerMsg) {
+ if (in_msg.Type == TriggerType:ALL_ACKS) {
+ trigger(Event:All_Acks, in_msg.addr, TBEs[in_msg.addr]);
+ } else {
+ error("Unexpected message");
+ }
+ }
+ }
+ }
+
in_port(unblockNetwork_in, ResponseMsg, responseToDir, rank=2) {
if (unblockNetwork_in.isReady(clockEdge())) {
peek(unblockNetwork_in, ResponseMsg) {
}
}
+ action(clearDMA, "cD", desc="Clear DMA flag in TBE") {
+ assert(is_valid(tbe));
+ assert(tbe.WaitingDMAAck);
+ tbe.WaitingDMAAck := false;
+ }
+
+ action(clearWBAck, "cWb", desc="Clear WB ack flag in TBE") {
+ assert(is_valid(tbe));
+ assert(tbe.WaitingWBAck);
+ tbe.WaitingWBAck := false;
+ }
+
action(c_clearOwner, "c", desc="Clear the owner field") {
getDirectoryEntry(address).Owner.clear();
}
unblockNetwork_in.dequeue(clockEdge());
}
+ action(popTriggerQueue, "pt", desc="Pop trigger queue.") {
+ triggerQueue_in.dequeue(clockEdge());
+ }
+
+ action(checkForCompletion, "\o", desc="Check if we have received all the messages required for completion") {
+ assert(is_valid(tbe));
+ if ((tbe.WaitingDMAAck == false) &&
+ (tbe.WaitingWBAck == false)) {
+ enqueue(triggerQueue_out, TriggerMsg) {
+ out_msg.addr := address;
+ out_msg.Type := TriggerType:ALL_ACKS;
+ }
+ }
+ }
+
action(m_addUnlockerToSharers, "m", desc="Add the unlocker to the sharer list") {
peek(unblockNetwork_in, ResponseMsg) {
if (in_msg.SenderMachine == MachineType:L2Cache) {
action(qw_queueMemoryWBFromCacheRequest, "qw", desc="Queue off-chip writeback request") {
peek(requestQueue_in, RequestMsg) {
- if (is_valid(tbe)) {
- enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
- out_msg.addr := address;
- out_msg.Type := MemoryRequestType:MEMORY_WB;
- out_msg.Sender := tbe.Requestor;
- out_msg.MessageSize := MessageSizeType:Writeback_Data;
- out_msg.DataBlk := in_msg.DataBlk;
- out_msg.Len := 0;
- }
- } else {
- enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
- out_msg.addr := address;
- out_msg.Type := MemoryRequestType:MEMORY_WB;
- out_msg.Sender := in_msg.Requestor;
- out_msg.MessageSize := MessageSizeType:Writeback_Data;
- out_msg.DataBlk := in_msg.DataBlk;
- out_msg.Len := 0;
- }
+ assert(is_valid(tbe));
+ enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
+ out_msg.addr := address;
+ out_msg.Type := MemoryRequestType:MEMORY_WB;
+ out_msg.Sender := in_msg.Requestor;
+ out_msg.MessageSize := MessageSizeType:Writeback_Data;
+ out_msg.DataBlk := in_msg.DataBlk;
+ out_msg.Len := 0;
}
+ tbe.DataBlk := in_msg.DataBlk;
+ tbe.WaitingWBAck := true;
}
}
out_msg.DataBlk := DataBlk;
out_msg.Len := 0;
}
+ tbe.DataBlk := DataBlk;
+ tbe.WaitingWBAck := true;
}
}
out_msg.DataBlk := DataBlk;
out_msg.Len := 0;
}
+ tbe.DataBlk := DataBlk;
+ tbe.WaitingWBAck := true;
}
}
action(qw_queueMemoryWBFromDMARequest, "/qw", desc="Queue off-chip writeback request") {
peek(requestQueue_in, RequestMsg) {
+ assert(is_valid(tbe));
enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) {
out_msg.addr := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := 0;
}
+ tbe.DataBlk := in_msg.DataBlk;
+ tbe.WaitingWBAck := true;
}
}
action(a_sendDMAAckFromReq, "\a", desc="Send DMA Ack that write completed, along with Inv Ack count") {
peek(requestQueue_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg, 1) {
+ assert(is_valid(tbe));
out_msg.addr := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:Directory;
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
out_msg.Type := CoherenceResponseType:DMA_ACK;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ tbe.WaitingDMAAck := true;
}
}
}
out_msg.Acks := getDirectoryEntry(address).Sharers.count(); // for dma requests
out_msg.Type := CoherenceResponseType:DMA_ACK;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ tbe.WaitingDMAAck := true;
}
}
action(v_allocateTBE, "v", desc="Allocate TBE entry") {
peek (requestQueue_in, RequestMsg) {
+ assert(is_valid(tbe) == false);
TBEs.allocate(address);
set_tbe(TBEs[address]);
tbe.PhysicalAddress := in_msg.addr;
tbe.Len := in_msg.Len;
tbe.DataBlk := in_msg.DataBlk;
tbe.Requestor := in_msg.Requestor;
+ tbe.WaitingWBAck := false;
+ tbe.WaitingDMAAck := false;
}
}
action(w_deallocateTBE, "w", desc="Deallocate TBE entry") {
+ assert(is_valid(tbe));
+ assert(tbe.WaitingWBAck == false);
+ assert(tbe.WaitingDMAAck == false);
TBEs.deallocate(address);
unset_tbe();
}
// TRANSITIONS
- transition(I, GETX, MM) {
+ transition(I, GETX, MM_M) {
allocDirEntry;
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
transition(I, DMA_WRITE_LINE, XI_U) {
allocDirEntry;
+ v_allocateTBE;
qw_queueMemoryWBFromDMARequest;
a_sendDMAAckFromReq; // ack count may be zero
i_popIncomingRequestQueue;
transition(XI_M_U, Memory_Data_DMA, XI_U) {
qw_queueMemoryWBFromMemResp;
a_sendDMAAckFromTBE; // ack count may be zero
- w_deallocateTBE;
q_popMemQueue;
}
q_popMemQueue;
}
- transition(XI_U, Exclusive_Unblock, I) {
+ transition(XI_U, Exclusive_Unblock, XI_U) {
cc_clearSharers;
c_clearOwner;
- deallocDirEntry;
+ clearDMA;
+ checkForCompletion;
j_popIncomingUnblockQueue;
}
- transition(S, GETX, MM) {
+ transition(XI_U, Memory_Ack, XI_U) {
+ clearWBAck;
+ checkForCompletion;
+ q_popMemQueue;
+ }
+
+ transition(XI_U, All_Acks, I) {
+ deallocDirEntry;
+ w_deallocateTBE;
+ popTriggerQueue;
+ }
+
+ transition(S, GETX, MM_M) {
qf_queueMemoryFetchRequest;
g_sendInvalidations;
i_popIncomingRequestQueue;
}
transition(S, DMA_WRITE_LINE, XI_U) {
+ v_allocateTBE;
qw_queueMemoryWBFromDMARequest;
a_sendDMAAckFromReq; // ack count may be zero
g_sendInvalidations; // the DMA will collect invalidations
i_popIncomingRequestQueue;
}
- transition(I, GETS, IS) {
+ transition(I, GETS, IS_M) {
allocDirEntry;
qf_queueMemoryFetchRequest;
i_popIncomingRequestQueue;
transition(OI_D, Data, XI_U) {
qw_queueMemoryWBFromCacheResp;
a_sendDMAAckFromTBE; // ack count may be zero
- w_deallocateTBE;
j_popIncomingUnblockQueue;
}
}
- transition({MM, MO, MI, MIS, OS, OSS, XI_M, XI_M_U, XI_U, OI_D, OD, MD}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE_LINE, DMA_WRITE_PARTIAL}) {
+ transition({MM_M, MM, MO, MI, MIS, OS, OSS, WBI, WBS, XI_M, XI_M_U, XI_U, OI_D, OD, MD}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE_LINE, DMA_WRITE_PARTIAL}) {
zz_recycleRequest;
}
j_popIncomingUnblockQueue;
}
- transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_WRITE_LINE,DMA_WRITE_PARTIAL}) {
+ transition({IS, IS_M, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_WRITE_LINE,DMA_WRITE_PARTIAL}) {
zz_recycleRequest;
}
- transition(IS, {GETS, DMA_READ}) {
+ transition({IS, IS_M}, {GETS, DMA_READ}) {
zz_recycleRequest;
}
j_popIncomingUnblockQueue;
}
- transition(MI, Dirty_Writeback, I) {
+ transition(MI, Dirty_Writeback, WBI) {
c_clearOwner;
cc_clearSharers;
+ v_allocateTBE;
qw_queueMemoryWBFromCacheRequest;
- deallocDirEntry;
i_popIncomingRequestQueue;
}
- transition(MIS, Dirty_Writeback, S) {
+ transition(WBI, Memory_Ack, I) {
+ clearWBAck;
+ w_deallocateTBE;
+ deallocDirEntry;
+ q_popMemQueue;
+ }
+
+ transition(MIS, Dirty_Writeback, WBS) {
c_moveOwnerToSharer;
+ v_allocateTBE;
qw_queueMemoryWBFromCacheRequest;
i_popIncomingRequestQueue;
}
i_popIncomingRequestQueue;
}
- transition(OS, Dirty_Writeback, S) {
+ transition(OS, Dirty_Writeback, WBS) {
c_clearOwner;
+ v_allocateTBE;
qw_queueMemoryWBFromCacheRequest;
i_popIncomingRequestQueue;
}
- transition(OSS, Dirty_Writeback, S) {
+ transition(OSS, Dirty_Writeback, WBS) {
c_moveOwnerToSharer;
+ v_allocateTBE;
qw_queueMemoryWBFromCacheRequest;
i_popIncomingRequestQueue;
}
+ transition(WBS, Memory_Ack, S) {
+ clearWBAck;
+ w_deallocateTBE;
+ q_popMemQueue;
+ }
+
transition(OSS, Clean_Writeback, S) {
c_moveOwnerToSharer;
i_popIncomingRequestQueue;
i_popIncomingRequestQueue;
}
- transition({MI, MIS}, Unblock, M) {
- j_popIncomingUnblockQueue;
+ transition({S, O, M, SS, OO}, Memory_Data_Cache) {
+ d_sendDataMsg;
+ q_popMemQueue;
}
- transition({OS, OSS}, Unblock, O) {
- j_popIncomingUnblockQueue;
+ transition(IS_M, Memory_Data_Cache, IS) {
+ d_sendDataMsg;
+ q_popMemQueue;
}
- transition({S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS}, Memory_Data_Cache) {
+ transition(MM_M, Memory_Data_Cache, MM) {
d_sendDataMsg;
q_popMemQueue;
}
q_popMemQueue;
}
- transition({I, S, O, M, IS, SS, OO, MO, MM, MI, MIS, OS, OSS, XI_U, XI_M, XI_M_U}, Memory_Ack) {
- q_popMemQueue;
- }
-
}