2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
5 * For use for simulation and test purposes only
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Authors: Mithuna Thottethodi
36 machine(MachineType:TCCdir, "AMD read-for-ownership directory for TCC (aka GPU L2)")
37 : CacheMemory * directory;
38 // Convention: wire buffers are prefixed with "w_" for clarity
39 WireBuffer * w_reqToTCCDir;
40 WireBuffer * w_respToTCCDir;
41 WireBuffer * w_TCCUnblockToTCCDir;
42 WireBuffer * w_reqToTCC;
43 WireBuffer * w_probeToTCC;
44 WireBuffer * w_respToTCC;
45 int TCC_select_num_bits;
46 Cycles response_latency := 5;
47 Cycles directory_latency := 6;
48 Cycles issue_latency := 120;
50 // From the TCPs or SQCs
51 MessageBuffer * requestFromTCP, network="From", virtual_network="1", vnet_type="request";
52 MessageBuffer * responseFromTCP, network="From", virtual_network="3", vnet_type="response";
53 MessageBuffer * unblockFromTCP, network="From", virtual_network="5", vnet_type="unblock";
55 // To the Cores. TCC deals only with TCPs/SQCs. CP cores do not communicate directly with TCC.
56 MessageBuffer * probeToCore, network="To", virtual_network="1", vnet_type="request";
57 MessageBuffer * responseToCore, network="To", virtual_network="3", vnet_type="response";
60 MessageBuffer * probeFromNB, network="From", virtual_network="0", vnet_type="request";
61 MessageBuffer * responseFromNB, network="From", virtual_network="2", vnet_type="response";
63 MessageBuffer * requestToNB, network="To", virtual_network="0", vnet_type="request";
64 MessageBuffer * responseToNB, network="To", virtual_network="2", vnet_type="response";
65 MessageBuffer * unblockToNB, network="To", virtual_network="4", vnet_type="unblock";
67 MessageBuffer * triggerQueue, random="false";
70 state_declaration(State, desc="Directory states", default="TCCdir_State_I") {
72 I, AccessPermission:Invalid, desc="Invalid";
73 S, AccessPermission:Invalid, desc="Shared";
74 E, AccessPermission:Invalid, desc="Shared";
75 O, AccessPermission:Invalid, desc="Owner";
76 M, AccessPermission:Invalid, desc="Modified";
78 CP_I, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to invalid";
79 B_I, AccessPermission:Invalid, desc="Blocked, need not send data after acks are in, going to invalid";
80 CP_O, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to owned";
81 CP_S, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to shared";
82 CP_OM, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to O_M";
83 CP_SM, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to S_M";
84 CP_ISM, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to I_M";
85 CP_IOM, AccessPermission:Invalid, desc="Blocked, must send data after acks are in, going to I_M";
86 CP_OSIW, AccessPermission:Invalid, desc="Blocked, must send data after acks+CancelWB are in, going to I_C";
89 // Transient states and busy states used for handling side (TCC-facing) interactions
90 BW_S, AccessPermission:Invalid, desc="Blocked, Awaiting TCC unblock";
91 BW_E, AccessPermission:Invalid, desc="Blocked, Awaiting TCC unblock";
92 BW_O, AccessPermission:Invalid, desc="Blocked, Awaiting TCC unblock";
93 BW_M, AccessPermission:Invalid, desc="Blocked, Awaiting TCC unblock";
95 // Transient states and busy states used for handling upward (TCP-facing) interactions
96 I_M, AccessPermission:Invalid, desc="Invalid, issued RdBlkM, have not seen response yet";
97 I_ES, AccessPermission:Invalid, desc="Invalid, issued RdBlk, have not seen response yet";
98 I_S, AccessPermission:Invalid, desc="Invalid, issued RdBlkS, have not seen response yet";
99 BBS_S, AccessPermission:Invalid, desc="Blocked, going from S to S";
100 BBO_O, AccessPermission:Invalid, desc="Blocked, going from O to O";
101 BBM_M, AccessPermission:Invalid, desc="Blocked, going from M to M, waiting for data to forward";
102 BBM_O, AccessPermission:Invalid, desc="Blocked, going from M to O, waiting for data to forward";
103 BB_M, AccessPermission:Invalid, desc="Blocked, going from M to M, waiting for unblock";
104 BB_O, AccessPermission:Invalid, desc="Blocked, going from M to O, waiting for unblock";
105 BB_OO, AccessPermission:Invalid, desc="Blocked, going from O to O (adding sharers), waiting for unblock";
106 BB_S, AccessPermission:Invalid, desc="Blocked, going to S, waiting for (possible multiple) unblock(s)";
107 BBS_M, AccessPermission:Invalid, desc="Blocked, going from S or O to M";
108 BBO_M, AccessPermission:Invalid, desc="Blocked, going from S or O to M";
109 BBS_UM, AccessPermission:Invalid, desc="Blocked, going from S or O to M via upgrade";
110 BBO_UM, AccessPermission:Invalid, desc="Blocked, going from S or O to M via upgrade";
111 S_M, AccessPermission:Invalid, desc="Shared, issued CtoD, have not seen response yet";
112 O_M, AccessPermission:Invalid, desc="Shared, issued CtoD, have not seen response yet";
115 BBB_S, AccessPermission:Invalid, desc="Blocked, going to S after core unblock";
116 BBB_M, AccessPermission:Invalid, desc="Blocked, going to M after core unblock";
117 BBB_E, AccessPermission:Invalid, desc="Blocked, going to E after core unblock";
119 VES_I, AccessPermission:Invalid, desc="TCC replacement, waiting for clean WB ack";
120 VM_I, AccessPermission:Invalid, desc="TCC replacement, waiting for dirty WB ack";
121 VO_I, AccessPermission:Invalid, desc="TCC replacement, waiting for dirty WB ack";
122 VO_S, AccessPermission:Invalid, desc="TCC owner replacement, waiting for dirty WB ack";
124 ES_I, AccessPermission:Invalid, desc="L1 replacement, waiting for clean WB ack";
125 MO_I, AccessPermission:Invalid, desc="L1 replacement, waiting for dirty WB ack";
127 I_C, AccessPermission:Invalid, desc="Invalid, waiting for WBAck from NB for canceled WB";
128 I_W, AccessPermission:Invalid, desc="Invalid, waiting for WBAck from NB; canceled WB raced with directory invalidation";
131 BRWD_I, AccessPermission:Invalid, desc="Recalling, waiting for WBAck and Probe Data responses";
132 BRW_I, AccessPermission:Read_Write, desc="Recalling, waiting for WBAck";
133 BRD_I, AccessPermission:Invalid, desc="Recalling, waiting for Probe Data responses";
137 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
138 DataArrayRead, desc="Read the data array";
139 DataArrayWrite, desc="Write the data array";
140 TagArrayRead, desc="Read the data array";
141 TagArrayWrite, desc="Write the data array";
147 enumeration(Event, desc="TCC Directory Events") {
148 // Upward facing events (TCCdir w.r.t. TCP/SQC and TCC behaves like NBdir behaves with TCP/SQC and L3
151 Recall, desc="directory cache is full";
153 CPUWrite, desc="Initial req from core, sent to TCC";
154 NoCPUWrite, desc="Initial req from core, but non-exclusive clean data; can be discarded";
155 CPUWriteCancel, desc="Initial req from core, sent to TCC";
157 // Requests from the TCPs
158 RdBlk, desc="RdBlk event";
159 RdBlkM, desc="RdBlkM event";
160 RdBlkS, desc="RdBlkS event";
161 CtoD, desc="Change to Dirty request";
164 VicDirty, desc="...";
165 VicDirtyLast, desc="...";
166 VicClean, desc="...";
168 StaleVic, desc="...";
169 CancelWB, desc="TCC got invalidating probe, canceled WB";
171 // Probe Responses from TCP/SQCs
172 CPUPrbResp, desc="Probe response from TCP/SQC";
173 TCCPrbResp, desc="Probe response from TCC";
175 ProbeAcksComplete, desc="All acks received";
176 ProbeAcksCompleteReissue, desc="All acks received, changing CtoD to reissue";
178 CoreUnblock, desc="unblock from TCP/SQC";
179 LastCoreUnblock, desc="Last unblock from TCP/SQC";
180 TCCUnblock, desc="unblock from TCC (current owner)";
181 TCCUnblock_Sharer, desc="unblock from TCC (a sharer, not owner)";
182 TCCUnblock_NotValid,desc="unblock from TCC (not valid...caused by stale writebacks)";
184 // Downward facing events
187 NB_AckS, desc="NB Ack to TCC Request";
188 NB_AckE, desc="NB Ack to TCC Request";
189 NB_AckM, desc="NB Ack to TCC Request";
190 NB_AckCtoD, desc="NB Ack to TCC Request";
191 NB_AckWB, desc="NB Ack for clean WB";
194 // Incoming Probes from NB
195 PrbInvData, desc="Invalidating probe, return dirty data";
196 PrbInv, desc="Invalidating probe, no need to return data";
197 PrbShrData, desc="Downgrading probe, return data";
203 // Entry for directory
204 structure(Entry, desc="...", interface='AbstractCacheEntry') {
205 State CacheState, desc="Cache state (Cache of directory entries)";
206 DataBlock DataBlk, desc="data for the block";
207 NetDest Sharers, desc="Sharers for this block";
208 NetDest Owner, desc="Owner of this block";
209 NetDest MergedSharers, desc="Read sharers who are merged on a request";
210 int WaitingUnblocks, desc="Number of acks we're waiting for";
213 structure(TBE, desc="...") {
214 State TBEState, desc="Transient state";
215 DataBlock DataBlk, desc="DataBlk";
216 bool Dirty, desc="Is the data dirty?";
217 MachineID Requestor, desc="requestor";
218 int NumPendingAcks, desc="num acks expected";
219 MachineID OriginalRequestor, desc="Original Requestor";
220 MachineID UntransferredOwner, desc = "Untransferred owner for an upgrade transaction";
221 bool UntransferredOwnerExists, desc = "1 if Untransferred owner exists for an upgrade transaction";
222 bool Cached, desc="data hit in Cache";
223 bool Shared, desc="victim hit by shared probe";
224 bool Upgrade, desc="An upgrade request in progress";
225 bool CtoD, desc="Saved sysack info";
226 CoherenceState CohState, desc="Saved sysack info";
227 MessageSizeType MessageSize, desc="Saved sysack info";
228 MachineID Sender, desc="sender";
231 structure(TBETable, external = "yes") {
234 void deallocate(Addr);
235 bool isPresent(Addr);
239 TBETable TBEs, template="<TCCdir_TBE>", constructor="m_number_of_TBEs";
240 int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
241 NetDest TCC_dir_subtree;
245 Tick cyclesToTicks(Cycles c);
247 void set_cache_entry(AbstractCacheEntry b);
248 void unset_cache_entry();
251 MachineID mapAddressToMachine(Addr addr, MachineType mtype);
253 bool presentOrAvail(Addr addr) {
254 return directory.isTagPresent(addr) || directory.cacheAvail(addr);
257 Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
258 return static_cast(Entry, "pointer", directory.lookup(addr));
261 DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
262 TBE tbe := TBEs.lookup(addr);
267 return getCacheEntry(addr).DataBlk;
271 State getState(TBE tbe, Entry cache_entry, Addr addr) {
274 } else if (is_valid(cache_entry)) {
275 return cache_entry.CacheState;
280 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
281 if (is_valid(cache_entry)) {
282 cache_entry.changePermission(TCCdir_State_to_permission(state));
286 AccessPermission getAccessPermission(Addr addr) {
287 TBE tbe := TBEs.lookup(addr);
289 return TCCdir_State_to_permission(tbe.TBEState);
292 Entry cache_entry := getCacheEntry(addr);
293 if(is_valid(cache_entry)) {
294 return TCCdir_State_to_permission(cache_entry.CacheState);
297 return AccessPermission:NotPresent;
300 void functionalRead(Addr addr, Packet *pkt) {
301 TBE tbe := TBEs.lookup(addr);
303 testAndRead(addr, tbe.DataBlk, pkt);
305 functionalMemoryRead(pkt);
309 int functionalWrite(Addr addr, Packet *pkt) {
310 int num_functional_writes := 0;
312 TBE tbe := TBEs.lookup(addr);
314 num_functional_writes := num_functional_writes +
315 testAndWrite(addr, tbe.DataBlk, pkt);
318 num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
319 return num_functional_writes;
322 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
324 tbe.TBEState := state;
327 if (is_valid(cache_entry)) {
328 cache_entry.CacheState := state;
330 if (state == State:S) {
331 assert(cache_entry.Owner.count() == 0);
334 if (state == State:O) {
335 assert(cache_entry.Owner.count() == 1);
336 assert(cache_entry.Sharers.isSuperset(cache_entry.Owner) == false);
339 if (state == State:M) {
340 assert(cache_entry.Owner.count() == 1);
341 assert(cache_entry.Sharers.count() == 0);
344 if (state == State:E) {
345 assert(cache_entry.Owner.count() == 0);
346 assert(cache_entry.Sharers.count() == 1);
353 void recordRequestType(RequestType request_type, Addr addr) {
354 if (request_type == RequestType:DataArrayRead) {
355 directory.recordRequestType(CacheRequestType:DataArrayRead, addr);
356 } else if (request_type == RequestType:DataArrayWrite) {
357 directory.recordRequestType(CacheRequestType:DataArrayWrite, addr);
358 } else if (request_type == RequestType:TagArrayRead) {
359 directory.recordRequestType(CacheRequestType:TagArrayRead, addr);
360 } else if (request_type == RequestType:TagArrayWrite) {
361 directory.recordRequestType(CacheRequestType:TagArrayWrite, addr);
365 bool checkResourceAvailable(RequestType request_type, Addr addr) {
366 if (request_type == RequestType:DataArrayRead) {
367 return directory.checkResourceAvailable(CacheResourceType:DataArray, addr);
368 } else if (request_type == RequestType:DataArrayWrite) {
369 return directory.checkResourceAvailable(CacheResourceType:DataArray, addr);
370 } else if (request_type == RequestType:TagArrayRead) {
371 return directory.checkResourceAvailable(CacheResourceType:TagArray, addr);
372 } else if (request_type == RequestType:TagArrayWrite) {
373 return directory.checkResourceAvailable(CacheResourceType:TagArray, addr);
375 error("Invalid RequestType type in checkResourceAvailable");
382 // Three classes of ports
383 // Class 1: downward facing network links to NB
384 out_port(requestToNB_out, CPURequestMsg, requestToNB);
385 out_port(responseToNB_out, ResponseMsg, responseToNB);
386 out_port(unblockToNB_out, UnblockMsg, unblockToNB);
389 // Class 2: upward facing ports to GPU cores
390 out_port(probeToCore_out, TDProbeRequestMsg, probeToCore);
391 out_port(responseToCore_out, ResponseMsg, responseToCore);
393 // Class 3: sideward facing ports (on "wirebuffer" links) to TCC
394 out_port(w_requestTCC_out, CPURequestMsg, w_reqToTCC);
395 out_port(w_probeTCC_out, NBProbeRequestMsg, w_probeToTCC);
396 out_port(w_respTCC_out, ResponseMsg, w_respToTCC);
399 // local trigger port
400 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
403 // request queue going to NB
409 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=8) {
410 if (triggerQueue_in.isReady(clockEdge())) {
411 peek(triggerQueue_in, TriggerMsg) {
412 TBE tbe := TBEs.lookup(in_msg.addr);
413 assert(is_valid(tbe));
414 Entry cache_entry := getCacheEntry(in_msg.addr);
415 if ((in_msg.Type == TriggerType:AcksComplete) && (tbe.Upgrade == false)) {
416 trigger(Event:ProbeAcksComplete, in_msg.addr, cache_entry, tbe);
417 } else if ((in_msg.Type == TriggerType:AcksComplete) && (tbe.Upgrade == true)) {
418 trigger(Event:ProbeAcksCompleteReissue, in_msg.addr, cache_entry, tbe);
424 // Unblock Networks (TCCdir can receive unblocks from TCC, TCPs)
425 // Port on first (of three) wire buffers from TCC
426 in_port(w_TCCUnblock_in, UnblockMsg, w_TCCUnblockToTCCDir, rank=7) {
427 if (w_TCCUnblock_in.isReady(clockEdge())) {
428 peek(w_TCCUnblock_in, UnblockMsg) {
429 TBE tbe := TBEs.lookup(in_msg.addr);
430 Entry cache_entry := getCacheEntry(in_msg.addr);
431 if (in_msg.currentOwner) {
432 trigger(Event:TCCUnblock, in_msg.addr, cache_entry, tbe);
433 } else if (in_msg.valid) {
434 trigger(Event:TCCUnblock_Sharer, in_msg.addr, cache_entry, tbe);
436 trigger(Event:TCCUnblock_NotValid, in_msg.addr, cache_entry, tbe);
442 in_port(unblockNetwork_in, UnblockMsg, unblockFromTCP, rank=6) {
443 if (unblockNetwork_in.isReady(clockEdge())) {
444 peek(unblockNetwork_in, UnblockMsg) {
445 TBE tbe := TBEs.lookup(in_msg.addr);
446 Entry cache_entry := getCacheEntry(in_msg.addr);
447 if(cache_entry.WaitingUnblocks == 1) {
448 trigger(Event:LastCoreUnblock, in_msg.addr, cache_entry, tbe);
451 trigger(Event:CoreUnblock, in_msg.addr, cache_entry, tbe);
458 //Responses from TCC, and Cores
459 // Port on second (of three) wire buffers from TCC
460 in_port(w_TCCResponse_in, ResponseMsg, w_respToTCCDir, rank=5) {
461 if (w_TCCResponse_in.isReady(clockEdge())) {
462 peek(w_TCCResponse_in, ResponseMsg) {
463 TBE tbe := TBEs.lookup(in_msg.addr);
464 Entry cache_entry := getCacheEntry(in_msg.addr);
465 if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
466 trigger(Event:TCCPrbResp, in_msg.addr, cache_entry, tbe);
472 in_port(responseNetwork_in, ResponseMsg, responseFromTCP, rank=4) {
473 if (responseNetwork_in.isReady(clockEdge())) {
474 peek(responseNetwork_in, ResponseMsg) {
475 TBE tbe := TBEs.lookup(in_msg.addr);
476 Entry cache_entry := getCacheEntry(in_msg.addr);
477 if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
478 trigger(Event:CPUPrbResp, in_msg.addr, cache_entry, tbe);
485 // Port on third (of three) wire buffers from TCC
486 in_port(w_TCCRequest_in, CPURequestMsg, w_reqToTCCDir, rank=3) {
487 if(w_TCCRequest_in.isReady(clockEdge())) {
488 peek(w_TCCRequest_in, CPURequestMsg) {
489 TBE tbe := TBEs.lookup(in_msg.addr);
490 Entry cache_entry := getCacheEntry(in_msg.addr);
491 if (in_msg.Type == CoherenceRequestType:WrCancel) {
492 trigger(Event:CancelWB, in_msg.addr, cache_entry, tbe);
493 } else if (in_msg.Type == CoherenceRequestType:VicDirty) {
494 if (is_valid(cache_entry) && cache_entry.Owner.isElement(in_msg.Requestor)) {
495 // if modified, or owner with no other sharers
496 if ((cache_entry.CacheState == State:M) || (cache_entry.Sharers.count() == 0)) {
497 assert(cache_entry.Owner.count()==1);
498 trigger(Event:VicDirtyLast, in_msg.addr, cache_entry, tbe);
500 trigger(Event:VicDirty, in_msg.addr, cache_entry, tbe);
503 trigger(Event:StaleVic, in_msg.addr, cache_entry, tbe);
506 if (in_msg.Type == CoherenceRequestType:VicClean) {
507 if (is_valid(cache_entry) && cache_entry.Sharers.isElement(in_msg.Requestor)) {
508 if (cache_entry.Sharers.count() == 1) {
509 // Last copy, victimize to L3
510 trigger(Event:VicClean, in_msg.addr, cache_entry, tbe);
512 // Either not the last copy or stall. No need to victimmize
513 // remove sharer from sharer list
514 assert(cache_entry.Sharers.count() > 1);
515 trigger(Event:NoVic, in_msg.addr, cache_entry, tbe);
518 trigger(Event:StaleVic, in_msg.addr, cache_entry, tbe);
526 in_port(responseFromNB_in, ResponseMsg, responseFromNB, rank=2) {
527 if (responseFromNB_in.isReady(clockEdge())) {
528 peek(responseFromNB_in, ResponseMsg, block_on="addr") {
530 TBE tbe := TBEs.lookup(in_msg.addr);
531 Entry cache_entry := getCacheEntry(in_msg.addr);
532 if (in_msg.Type == CoherenceResponseType:NBSysResp) {
533 if (in_msg.State == CoherenceState:Modified) {
535 trigger(Event:NB_AckCtoD, in_msg.addr, cache_entry, tbe);
537 trigger(Event:NB_AckM, in_msg.addr, cache_entry, tbe);
539 } else if (in_msg.State == CoherenceState:Shared) {
540 trigger(Event:NB_AckS, in_msg.addr, cache_entry, tbe);
541 } else if (in_msg.State == CoherenceState:Exclusive) {
542 trigger(Event:NB_AckE, in_msg.addr, cache_entry, tbe);
544 } else if (in_msg.Type == CoherenceResponseType:NBSysWBAck) {
545 trigger(Event:NB_AckWB, in_msg.addr, cache_entry, tbe);
547 error("Unexpected Response Message to Core");
553 // Finally handling incoming requests (from TCP) and probes (from NB).
555 in_port(probeNetwork_in, NBProbeRequestMsg, probeFromNB, rank=1) {
556 if (probeNetwork_in.isReady(clockEdge())) {
557 peek(probeNetwork_in, NBProbeRequestMsg) {
558 DPRINTF(RubySlicc, "%s\n", in_msg);
559 DPRINTF(RubySlicc, "machineID: %s\n", machineID);
560 Entry cache_entry := getCacheEntry(in_msg.addr);
561 TBE tbe := TBEs.lookup(in_msg.addr);
563 if (in_msg.Type == ProbeRequestType:PrbInv) {
564 if (in_msg.ReturnData) {
565 trigger(Event:PrbInvData, in_msg.addr, cache_entry, tbe);
567 trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe);
569 } else if (in_msg.Type == ProbeRequestType:PrbDowngrade) {
570 assert(in_msg.ReturnData);
571 trigger(Event:PrbShrData, in_msg.addr, cache_entry, tbe);
578 in_port(coreRequestNetwork_in, CPURequestMsg, requestFromTCP, rank=0) {
579 if (coreRequestNetwork_in.isReady(clockEdge())) {
580 peek(coreRequestNetwork_in, CPURequestMsg) {
581 TBE tbe := TBEs.lookup(in_msg.addr);
582 Entry cache_entry := getCacheEntry(in_msg.addr);
583 if (presentOrAvail(in_msg.addr)) {
584 if (in_msg.Type == CoherenceRequestType:VicDirty) {
585 trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe);
586 } else if (in_msg.Type == CoherenceRequestType:VicClean) {
587 if (is_valid(cache_entry) && cache_entry.Owner.isElement(in_msg.Requestor)) {
588 trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe);
589 } else if(is_valid(cache_entry) && (cache_entry.Sharers.count() + cache_entry.Owner.count() ) >1) {
590 trigger(Event:NoCPUWrite, in_msg.addr, cache_entry, tbe);
592 trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe);
594 } else if (in_msg.Type == CoherenceRequestType:RdBlk) {
595 trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe);
596 } else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
597 trigger(Event:RdBlkS, in_msg.addr, cache_entry, tbe);
598 } else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
599 trigger(Event:RdBlkM, in_msg.addr, cache_entry, tbe);
600 } else if (in_msg.Type == CoherenceRequestType:WrCancel) {
601 trigger(Event:CPUWriteCancel, in_msg.addr, cache_entry, tbe);
604 // All requests require a directory entry
605 Addr victim := directory.cacheProbe(in_msg.addr);
606 trigger(Event:Recall, victim, getCacheEntry(victim), TBEs.lookup(victim));
617 //Downward facing actions
619 action(c_clearOwner, "c", desc="Clear the owner field") {
620 cache_entry.Owner.clear();
623 action(rS_removeRequesterFromSharers, "rS", desc="Remove unblocker from sharer list") {
624 peek(unblockNetwork_in, UnblockMsg) {
625 cache_entry.Sharers.remove(in_msg.Sender);
629 action(rT_removeTCCFromSharers, "rT", desc="Remove TCC from sharer list") {
630 peek(w_TCCRequest_in, CPURequestMsg) {
631 cache_entry.Sharers.remove(in_msg.Requestor);
635 action(rO_removeOriginalRequestorFromSharers, "rO", desc="Remove replacing core from sharer list") {
636 peek(coreRequestNetwork_in, CPURequestMsg) {
637 cache_entry.Sharers.remove(in_msg.Requestor);
641 action(rC_removeCoreFromSharers, "rC", desc="Remove replacing core from sharer list") {
642 peek(coreRequestNetwork_in, CPURequestMsg) {
643 cache_entry.Sharers.remove(in_msg.Requestor);
647 action(rCo_removeCoreFromOwner, "rCo", desc="Remove replacing core from sharer list") {
648 // Note that under some cases this action will try to remove a stale owner
649 peek(coreRequestNetwork_in, CPURequestMsg) {
650 cache_entry.Owner.remove(in_msg.Requestor);
654 action(rR_removeResponderFromSharers, "rR", desc="Remove responder from sharer list") {
655 peek(responseNetwork_in, ResponseMsg) {
656 cache_entry.Sharers.remove(in_msg.Sender);
660 action(nC_sendNullWBAckToCore, "nC", desc = "send a null WB Ack to release core") {
661 peek(coreRequestNetwork_in, CPURequestMsg) {
662 enqueue(responseToCore_out, ResponseMsg, 1) {
663 out_msg.addr := address;
664 out_msg.Type := CoherenceResponseType:TDSysWBNack;
665 out_msg.Sender := machineID;
666 out_msg.Destination.add(in_msg.Requestor);
667 out_msg.MessageSize := in_msg.MessageSize;
672 action(nT_sendNullWBAckToTCC, "nT", desc = "send a null WB Ack to release TCC") {
673 peek(w_TCCRequest_in, CPURequestMsg) {
674 enqueue(w_respTCC_out, ResponseMsg, 1) {
675 out_msg.addr := address;
676 out_msg.Type := CoherenceResponseType:TDSysWBAck;
677 out_msg.Sender := machineID;
678 out_msg.Destination.add(in_msg.Requestor);
679 out_msg.MessageSize := in_msg.MessageSize;
684 action(eto_moveExSharerToOwner, "eto", desc="move the current exclusive sharer to owner") {
685 assert(cache_entry.Sharers.count() == 1);
686 assert(cache_entry.Owner.count() == 0);
687 cache_entry.Owner := cache_entry.Sharers;
688 cache_entry.Sharers.clear();
689 APPEND_TRANSITION_COMMENT(" new owner ");
690 APPEND_TRANSITION_COMMENT(cache_entry.Owner);
693 action(aT_addTCCToSharers, "aT", desc="Add TCC to sharer list") {
694 peek(w_TCCUnblock_in, UnblockMsg) {
695 cache_entry.Sharers.add(in_msg.Sender);
699 action(as_addToSharers, "as", desc="Add unblocker to sharer list") {
700 peek(unblockNetwork_in, UnblockMsg) {
701 cache_entry.Sharers.add(in_msg.Sender);
705 action(c_moveOwnerToSharer, "cc", desc="Move owner to sharers") {
706 cache_entry.Sharers.addNetDest(cache_entry.Owner);
707 cache_entry.Owner.clear();
710 action(cc_clearSharers, "\c", desc="Clear the sharers field") {
711 cache_entry.Sharers.clear();
714 action(e_ownerIsUnblocker, "e", desc="The owner is now the unblocker") {
715 peek(unblockNetwork_in, UnblockMsg) {
716 cache_entry.Owner.clear();
717 cache_entry.Owner.add(in_msg.Sender);
718 APPEND_TRANSITION_COMMENT(" tcp_ub owner ");
719 APPEND_TRANSITION_COMMENT(cache_entry.Owner);
723 action(eT_ownerIsUnblocker, "eT", desc="TCC (unblocker) is now owner") {
724 peek(w_TCCUnblock_in, UnblockMsg) {
725 cache_entry.Owner.clear();
726 cache_entry.Owner.add(in_msg.Sender);
727 APPEND_TRANSITION_COMMENT(" tcc_ub owner ");
728 APPEND_TRANSITION_COMMENT(cache_entry.Owner);
732 action(ctr_copyTCCResponseToTBE, "ctr", desc="Copy TCC probe response data to TBE") {
733 peek(w_TCCResponse_in, ResponseMsg) {
734 // Overwrite data if tbe does not hold dirty data. Stop once it is dirty.
735 if(tbe.Dirty == false) {
736 tbe.DataBlk := in_msg.DataBlk;
737 tbe.Dirty := in_msg.Dirty;
738 tbe.Sender := in_msg.Sender;
740 DPRINTF(RubySlicc, "%s\n", (tbe.DataBlk));
744 action(ccr_copyCoreResponseToTBE, "ccr", desc="Copy core probe response data to TBE") {
745 peek(responseNetwork_in, ResponseMsg) {
746 // Overwrite data if tbe does not hold dirty data. Stop once it is dirty.
747 if(tbe.Dirty == false) {
748 tbe.DataBlk := in_msg.DataBlk;
749 tbe.Dirty := in_msg.Dirty;
751 if(tbe.Sender == machineID) {
752 tbe.Sender := in_msg.Sender;
755 DPRINTF(RubySlicc, "%s\n", (tbe.DataBlk));
759 action(cd_clearDirtyBitTBE, "cd", desc="Clear Dirty bit in TBE") {
763 action(n_issueRdBlk, "n-", desc="Issue RdBlk") {
764 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
765 out_msg.addr := address;
766 out_msg.Type := CoherenceRequestType:RdBlk;
767 out_msg.Requestor := machineID;
768 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
769 out_msg.MessageSize := MessageSizeType:Request_Control;
773 action(nS_issueRdBlkS, "nS", desc="Issue RdBlkS") {
774 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
775 out_msg.addr := address;
776 out_msg.Type := CoherenceRequestType:RdBlkS;
777 out_msg.Requestor := machineID;
778 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
779 out_msg.MessageSize := MessageSizeType:Request_Control;
783 action(nM_issueRdBlkM, "nM", desc="Issue RdBlkM") {
784 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
785 out_msg.addr := address;
786 out_msg.Type := CoherenceRequestType:RdBlkM;
787 out_msg.Requestor := machineID;
788 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
789 out_msg.MessageSize := MessageSizeType:Request_Control;
793 action(rU_rememberUpgrade, "rU", desc="Remember that this was an upgrade") {
797 action(ruo_rememberUntransferredOwner, "ruo", desc="Remember the untransferred owner") {
798 peek(responseNetwork_in, ResponseMsg) {
799 if(in_msg.UntransferredOwner == true) {
800 tbe.UntransferredOwner := in_msg.Sender;
801 tbe.UntransferredOwnerExists := true;
803 DPRINTF(RubySlicc, "%s\n", (in_msg));
807 action(ruoT_rememberUntransferredOwnerTCC, "ruoT", desc="Remember the untransferred owner") {
808 peek(w_TCCResponse_in, ResponseMsg) {
809 if(in_msg.UntransferredOwner == true) {
810 tbe.UntransferredOwner := in_msg.Sender;
811 tbe.UntransferredOwnerExists := true;
813 DPRINTF(RubySlicc, "%s\n", (in_msg));
817 action(vd_victim, "vd", desc="Victimize M/O Data") {
818 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
819 out_msg.addr := address;
820 out_msg.Requestor := machineID;
821 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
822 out_msg.MessageSize := MessageSizeType:Request_Control;
823 out_msg.Type := CoherenceRequestType:VicDirty;
824 if (cache_entry.CacheState == State:O) {
825 out_msg.Shared := true;
827 out_msg.Shared := false;
829 out_msg.Dirty := true;
833 action(vc_victim, "vc", desc="Victimize E/S Data") {
834 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
835 out_msg.addr := address;
836 out_msg.Requestor := machineID;
837 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
838 out_msg.MessageSize := MessageSizeType:Request_Control;
839 out_msg.Type := CoherenceRequestType:VicClean;
840 if (cache_entry.CacheState == State:S) {
841 out_msg.Shared := true;
843 out_msg.Shared := false;
845 out_msg.Dirty := false;
850 action(sT_sendRequestToTCC, "sT", desc="send request to TCC") {
851 peek(coreRequestNetwork_in, CPURequestMsg) {
852 enqueue(w_requestTCC_out, CPURequestMsg, 1) {
853 out_msg.addr := address;
854 out_msg.Type := in_msg.Type;
855 out_msg.Requestor := in_msg.Requestor;
856 out_msg.DataBlk := in_msg.DataBlk;
857 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
858 TCC_select_low_bit, TCC_select_num_bits));
859 out_msg.Shared := in_msg.Shared;
860 out_msg.MessageSize := in_msg.MessageSize;
862 APPEND_TRANSITION_COMMENT(" requestor ");
863 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
869 action(sc_probeShrCoreData, "sc", desc="probe shared cores, return data") {
870 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
871 TCC_select_low_bit, TCC_select_num_bits);
873 temp := cache_entry.Sharers;
874 temp.addNetDest(cache_entry.Owner);
875 if (temp.isElement(tcc)) {
878 if (temp.count() > 0) {
879 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
880 out_msg.addr := address;
881 out_msg.Type := ProbeRequestType:PrbDowngrade;
882 out_msg.ReturnData := true;
883 out_msg.MessageSize := MessageSizeType:Control;
884 out_msg.Destination := temp;
885 tbe.NumPendingAcks := temp.count();
886 if(cache_entry.CacheState == State:M) {
887 assert(tbe.NumPendingAcks == 1);
889 DPRINTF(RubySlicc, "%s\n", (out_msg));
894 action(ls2_probeShrL2Data, "ls2", desc="local probe downgrade L2, return data") {
895 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
896 TCC_select_low_bit, TCC_select_num_bits);
897 if ((cache_entry.Sharers.isElement(tcc)) || (cache_entry.Owner.isElement(tcc))) {
898 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
899 out_msg.addr := address;
900 out_msg.Type := ProbeRequestType:PrbDowngrade;
901 out_msg.ReturnData := true;
902 out_msg.MessageSize := MessageSizeType:Control;
903 out_msg.Destination.add(tcc);
904 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
905 DPRINTF(RubySlicc, "%s\n", out_msg);
911 action(s2_probeShrL2Data, "s2", desc="probe shared L2, return data") {
912 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
913 TCC_select_low_bit, TCC_select_num_bits);
914 if ((cache_entry.Sharers.isElement(tcc)) || (cache_entry.Owner.isElement(tcc))) {
915 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
916 out_msg.addr := address;
917 out_msg.Type := ProbeRequestType:PrbDowngrade;
918 out_msg.ReturnData := true;
919 out_msg.MessageSize := MessageSizeType:Control;
920 out_msg.Destination.add(tcc);
921 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
922 DPRINTF(RubySlicc, "%s\n", out_msg);
928 action(ldc_probeInvCoreData, "ldc", desc="local probe to inv cores, return data") {
929 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
930 TCC_select_low_bit, TCC_select_num_bits);
931 peek(coreRequestNetwork_in, CPURequestMsg) {
932 NetDest dest:= cache_entry.Sharers;
933 dest.addNetDest(cache_entry.Owner);
934 if(dest.isElement(tcc)){
937 dest.remove(in_msg.Requestor);
938 tbe.NumPendingAcks := dest.count();
940 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
941 out_msg.addr := address;
942 out_msg.Type := ProbeRequestType:PrbInv;
943 out_msg.ReturnData := true;
944 out_msg.MessageSize := MessageSizeType:Control;
946 out_msg.Destination.addNetDest(dest);
947 if(cache_entry.CacheState == State:M) {
948 assert(tbe.NumPendingAcks == 1);
951 DPRINTF(RubySlicc, "%s\n", (out_msg));
957 action(ld2_probeInvL2Data, "ld2", desc="local probe inv L2, return data") {
958 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
959 TCC_select_low_bit, TCC_select_num_bits);
960 if ((cache_entry.Sharers.isElement(tcc)) || (cache_entry.Owner.isElement(tcc))) {
961 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
962 out_msg.addr := address;
963 out_msg.Type := ProbeRequestType:PrbInv;
964 out_msg.ReturnData := true;
965 out_msg.MessageSize := MessageSizeType:Control;
966 out_msg.Destination.add(tcc);
967 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
968 DPRINTF(RubySlicc, "%s\n", out_msg);
974 action(dc_probeInvCoreData, "dc", desc="probe inv cores + TCC, return data") {
975 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
976 TCC_select_low_bit, TCC_select_num_bits);
977 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
978 out_msg.addr := address;
979 out_msg.Type := ProbeRequestType:PrbInv;
980 out_msg.ReturnData := true;
981 out_msg.MessageSize := MessageSizeType:Control;
983 out_msg.Destination.addNetDest(cache_entry.Sharers);
984 out_msg.Destination.addNetDest(cache_entry.Owner);
985 tbe.NumPendingAcks := cache_entry.Sharers.count() + cache_entry.Owner.count();
986 if(cache_entry.CacheState == State:M) {
987 assert(tbe.NumPendingAcks == 1);
989 if (out_msg.Destination.isElement(tcc)) {
990 out_msg.Destination.remove(tcc);
991 tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
994 DPRINTF(RubySlicc, "%s\n", (out_msg));
998 action(d2_probeInvL2Data, "d2", desc="probe inv L2, return data") {
999 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
1000 TCC_select_low_bit, TCC_select_num_bits);
1001 if ((cache_entry.Sharers.isElement(tcc)) || (cache_entry.Owner.isElement(tcc))) {
1002 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
1003 out_msg.addr := address;
1004 out_msg.Type := ProbeRequestType:PrbInv;
1005 out_msg.ReturnData := true;
1006 out_msg.MessageSize := MessageSizeType:Control;
1007 out_msg.Destination.add(tcc);
1008 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
1009 DPRINTF(RubySlicc, "%s\n", out_msg);
1015 action(lpc_probeInvCore, "lpc", desc="local probe inv cores, no data") {
1016 peek(coreRequestNetwork_in, CPURequestMsg) {
1017 TCC_dir_subtree.broadcast(MachineType:TCP);
1018 TCC_dir_subtree.broadcast(MachineType:SQC);
1020 temp := cache_entry.Sharers;
1021 temp := temp.OR(cache_entry.Owner);
1022 TCC_dir_subtree := TCC_dir_subtree.AND(temp);
1023 tbe.NumPendingAcks := TCC_dir_subtree.count();
1024 if(cache_entry.CacheState == State:M) {
1025 assert(tbe.NumPendingAcks == 1);
1027 if(TCC_dir_subtree.isElement(in_msg.Requestor)) {
1028 TCC_dir_subtree.remove(in_msg.Requestor);
1029 tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
1032 if(TCC_dir_subtree.count() > 0) {
1033 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
1034 out_msg.addr := address;
1035 out_msg.Type := ProbeRequestType:PrbInv;
1036 out_msg.ReturnData := false;
1037 out_msg.MessageSize := MessageSizeType:Control;
1038 out_msg.localCtoD := true;
1040 out_msg.Destination.addNetDest(TCC_dir_subtree);
1042 DPRINTF(RubySlicc, "%s\n", (out_msg));
1048 action(ipc_probeInvCore, "ipc", desc="probe inv cores, no data") {
1049 TCC_dir_subtree.broadcast(MachineType:TCP);
1050 TCC_dir_subtree.broadcast(MachineType:SQC);
1052 temp := cache_entry.Sharers;
1053 temp := temp.OR(cache_entry.Owner);
1054 TCC_dir_subtree := TCC_dir_subtree.AND(temp);
1055 tbe.NumPendingAcks := TCC_dir_subtree.count();
1056 if(TCC_dir_subtree.count() > 0) {
1058 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
1059 out_msg.addr := address;
1060 out_msg.Type := ProbeRequestType:PrbInv;
1061 out_msg.ReturnData := false;
1062 out_msg.MessageSize := MessageSizeType:Control;
1064 out_msg.Destination.addNetDest(TCC_dir_subtree);
1065 if(cache_entry.CacheState == State:M) {
1066 assert(tbe.NumPendingAcks == 1);
1069 DPRINTF(RubySlicc, "%s\n", (out_msg));
1074 action(i2_probeInvL2, "i2", desc="probe inv L2, no data") {
1075 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
1076 TCC_select_low_bit, TCC_select_num_bits);
1077 if ((cache_entry.Sharers.isElement(tcc)) || (cache_entry.Owner.isElement(tcc))) {
1078 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
1079 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
1080 out_msg.addr := address;
1081 out_msg.Type := ProbeRequestType:PrbInv;
1082 out_msg.ReturnData := false;
1083 out_msg.MessageSize := MessageSizeType:Control;
1084 out_msg.Destination.add(tcc);
1085 DPRINTF(RubySlicc, "%s\n", out_msg);
1091 action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") {
1092 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1093 out_msg.addr := address;
1094 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes
1095 out_msg.Sender := machineID;
1096 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1097 out_msg.Dirty := false;
1098 out_msg.Hit := false;
1099 out_msg.Ntsl := true;
1100 out_msg.State := CoherenceState:NA;
1101 out_msg.MessageSize := MessageSizeType:Response_Control;
1105 action(pim_sendProbeResponseInvMs, "pim", desc="send probe ack inv, no data") {
1106 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1107 out_msg.addr := address;
1108 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and TCC respond in same way to probes
1109 out_msg.Sender := machineID;
1110 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1111 out_msg.Dirty := false;
1112 out_msg.Ntsl := true;
1113 out_msg.Hit := false;
1114 out_msg.State := CoherenceState:NA;
1115 out_msg.MessageSize := MessageSizeType:Response_Control;
1119 action(prm_sendProbeResponseMiss, "prm", desc="send probe ack PrbShrData, no data") {
1120 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1121 out_msg.addr := address;
1122 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and TCC respond in same way to probes
1123 out_msg.Sender := machineID;
1124 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1125 out_msg.Dirty := false; // only true if sending back data i think
1126 out_msg.Hit := false;
1127 out_msg.Ntsl := false;
1128 out_msg.State := CoherenceState:NA;
1129 out_msg.MessageSize := MessageSizeType:Response_Control;
1135 action(pd_sendProbeResponseData, "pd", desc="send probe ack, with data") {
1136 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1137 assert(is_valid(cache_entry) || is_valid(tbe));
1138 out_msg.addr := address;
1139 out_msg.Type := CoherenceResponseType:CPUPrbResp;
1140 out_msg.Sender := machineID;
1141 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1142 out_msg.DataBlk := getDataBlock(address);
1143 if (is_valid(tbe)) {
1144 out_msg.Dirty := tbe.Dirty;
1146 out_msg.Hit := true;
1147 out_msg.State := CoherenceState:NA;
1148 out_msg.MessageSize := MessageSizeType:Response_Data;
1153 action(pdm_sendProbeResponseDataMs, "pdm", desc="send probe ack, with data") {
1154 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1155 assert(is_valid(cache_entry) || is_valid(tbe));
1156 assert(is_valid(cache_entry));
1157 out_msg.addr := address;
1158 out_msg.Type := CoherenceResponseType:CPUPrbResp;
1159 out_msg.Sender := machineID;
1160 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1161 out_msg.DataBlk := getDataBlock(address);
1162 if (is_valid(tbe)) {
1163 out_msg.Dirty := tbe.Dirty;
1165 out_msg.Hit := true;
1166 out_msg.State := CoherenceState:NA;
1167 out_msg.MessageSize := MessageSizeType:Response_Data;
1171 action(mc_cancelWB, "mc", desc="send writeback cancel to NB directory") {
1172 enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
1173 out_msg.addr := address;
1174 out_msg.Type := CoherenceRequestType:WrCancel;
1175 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1176 out_msg.Requestor := machineID;
1177 out_msg.MessageSize := MessageSizeType:Request_Control;
1181 action(sCS_sendCollectiveResponseS, "sCS", desc="send shared response to all merged TCP/SQC") {
1182 enqueue(responseToCore_out, ResponseMsg, 1) {
1183 out_msg.addr := address;
1184 out_msg.Type := CoherenceResponseType:TDSysResp;
1185 out_msg.Sender := tbe.Sender;
1186 out_msg.DataBlk := tbe.DataBlk;
1187 out_msg.MessageSize := MessageSizeType:Response_Data;
1188 out_msg.CtoD := false;
1189 out_msg.State := CoherenceState:Shared;
1190 out_msg.Destination.addNetDest(cache_entry.MergedSharers);
1191 out_msg.Shared := tbe.Shared;
1192 out_msg.Dirty := tbe.Dirty;
1193 DPRINTF(RubySlicc, "%s\n", out_msg);
1197 action(sS_sendResponseS, "sS", desc="send shared response to TCP/SQC") {
1198 enqueue(responseToCore_out, ResponseMsg, 1) {
1199 out_msg.addr := address;
1200 out_msg.Type := CoherenceResponseType:TDSysResp;
1201 out_msg.Sender := tbe.Sender;
1202 out_msg.DataBlk := tbe.DataBlk;
1203 out_msg.MessageSize := MessageSizeType:Response_Data;
1204 out_msg.CtoD := false;
1205 out_msg.State := CoherenceState:Shared;
1206 out_msg.Destination.add(tbe.OriginalRequestor);
1207 out_msg.Shared := tbe.Shared;
1208 out_msg.Dirty := tbe.Dirty;
1209 DPRINTF(RubySlicc, "%s\n", out_msg);
1213 action(sM_sendResponseM, "sM", desc="send response to TCP/SQC") {
1214 enqueue(responseToCore_out, ResponseMsg, 1) {
1215 out_msg.addr := address;
1216 out_msg.Type := CoherenceResponseType:TDSysResp;
1217 out_msg.Sender := tbe.Sender;
1218 out_msg.DataBlk := tbe.DataBlk;
1219 out_msg.MessageSize := MessageSizeType:Response_Data;
1220 out_msg.CtoD := false;
1221 out_msg.State := CoherenceState:Modified;
1222 out_msg.Destination.add(tbe.OriginalRequestor);
1223 out_msg.Shared := tbe.Shared;
1224 out_msg.Dirty := tbe.Dirty;
1225 DPRINTF(RubySlicc, "%s\n", out_msg);
1231 action(fw2_forwardWBAck, "fw2", desc="forward WBAck to TCC") {
1232 peek(responseFromNB_in, ResponseMsg) {
1233 if(tbe.OriginalRequestor != machineID) {
1234 enqueue(w_respTCC_out, ResponseMsg, 1) {
1235 out_msg.addr := address;
1236 out_msg.Type := CoherenceResponseType:TDSysWBAck;
1237 out_msg.Sender := machineID;
1238 //out_msg.DataBlk := tbe.DataBlk;
1239 out_msg.Destination.add(tbe.OriginalRequestor);
1240 out_msg.MessageSize := in_msg.MessageSize;
1246 action(sa_saveSysAck, "sa", desc="Save SysAck ") {
1247 peek(responseFromNB_in, ResponseMsg) {
1248 tbe.Dirty := in_msg.Dirty;
1249 if (tbe.Dirty == false) {
1250 tbe.DataBlk := in_msg.DataBlk;
1253 tbe.DataBlk := tbe.DataBlk;
1255 tbe.CtoD := in_msg.CtoD;
1256 tbe.CohState := in_msg.State;
1257 tbe.Shared := in_msg.Shared;
1258 tbe.MessageSize := in_msg.MessageSize;
1262 action(fsa_forwardSavedAck, "fsa", desc="forward saved SysAck to TCP or SQC") {
1263 enqueue(responseToCore_out, ResponseMsg, 1) {
1264 out_msg.addr := address;
1265 out_msg.Type := CoherenceResponseType:TDSysResp;
1266 out_msg.Sender := machineID;
1267 if (tbe.Dirty == false) {
1268 out_msg.DataBlk := tbe.DataBlk;
1271 out_msg.DataBlk := tbe.DataBlk;
1273 out_msg.CtoD := tbe.CtoD;
1274 out_msg.State := tbe.CohState;
1275 out_msg.Destination.add(tbe.OriginalRequestor);
1276 out_msg.Shared := tbe.Shared;
1277 out_msg.MessageSize := tbe.MessageSize;
1278 out_msg.Dirty := tbe.Dirty;
1279 out_msg.Sender := tbe.Sender;
1283 action(fa_forwardSysAck, "fa", desc="forward SysAck to TCP or SQC") {
1284 peek(responseFromNB_in, ResponseMsg) {
1285 enqueue(responseToCore_out, ResponseMsg, 1) {
1286 out_msg.addr := address;
1287 out_msg.Type := CoherenceResponseType:TDSysResp;
1288 out_msg.Sender := machineID;
1289 if (tbe.Dirty == false) {
1290 out_msg.DataBlk := in_msg.DataBlk;
1291 tbe.Sender := machineID;
1294 out_msg.DataBlk := tbe.DataBlk;
1296 out_msg.CtoD := in_msg.CtoD;
1297 out_msg.State := in_msg.State;
1298 out_msg.Destination.add(tbe.OriginalRequestor);
1299 out_msg.Shared := in_msg.Shared;
1300 out_msg.MessageSize := in_msg.MessageSize;
1301 out_msg.Dirty := in_msg.Dirty;
1302 out_msg.Sender := tbe.Sender;
1303 DPRINTF(RubySlicc, "%s\n", (out_msg.DataBlk));
1308 action(pso_probeSharedDataOwner, "pso", desc="probe shared data at owner") {
1309 MachineID tcc := mapAddressToRange(address,MachineType:TCC,
1310 TCC_select_low_bit, TCC_select_num_bits);
1311 if (cache_entry.Owner.isElement(tcc)) {
1312 enqueue(w_probeTCC_out, TDProbeRequestMsg, 1) {
1313 out_msg.addr := address;
1314 out_msg.Type := ProbeRequestType:PrbDowngrade;
1315 out_msg.ReturnData := true;
1316 out_msg.MessageSize := MessageSizeType:Control;
1317 out_msg.Destination.add(tcc);
1318 DPRINTF(RubySlicc, "%s\n", out_msg);
1321 else { // i.e., owner is a core
1322 enqueue(probeToCore_out, TDProbeRequestMsg, response_latency) {
1323 out_msg.addr := address;
1324 out_msg.Type := ProbeRequestType:PrbDowngrade;
1325 out_msg.ReturnData := true;
1326 out_msg.MessageSize := MessageSizeType:Control;
1327 out_msg.Destination.addNetDest(cache_entry.Owner);
1328 DPRINTF(RubySlicc, "%s\n", out_msg);
1331 tbe.NumPendingAcks := 1;
1334 action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
1335 coreRequestNetwork_in.dequeue(clockEdge());
1338 action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
1339 unblockNetwork_in.dequeue(clockEdge());
1342 action(pk_popResponseQueue, "pk", desc="Pop response queue") {
1343 responseNetwork_in.dequeue(clockEdge());
1346 action(pp_popProbeQueue, "pp", desc="Pop incoming probe queue") {
1347 probeNetwork_in.dequeue(clockEdge());
1350 action(pR_popResponseFromNBQueue, "pR", desc="Pop incoming Response queue From NB") {
1351 responseFromNB_in.dequeue(clockEdge());
1354 action(pt_popTriggerQueue, "pt", desc="pop trigger queue") {
1355 triggerQueue_in.dequeue(clockEdge());
1358 action(pl_popTCCRequestQueue, "pl", desc="pop TCC request queue") {
1359 w_TCCRequest_in.dequeue(clockEdge());
1362 action(plr_popTCCResponseQueue, "plr", desc="pop TCC response queue") {
1363 w_TCCResponse_in.dequeue(clockEdge());
1366 action(plu_popTCCUnblockQueue, "plu", desc="pop TCC unblock queue") {
1367 w_TCCUnblock_in.dequeue(clockEdge());
1371 action(m_addUnlockerToSharers, "m", desc="Add the unlocker to the sharer list") {
1372 peek(unblockNetwork_in, UnblockMsg) {
1373 cache_entry.Sharers.add(in_msg.Sender);
1374 cache_entry.MergedSharers.remove(in_msg.Sender);
1375 assert(cache_entry.WaitingUnblocks >= 0);
1376 cache_entry.WaitingUnblocks := cache_entry.WaitingUnblocks - 1;
1380 action(q_addOutstandingMergedSharer, "q", desc="Increment outstanding requests") {
1381 peek(coreRequestNetwork_in, CPURequestMsg) {
1382 cache_entry.MergedSharers.add(in_msg.Requestor);
1383 cache_entry.WaitingUnblocks := cache_entry.WaitingUnblocks + 1;
1387 action(uu_sendUnblock, "uu", desc="state changed, unblock") {
1388 enqueue(unblockToNB_out, UnblockMsg, issue_latency) {
1389 out_msg.addr := address;
1390 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1391 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1392 DPRINTF(RubySlicc, "%s\n", out_msg);
1396 action(zz_recycleRequest, "\z", desc="Recycle the request queue") {
1397 coreRequestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1400 action(yy_recycleTCCRequestQueue, "yy", desc="recycle yy request queue") {
1401 w_TCCRequest_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1404 action(xz_recycleResponseQueue, "xz", desc="recycle response queue") {
1405 responseNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1408 action(xx_recycleTCCResponseQueue, "xx", desc="recycle TCC response queue") {
1409 w_TCCResponse_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1412 action(vv_recycleTCCUnblockQueue, "vv", desc="Recycle the probe request queue") {
1413 w_TCCUnblock_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1416 action(xy_recycleUnblockQueue, "xy", desc="Recycle the probe request queue") {
1417 w_TCCUnblock_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1420 action(ww_recycleProbeRequest, "ww", desc="Recycle the probe request queue") {
1421 probeNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1424 action(x_decrementAcks, "x", desc="decrement Acks pending") {
1425 tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
1428 action(o_checkForAckCompletion, "o", desc="check for ack completion") {
1429 if (tbe.NumPendingAcks == 0) {
1430 enqueue(triggerQueue_out, TriggerMsg, 1) {
1431 out_msg.addr := address;
1432 out_msg.Type := TriggerType:AcksComplete;
1435 APPEND_TRANSITION_COMMENT(" tbe acks ");
1436 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
1439 action(tp_allocateTBE, "tp", desc="allocate TBE Entry for upward transactions") {
1440 check_allocate(TBEs);
1441 peek(probeNetwork_in, NBProbeRequestMsg) {
1442 TBEs.allocate(address);
1443 set_tbe(TBEs.lookup(address));
1445 tbe.NumPendingAcks := 0;
1446 tbe.UntransferredOwnerExists := false;
1450 action(tv_allocateTBE, "tv", desc="allocate TBE Entry for TCC transactions") {
1451 check_allocate(TBEs);
1452 peek(w_TCCRequest_in, CPURequestMsg) {
1453 TBEs.allocate(address);
1454 set_tbe(TBEs.lookup(address));
1455 tbe.DataBlk := in_msg.DataBlk; // Data only for WBs
1457 tbe.OriginalRequestor := in_msg.Requestor;
1458 tbe.NumPendingAcks := 0;
1459 tbe.UntransferredOwnerExists := false;
1463 action(t_allocateTBE, "t", desc="allocate TBE Entry") {
1464 check_allocate(TBEs);//check whether resources are full
1465 peek(coreRequestNetwork_in, CPURequestMsg) {
1466 TBEs.allocate(address);
1467 set_tbe(TBEs.lookup(address));
1468 tbe.DataBlk := cache_entry.DataBlk; // Data only for WBs
1470 tbe.Upgrade := false;
1471 tbe.OriginalRequestor := in_msg.Requestor;
1472 tbe.NumPendingAcks := 0;
1473 tbe.UntransferredOwnerExists := false;
1474 tbe.Sender := machineID;
1478 action(tr_allocateTBE, "tr", desc="allocate TBE Entry for recall") {
1479 check_allocate(TBEs);//check whether resources are full
1480 TBEs.allocate(address);
1481 set_tbe(TBEs.lookup(address));
1482 tbe.DataBlk := cache_entry.DataBlk; // Data only for WBs
1484 tbe.Upgrade := false;
1485 tbe.OriginalRequestor := machineID; //Recall request, Self initiated
1486 tbe.NumPendingAcks := 0;
1487 tbe.UntransferredOwnerExists := false;
1490 action(dt_deallocateTBE, "dt", desc="Deallocate TBE entry") {
1491 TBEs.deallocate(address);
1496 action(d_allocateDir, "d", desc="allocate Directory Cache") {
1497 if (is_invalid(cache_entry)) {
1498 set_cache_entry(directory.allocate(address, new Entry));
1502 action(dd_deallocateDir, "dd", desc="deallocate Directory Cache") {
1503 if (is_valid(cache_entry)) {
1504 directory.deallocate(address);
1506 unset_cache_entry();
1509 action(ss_sendStaleNotification, "ss", desc="stale data; nothing to writeback") {
1510 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1511 out_msg.addr := address;
1512 out_msg.Type := CoherenceResponseType:StaleNotif;
1513 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1514 out_msg.Sender := machineID;
1515 out_msg.MessageSize := MessageSizeType:Response_Control;
1519 action(wb_data, "wb", desc="write back data") {
1520 enqueue(responseToNB_out, ResponseMsg, issue_latency) {
1521 out_msg.addr := address;
1522 out_msg.Type := CoherenceResponseType:CPUData;
1523 out_msg.Sender := machineID;
1524 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1525 out_msg.DataBlk := tbe.DataBlk;
1526 out_msg.Dirty := tbe.Dirty;
1528 out_msg.NbReqShared := true;
1530 out_msg.NbReqShared := false;
1532 out_msg.State := CoherenceState:Shared; // faux info
1533 out_msg.MessageSize := MessageSizeType:Writeback_Data;
1534 DPRINTF(RubySlicc, "%s\n", out_msg);
1538 action(sf_setSharedFlip, "sf", desc="hit by shared probe, status may be different") {
1539 assert(is_valid(tbe));
1543 action(y_writeDataToTBE, "y", desc="write Probe Data to TBE") {
1544 peek(responseNetwork_in, ResponseMsg) {
1545 if (!tbe.Dirty || in_msg.Dirty) {
1546 tbe.DataBlk := in_msg.DataBlk;
1547 tbe.Dirty := in_msg.Dirty;
1555 action(ty_writeTCCDataToTBE, "ty", desc="write TCC Probe Data to TBE") {
1556 peek(w_TCCResponse_in, ResponseMsg) {
1557 if (!tbe.Dirty || in_msg.Dirty) {
1558 tbe.DataBlk := in_msg.DataBlk;
1559 tbe.Dirty := in_msg.Dirty;
1568 action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") {
1569 directory.setMRU(address);
1574 // Handling TCP/SQC requests (similar to how NB dir handles TCC events with some changes to account for stateful directory).
1577 // transitions from base
1578 transition(I, RdBlk, I_ES){TagArrayRead} {
1582 i_popIncomingRequestQueue;
1585 transition(I, RdBlkS, I_S){TagArrayRead} {
1589 i_popIncomingRequestQueue;
1593 transition(I_S, NB_AckS, BBB_S) {
1595 pR_popResponseFromNBQueue;
1598 transition(I_ES, NB_AckS, BBB_S) {
1600 pR_popResponseFromNBQueue;
1603 transition(I_ES, NB_AckE, BBB_E) {
1605 pR_popResponseFromNBQueue;
1608 transition({S_M, O_M}, {NB_AckCtoD,NB_AckM}, BBB_M) {
1610 pR_popResponseFromNBQueue;
1613 transition(I_M, NB_AckM, BBB_M) {
1615 pR_popResponseFromNBQueue;
1618 transition(BBB_M, CoreUnblock, M){TagArrayWrite} {
1624 j_popIncomingUnblockQueue;
1627 transition(BBB_S, CoreUnblock, S){TagArrayWrite} {
1631 j_popIncomingUnblockQueue;
1634 transition(BBB_E, CoreUnblock, E){TagArrayWrite} {
1638 j_popIncomingUnblockQueue;
1642 transition(I, RdBlkM, I_M){TagArrayRead} {
1646 i_popIncomingRequestQueue;
1650 transition(S, {RdBlk, RdBlkS}, BBS_S){TagArrayRead} {
1652 sc_probeShrCoreData;
1654 q_addOutstandingMergedSharer;
1655 i_popIncomingRequestQueue;
1657 // Merging of read sharing into a single request
1658 transition(BBS_S, {RdBlk, RdBlkS}) {
1659 q_addOutstandingMergedSharer;
1660 i_popIncomingRequestQueue;
1662 // Wait for probe acks to be complete
1663 transition(BBS_S, CPUPrbResp) {
1664 ccr_copyCoreResponseToTBE;
1666 o_checkForAckCompletion;
1667 pk_popResponseQueue;
1670 transition(BBS_S, TCCPrbResp) {
1671 ctr_copyTCCResponseToTBE;
1673 o_checkForAckCompletion;
1674 plr_popTCCResponseQueue;
1677 // Window for merging complete with this transition
1678 // Send responses to all outstanding
1679 transition(BBS_S, ProbeAcksComplete, BB_S) {
1680 sCS_sendCollectiveResponseS;
1684 transition(BB_S, CoreUnblock, BB_S) {
1685 m_addUnlockerToSharers;
1686 j_popIncomingUnblockQueue;
1689 transition(BB_S, LastCoreUnblock, S) {
1690 m_addUnlockerToSharers;
1692 j_popIncomingUnblockQueue;
1695 transition(O, {RdBlk, RdBlkS}, BBO_O){TagArrayRead} {
1697 pso_probeSharedDataOwner;
1698 q_addOutstandingMergedSharer;
1699 i_popIncomingRequestQueue;
1701 // Merging of read sharing into a single request
1702 transition(BBO_O, {RdBlk, RdBlkS}) {
1703 q_addOutstandingMergedSharer;
1704 i_popIncomingRequestQueue;
1707 // Wait for probe acks to be complete
1708 transition(BBO_O, CPUPrbResp) {
1709 ccr_copyCoreResponseToTBE;
1711 o_checkForAckCompletion;
1712 pk_popResponseQueue;
1715 transition(BBO_O, TCCPrbResp) {
1716 ctr_copyTCCResponseToTBE;
1718 o_checkForAckCompletion;
1719 plr_popTCCResponseQueue;
1722 // Window for merging complete with this transition
1723 // Send responses to all outstanding
1724 transition(BBO_O, ProbeAcksComplete, BB_OO) {
1725 sCS_sendCollectiveResponseS;
1729 transition(BB_OO, CoreUnblock) {
1730 m_addUnlockerToSharers;
1731 j_popIncomingUnblockQueue;
1734 transition(BB_OO, LastCoreUnblock, O){TagArrayWrite} {
1735 m_addUnlockerToSharers;
1737 j_popIncomingUnblockQueue;
1740 transition(S, CPUWrite, BW_S){TagArrayRead} {
1742 rC_removeCoreFromSharers;
1743 sT_sendRequestToTCC;
1744 i_popIncomingRequestQueue;
1747 transition(E, CPUWrite, BW_E){TagArrayRead} {
1749 rC_removeCoreFromSharers;
1750 sT_sendRequestToTCC;
1751 i_popIncomingRequestQueue;
1754 transition(O, CPUWrite, BW_O){TagArrayRead} {
1756 rCo_removeCoreFromOwner;
1757 rC_removeCoreFromSharers;
1758 sT_sendRequestToTCC;
1759 i_popIncomingRequestQueue;
1762 transition(M, CPUWrite, BW_M){TagArrayRead} {
1764 rCo_removeCoreFromOwner;
1765 rC_removeCoreFromSharers;
1766 sT_sendRequestToTCC;
1767 i_popIncomingRequestQueue;
1770 transition(BW_S, TCCUnblock_Sharer, S){TagArrayWrite} {
1773 plu_popTCCUnblockQueue;
1776 transition(BW_S, TCCUnblock_NotValid, S){TagArrayWrite} {
1778 plu_popTCCUnblockQueue;
1781 transition(BW_E, TCCUnblock, E){TagArrayWrite} {
1785 plu_popTCCUnblockQueue;
1788 transition(BW_E, TCCUnblock_NotValid, E) {
1790 plu_popTCCUnblockQueue;
1793 transition(BW_M, TCCUnblock, M) {
1796 eT_ownerIsUnblocker;
1798 plu_popTCCUnblockQueue;
1801 transition(BW_M, TCCUnblock_NotValid, M) {
1802 // Note this transition should only be executed if we received a stale wb
1804 plu_popTCCUnblockQueue;
1807 transition(BW_O, TCCUnblock, O) {
1809 eT_ownerIsUnblocker;
1811 plu_popTCCUnblockQueue;
1814 transition(BW_O, TCCUnblock_NotValid, O) {
1815 // Note this transition should only be executed if we received a stale wb
1817 plu_popTCCUnblockQueue;
1820 // We lost the owner likely do to an invalidation racing with a 'O' wb
1821 transition(BW_O, TCCUnblock_Sharer, S) {
1825 plu_popTCCUnblockQueue;
1828 transition({BW_M, BW_S, BW_E, BW_O}, {PrbInv,PrbInvData,PrbShrData}) {
1829 ww_recycleProbeRequest;
1832 transition(BRWD_I, {PrbInvData, PrbInv, PrbShrData}) {
1833 ww_recycleProbeRequest;
1836 // Three step process: locally invalidate others, issue CtoD, wait for NB_AckCtoD
1837 transition(S, CtoD, BBS_UM) {TagArrayRead} {
1841 o_checkForAckCompletion;
1842 i_popIncomingRequestQueue;
1845 transition(BBS_UM, CPUPrbResp, BBS_UM) {
1847 o_checkForAckCompletion;
1848 pk_popResponseQueue;
1851 transition(BBS_UM, TCCPrbResp) {
1853 o_checkForAckCompletion;
1854 plr_popTCCResponseQueue;
1857 transition(BBS_UM, ProbeAcksComplete, S_M) {
1863 // Three step process: locally invalidate others, issue CtoD, wait for NB_AckCtoD
1864 transition(O, CtoD, BBO_UM){TagArrayRead} {
1868 o_checkForAckCompletion;
1869 i_popIncomingRequestQueue;
1872 transition(BBO_UM, CPUPrbResp, BBO_UM) {
1873 ruo_rememberUntransferredOwner;
1875 o_checkForAckCompletion;
1876 pk_popResponseQueue;
1879 transition(BBO_UM, TCCPrbResp) {
1880 ruoT_rememberUntransferredOwnerTCC;
1882 o_checkForAckCompletion;
1883 plr_popTCCResponseQueue;
1886 transition(BBO_UM, ProbeAcksComplete, O_M) {
1892 transition({S,E}, RdBlkM, BBS_M){TagArrayWrite} {
1894 ldc_probeInvCoreData;
1896 o_checkForAckCompletion;
1897 i_popIncomingRequestQueue;
1900 transition(BBS_M, CPUPrbResp) {
1901 ccr_copyCoreResponseToTBE;
1902 rR_removeResponderFromSharers;
1904 o_checkForAckCompletion;
1905 pk_popResponseQueue;
1908 transition(BBS_M, TCCPrbResp) {
1909 ctr_copyTCCResponseToTBE;
1911 o_checkForAckCompletion;
1912 plr_popTCCResponseQueue;
1915 transition(BBS_M, ProbeAcksComplete, S_M) {
1920 transition(O, RdBlkM, BBO_M){TagArrayRead} {
1922 ldc_probeInvCoreData;
1924 o_checkForAckCompletion;
1925 i_popIncomingRequestQueue;
1928 transition(BBO_M, CPUPrbResp) {
1929 ccr_copyCoreResponseToTBE;
1930 rR_removeResponderFromSharers;
1932 o_checkForAckCompletion;
1933 pk_popResponseQueue;
1936 transition(BBO_M, TCCPrbResp) {
1937 ctr_copyTCCResponseToTBE;
1939 o_checkForAckCompletion;
1940 plr_popTCCResponseQueue;
1943 transition(BBO_M, ProbeAcksComplete, O_M) {
1949 transition(M, RdBlkM, BBM_M){TagArrayRead} {
1951 ldc_probeInvCoreData;
1953 i_popIncomingRequestQueue;
1956 transition(BBM_M, CPUPrbResp) {
1957 ccr_copyCoreResponseToTBE;
1959 o_checkForAckCompletion;
1960 pk_popResponseQueue;
1963 // TCP recalled block before receiving probe
1964 transition({BBM_M, BBS_M, BBO_M}, {CPUWrite,NoCPUWrite}) {
1968 transition(BBM_M, TCCPrbResp) {
1969 ctr_copyTCCResponseToTBE;
1971 o_checkForAckCompletion;
1972 plr_popTCCResponseQueue;
1975 transition(BBM_M, ProbeAcksComplete, BB_M) {
1980 transition(BB_M, CoreUnblock, M){TagArrayWrite} {
1983 j_popIncomingUnblockQueue;
1986 transition(M, {RdBlkS, RdBlk}, BBM_O){TagArrayRead} {
1988 sc_probeShrCoreData;
1990 i_popIncomingRequestQueue;
1993 transition(E, {RdBlkS, RdBlk}, BBM_O){TagArrayRead} {
1995 eto_moveExSharerToOwner;
1996 sc_probeShrCoreData;
1998 i_popIncomingRequestQueue;
2001 transition(BBM_O, CPUPrbResp) {
2002 ccr_copyCoreResponseToTBE;
2004 o_checkForAckCompletion;
2005 pk_popResponseQueue;
2007 transition(BBM_O, TCCPrbResp) {
2008 ctr_copyTCCResponseToTBE;
2010 o_checkForAckCompletion;
2011 plr_popTCCResponseQueue;
2013 transition(BBM_O, ProbeAcksComplete, BB_O) {
2018 transition(BB_O, CoreUnblock, O){TagArrayWrite} {
2021 j_popIncomingUnblockQueue;
2024 transition({BBO_O, BBM_M, BBS_S, BBM_O, BB_M, BB_O, BB_S, BBO_UM, BBS_UM, BBS_M, BBO_M, BB_OO}, {PrbInvData, PrbInv,PrbShrData}) {
2025 ww_recycleProbeRequest;
2028 transition({BBM_O, BBS_S, CP_S, CP_O, CP_SM, CP_OM, BBO_O}, {CPUWrite,NoCPUWrite}) {
2032 // stale CtoD raced with external invalidation
2033 transition({I, CP_I, B_I, CP_IOM, CP_ISM, CP_OSIW, BRWD_I, BRW_I, BRD_I}, CtoD) {
2034 i_popIncomingRequestQueue;
2037 // stale CtoD raced with internal RdBlkM
2038 transition({BBM_M, BBS_M, BBO_M, BBB_M, BBS_UM, BBO_UM}, CtoD) {
2039 i_popIncomingRequestQueue;
2042 transition({E, M}, CtoD) {
2043 i_popIncomingRequestQueue;
2047 // TCC-directory has sent out (And potentially received acks for) probes.
2048 // TCP/SQC replacement (known to be stale subsequent) are popped off.
2049 transition({BBO_UM, BBS_UM}, {CPUWrite,NoCPUWrite}) {
2050 nC_sendNullWBAckToCore;
2051 i_popIncomingRequestQueue;
2054 transition(S_M, {NoCPUWrite, CPUWrite}) {
2058 transition(O_M, {NoCPUWrite, CPUWrite}) {
2063 transition({BBM_M, BBS_M, BBO_M, BBO_UM, BBS_UM}, {VicDirty, VicClean, VicDirtyLast, NoVic}) {
2064 nT_sendNullWBAckToTCC;
2065 pl_popTCCRequestQueue;
2068 transition({CP_S, CP_O, CP_OM, CP_SM}, {VicDirty, VicClean, VicDirtyLast, CancelWB, NoVic}) {
2069 yy_recycleTCCRequestQueue;
2072 // However, when TCCdir has sent out PrbSharedData, one cannot ignore.
2073 transition({BBS_S, BBO_O, BBM_O, S_M, O_M, BBB_M, BBB_S, BBB_E}, {VicDirty, VicClean, VicDirtyLast,CancelWB}) {
2074 yy_recycleTCCRequestQueue;
2077 transition({BW_S,BW_E,BW_O, BW_M}, {VicDirty, VicClean, VicDirtyLast, NoVic}) {
2078 yy_recycleTCCRequestQueue;
2081 transition({BW_S,BW_E,BW_O, BW_M}, CancelWB) {
2082 nT_sendNullWBAckToTCC;
2083 pl_popTCCRequestQueue;
2087 /// recycle if waiting for unblocks.
2088 transition({BB_M,BB_O,BB_S,BB_OO}, {VicDirty, VicClean, VicDirtyLast,NoVic,CancelWB}) {
2089 yy_recycleTCCRequestQueue;
2092 transition({BBS_S, BBO_O}, NoVic) {
2093 rT_removeTCCFromSharers;
2094 nT_sendNullWBAckToTCC;
2095 pl_popTCCRequestQueue;
2098 // stale. Pop message and send dummy ack.
2099 transition({I_S, I_ES, I_M}, {VicDirty, VicClean, VicDirtyLast, NoVic}) {
2100 nT_sendNullWBAckToTCC;
2101 pl_popTCCRequestQueue;
2104 transition(M, VicDirtyLast, VM_I){TagArrayRead} {
2107 pl_popTCCRequestQueue;
2110 transition(E, VicDirty, VM_I){TagArrayRead} {
2113 pl_popTCCRequestQueue;
2116 transition(O, VicDirty, VO_S){TagArrayRead} {
2119 pl_popTCCRequestQueue;
2122 transition(O, {VicDirtyLast, VicClean}, VO_I){TagArrayRead} {
2125 pl_popTCCRequestQueue;
2128 transition({E, S}, VicClean, VES_I){TagArrayRead} {
2131 pl_popTCCRequestQueue;
2134 transition({O, S}, NoVic){TagArrayRead} {
2135 rT_removeTCCFromSharers;
2136 nT_sendNullWBAckToTCC;
2137 pl_popTCCRequestQueue;
2140 transition({O,S}, NoCPUWrite){TagArrayRead} {
2141 rC_removeCoreFromSharers;
2142 nC_sendNullWBAckToCore;
2143 i_popIncomingRequestQueue;
2146 transition({M,E}, NoCPUWrite){TagArrayRead} {
2147 rC_removeCoreFromSharers;
2148 nC_sendNullWBAckToCore;
2149 i_popIncomingRequestQueue;
2152 // This can only happen if it is race. (TCCdir sent out probes which caused this cancel in the first place.)
2153 transition({VM_I, VES_I, VO_I}, CancelWB) {
2154 pl_popTCCRequestQueue;
2157 transition({VM_I, VES_I, VO_I}, NB_AckWB, I){TagArrayWrite} {
2164 pR_popResponseFromNBQueue;
2167 transition(VO_S, NB_AckWB, S){TagArrayWrite} {
2172 pR_popResponseFromNBQueue;
2175 transition(I_C, NB_AckWB, I){TagArrayWrite} {
2178 ss_sendStaleNotification;
2182 pR_popResponseFromNBQueue;
2185 transition(I_W, NB_AckWB, I) {
2186 ss_sendStaleNotification;
2189 pR_popResponseFromNBQueue;
2194 // Do not handle replacements, reads of any kind or writebacks from transients; recycle
2195 transition({I_M, I_ES, I_S, MO_I, ES_I, S_M, O_M, VES_I, VO_I, VO_S, VM_I, I_C, I_W}, {RdBlkS,RdBlkM,RdBlk,CtoD}) {
2199 transition( VO_S, NoCPUWrite) {
2203 transition({BW_M, BW_S, BW_O, BW_E}, {RdBlkS,RdBlkM,RdBlk,CtoD,NoCPUWrite, CPUWrite}) {
2207 transition({BBB_M, BBB_S, BBB_E, BB_O, BB_M, BB_S, BB_OO}, { RdBlk, RdBlkS, RdBlkM, CPUWrite, NoCPUWrite}) {
2211 transition({BBB_S, BBB_E, BB_O, BB_S, BB_OO}, { CtoD}) {
2215 transition({BBS_UM, BBO_UM, BBM_M, BBM_O, BBS_M, BBO_M}, { RdBlk, RdBlkS, RdBlkM}) {
2219 transition(BBM_O, CtoD) {
2223 transition({BBS_S, BBO_O}, {RdBlkM, CtoD}) {
2227 transition({B_I, CP_I, CP_S, CP_O, CP_OM, CP_SM, CP_IOM, CP_ISM, CP_OSIW, BRWD_I, BRW_I, BRD_I}, {RdBlk, RdBlkS, RdBlkM}) {
2231 transition({CP_O, CP_S, CP_OM}, CtoD) {
2235 // Ignore replacement related messages after probe got in.
2236 transition({CP_I, B_I, CP_IOM, CP_ISM, CP_OSIW, BRWD_I, BRW_I, BRD_I}, {CPUWrite, NoCPUWrite}) {
2240 // Ignore replacement related messages after probes processed
2241 transition({I, I_S, I_ES, I_M, I_C, I_W}, {CPUWrite,NoCPUWrite}) {
2242 nC_sendNullWBAckToCore;
2243 i_popIncomingRequestQueue;
2245 // cannot ignore cancel... otherwise TCP/SQC will be stuck in I_C
2246 transition({I, I_S, I_ES, I_M, I_C, I_W, S_M, M, O, E, S}, CPUWriteCancel){TagArrayRead} {
2247 nC_sendNullWBAckToCore;
2248 i_popIncomingRequestQueue;
2251 transition({CP_I, B_I, CP_IOM, CP_ISM, BRWD_I, BRW_I, BRD_I}, {NoVic, VicClean, VicDirty, VicDirtyLast}){
2252 nT_sendNullWBAckToTCC;
2253 pl_popTCCRequestQueue;
2256 // Handling Probes from NB (General process: (1) propagate up, go to blocking state (2) process acks (3) on last ack downward.)
2259 transition({M, O, E, S}, PrbInvData, CP_I){TagArrayRead} {
2261 dc_probeInvCoreData;
2266 transition(CP_I, CPUPrbResp) {
2269 o_checkForAckCompletion;
2270 pk_popResponseQueue;
2273 transition(CP_I, TCCPrbResp) {
2274 ty_writeTCCDataToTBE;
2276 o_checkForAckCompletion;
2277 plr_popTCCResponseQueue;
2280 transition(CP_I, ProbeAcksComplete, I){TagArrayWrite} {
2281 pd_sendProbeResponseData;
2290 transition({M, O, E, S}, PrbInv, B_I){TagArrayWrite} {
2297 transition(B_I, CPUPrbResp) {
2299 o_checkForAckCompletion;
2300 pk_popResponseQueue;
2303 transition(B_I, TCCPrbResp) {
2305 o_checkForAckCompletion;
2306 plr_popTCCResponseQueue;
2309 transition(B_I, ProbeAcksComplete, I){TagArrayWrite} {
2310 // send response down to NB
2311 pi_sendProbeResponseInv;
2321 transition({M, O}, PrbShrData, CP_O){TagArrayRead} {
2323 sc_probeShrCoreData;
2328 transition(E, PrbShrData, CP_O){TagArrayRead} {
2330 eto_moveExSharerToOwner;
2331 sc_probeShrCoreData;
2336 transition(CP_O, CPUPrbResp) {
2339 o_checkForAckCompletion;
2340 pk_popResponseQueue;
2343 transition(CP_O, TCCPrbResp) {
2344 ty_writeTCCDataToTBE;
2346 o_checkForAckCompletion;
2347 plr_popTCCResponseQueue;
2350 transition(CP_O, ProbeAcksComplete, O){TagArrayWrite} {
2351 // send response down to NB
2352 pd_sendProbeResponseData;
2358 transition(S, PrbShrData, CP_S) {
2360 sc_probeShrCoreData;
2365 transition(CP_S, CPUPrbResp) {
2368 o_checkForAckCompletion;
2369 pk_popResponseQueue;
2372 transition(CP_S, TCCPrbResp) {
2373 ty_writeTCCDataToTBE;
2375 o_checkForAckCompletion;
2376 plr_popTCCResponseQueue;
2379 transition(CP_S, ProbeAcksComplete, S) {
2380 // send response down to NB
2381 pd_sendProbeResponseData;
2387 transition(O_M, PrbInvData, CP_IOM) {
2388 dc_probeInvCoreData;
2393 transition(CP_IOM, CPUPrbResp) {
2396 o_checkForAckCompletion;
2397 pk_popResponseQueue;
2400 transition(CP_IOM, TCCPrbResp) {
2401 ty_writeTCCDataToTBE;
2403 o_checkForAckCompletion;
2404 plr_popTCCResponseQueue;
2407 transition(CP_IOM, ProbeAcksComplete, I_M) {
2408 pdm_sendProbeResponseDataMs;
2411 cd_clearDirtyBitTBE;
2415 transition(CP_IOM, ProbeAcksCompleteReissue, I){TagArrayWrite} {
2416 pdm_sendProbeResponseDataMs;
2425 transition(S_M, PrbInvData, CP_ISM) {
2426 dc_probeInvCoreData;
2428 o_checkForAckCompletion;
2432 transition(CP_ISM, CPUPrbResp) {
2435 o_checkForAckCompletion;
2436 pk_popResponseQueue;
2439 transition(CP_ISM, TCCPrbResp) {
2440 ty_writeTCCDataToTBE;
2442 o_checkForAckCompletion;
2443 plr_popTCCResponseQueue;
2446 transition(CP_ISM, ProbeAcksComplete, I_M) {
2447 pdm_sendProbeResponseDataMs;
2450 cd_clearDirtyBitTBE;
2455 transition(CP_ISM, ProbeAcksCompleteReissue, I){TagArrayWrite} {
2456 pim_sendProbeResponseInvMs;
2465 transition({S_M, O_M}, {PrbInv}, CP_ISM) {
2466 dc_probeInvCoreData;
2470 // next steps inherited from BS_ISM
2474 transition({I_C, I_W}, {PrbInvData, PrbInv, PrbShrData}) {
2475 pi_sendProbeResponseInv;
2479 //If the directory is certain that the block is not present, one can send an acknowledgement right away.
2480 // No need for three step process.
2481 transition(I, {PrbInv,PrbShrData,PrbInvData}){TagArrayRead} {
2482 pi_sendProbeResponseInv;
2486 transition({I_M, I_ES, I_S}, {PrbInv, PrbInvData}) {
2487 pi_sendProbeResponseInv;
2491 transition({I_M, I_ES, I_S}, PrbShrData) {
2492 prm_sendProbeResponseMiss;
2497 transition(S_M, PrbShrData, CP_SM) {
2498 sc_probeShrCoreData;
2500 o_checkForAckCompletion;
2504 transition(CP_SM, CPUPrbResp) {
2507 o_checkForAckCompletion;
2508 pk_popResponseQueue;
2511 transition(CP_SM, TCCPrbResp) {
2512 ty_writeTCCDataToTBE;
2514 o_checkForAckCompletion;
2515 plr_popTCCResponseQueue;
2518 transition(CP_SM, {ProbeAcksComplete,ProbeAcksCompleteReissue}, S_M){DataArrayRead} {
2519 // send response down to NB
2520 pd_sendProbeResponseData;
2525 transition(O_M, PrbShrData, CP_OM) {
2526 sc_probeShrCoreData;
2531 transition(CP_OM, CPUPrbResp) {
2534 o_checkForAckCompletion;
2535 pk_popResponseQueue;
2538 transition(CP_OM, TCCPrbResp) {
2539 ty_writeTCCDataToTBE;
2541 o_checkForAckCompletion;
2542 plr_popTCCResponseQueue;
2545 transition(CP_OM, {ProbeAcksComplete,ProbeAcksCompleteReissue}, O_M) {
2546 // send response down to NB
2547 pd_sendProbeResponseData;
2551 transition(BRW_I, PrbInvData, I_W) {
2552 pd_sendProbeResponseData;
2556 transition({VM_I,VO_I}, PrbInvData, I_C) {
2557 pd_sendProbeResponseData;
2561 transition(VES_I, {PrbInvData,PrbInv}, I_C) {
2562 pi_sendProbeResponseInv;
2566 transition({VM_I, VO_I, BRW_I}, PrbInv, I_W) {
2567 pi_sendProbeResponseInv;
2571 transition({VM_I, VO_I, VO_S, VES_I, BRW_I}, PrbShrData) {
2572 pd_sendProbeResponseData;
2577 transition(VO_S, PrbInvData, CP_OSIW) {
2578 dc_probeInvCoreData;
2583 transition(CP_OSIW, TCCPrbResp) {
2585 o_checkForAckCompletion;
2586 plr_popTCCResponseQueue;
2588 transition(CP_OSIW, CPUPrbResp) {
2590 o_checkForAckCompletion;
2591 pk_popResponseQueue;
2594 transition(CP_OSIW, ProbeAcksComplete, I_C) {
2595 pd_sendProbeResponseData;
2596 cd_clearDirtyBitTBE;
2600 transition({I, S, E, O, M, CP_O, CP_S, CP_OM, CP_SM, CP_OSIW, BW_S, BW_E, BW_O, BW_M, I_M, I_ES, I_S, BBS_S, BBO_O, BBM_M, BBM_O, BB_M, BB_O, BB_OO, BB_S, BBS_M, BBO_M, BBO_UM, BBS_UM, S_M, O_M, BBB_S, BBB_M, BBB_E, VES_I, VM_I, VO_I, VO_S, ES_I, MO_I, I_C, I_W}, StaleVic) {
2601 nT_sendNullWBAckToTCC;
2602 pl_popTCCRequestQueue;
2605 transition({CP_I, B_I, CP_IOM, CP_ISM, BRWD_I, BRW_I, BRD_I}, StaleVic) {
2606 nT_sendNullWBAckToTCC;
2607 pl_popTCCRequestQueue;
2610 // Recall Transistions
2611 // transient states still require the directory state
2612 transition({M, O}, Recall, BRWD_I) {
2615 dc_probeInvCoreData;
2619 transition({E, S}, Recall, BRWD_I) {
2622 dc_probeInvCoreData;
2626 transition(I, Recall) {
2630 transition({BRWD_I, BRD_I}, CPUPrbResp) {
2633 o_checkForAckCompletion;
2634 pk_popResponseQueue;
2637 transition({BRWD_I, BRD_I}, TCCPrbResp) {
2638 ty_writeTCCDataToTBE;
2640 o_checkForAckCompletion;
2641 plr_popTCCResponseQueue;
2644 transition(BRWD_I, NB_AckWB, BRD_I) {
2645 pR_popResponseFromNBQueue;
2648 transition(BRWD_I, ProbeAcksComplete, BRW_I) {
2652 transition(BRW_I, NB_AckWB, I) {
2656 pR_popResponseFromNBQueue;
2659 transition(BRD_I, ProbeAcksComplete, I) {
2666 // wait for stable state for Recall
2667 transition({BRWD_I,BRD_I,BRW_I,CP_O, CP_S, CP_OM, CP_SM, CP_OSIW, BW_S, BW_E, BW_O, BW_M, I_M, I_ES, I_S, BBS_S, BBO_O, BBM_M, BBM_O, BB_M, BB_O, BB_OO, BB_S, BBS_M, BBO_M, BBO_UM, BBS_UM, S_M, O_M, BBB_S, BBB_M, BBB_E, VES_I, VM_I, VO_I, VO_S, ES_I, MO_I, I_C, I_W, CP_I}, Recall) {
2668 zz_recycleRequest; // stall and wait would be for the wrong address
2669 ut_updateTag; // try to find an easier recall