2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 machine(MachineType:L2Cache, "Token protocol")
30 : CacheMemory * L2cache;
31 Cycles response_latency := 2;
32 Cycles request_latency := 2;
35 // From local bank of L2 cache TO the network
36 MessageBuffer * L1RequestFromL2Cache, network="To", virtual_network="0",
37 vnet_type="request"; // this L2 bank -> a local L1
38 MessageBuffer * GlobalRequestFromL2Cache, network="To", virtual_network="1",
39 vnet_type="request"; // this L2 bank -> mod-directory
40 MessageBuffer * responseFromL2Cache, network="To", virtual_network="2",
41 vnet_type="response"; // this L2 bank -> a local L1 || mod-directory
43 // FROM the network to this local bank of L2 cache
44 MessageBuffer * L1RequestToL2Cache, network="From", virtual_network="0",
45 vnet_type="request"; // a local L1 -> this L2 bank, Lets try this???
46 MessageBuffer * GlobalRequestToL2Cache, network="From", virtual_network="1",
47 vnet_type="request"; // mod-directory -> this L2 bank
48 MessageBuffer * responseToL2Cache, network="From", virtual_network="2",
49 vnet_type="response"; // a local L1 || mod-directory -> this L2 bank
51 MessageBuffer * triggerQueue;
54 state_declaration(State, desc="L2 Cache states", default="L2Cache_State_I") {
57 NP, AccessPermission:Invalid, desc="Not Present";
58 I, AccessPermission:Invalid, desc="Invalid";
59 ILS, AccessPermission:Invalid, desc="Idle/NP, but local sharers exist";
60 ILX, AccessPermission:Invalid, desc="Idle/NP, but local exclusive exists";
61 ILO, AccessPermission:Invalid, desc="Idle/NP, but local owner exists";
62 ILOX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and chip is exclusive";
63 ILOS, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and local sharers as well";
64 ILOSX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
65 S, AccessPermission:Read_Only, desc="Shared, no local sharers";
66 O, AccessPermission:Read_Only, desc="Owned, no local sharers";
67 OLS, AccessPermission:Read_Only, desc="Owned with local sharers";
68 OLSX, AccessPermission:Read_Only, desc="Owned with local sharers, chip is exclusive";
69 SLS, AccessPermission:Read_Only, desc="Shared with local sharers";
70 M, AccessPermission:Read_Write, desc="Modified";
74 IFGX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner/exclusive. No other on-chip invs needed";
75 IFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner";
76 ISFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner, local sharers exist";
78 IFGXX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner but may need acks from other sharers";
79 OFGX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to owner and got data but may need acks";
81 OLSF, AccessPermission:Busy, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
84 ILOW, AccessPermission:Busy, desc="local WB request, was ILO";
85 ILOXW, AccessPermission:Busy, desc="local WB request, was ILOX";
86 ILOSW, AccessPermission:Busy, desc="local WB request, was ILOS";
87 ILOSXW, AccessPermission:Busy, desc="local WB request, was ILOSX";
88 SLSW, AccessPermission:Busy, desc="local WB request, was SLS";
89 OLSW, AccessPermission:Busy, desc="local WB request, was OLS";
90 ILSW, AccessPermission:Busy, desc="local WB request, was ILS";
91 IW, AccessPermission:Busy, desc="local WB request from only sharer, was ILS";
92 OW, AccessPermission:Busy, desc="local WB request from only sharer, was OLS";
93 SW, AccessPermission:Busy, desc="local WB request from only sharer, was SLS";
94 OXW, AccessPermission:Busy, desc="local WB request from only sharer, was OLSX";
95 OLSXW, AccessPermission:Busy, desc="local WB request from sharer, was OLSX";
96 ILXW, AccessPermission:Busy, desc="local WB request, was ILX";
98 IFLS, AccessPermission:Busy, desc="Blocked, forwarded local GETS to _some_ local sharer";
99 IFLO, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner";
100 IFLOX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner but chip is exclusive";
101 IFLOXX, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner/exclusive, chip is exclusive";
102 IFLOSX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner w/ other sharers, chip is exclusive";
103 IFLXO, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner with other sharers, chip is exclusive";
105 IGS, AccessPermission:Busy, desc="Semi-blocked, issued local GETS to directory";
106 IGM, AccessPermission:Busy, desc="Blocked, issued local GETX to directory. Need global acks and data";
107 IGMLS, AccessPermission:Busy, desc="Blocked, issued local GETX to directory but may need to INV local sharers";
108 IGMO, AccessPermission:Busy, desc="Blocked, have data for local GETX but need all acks";
109 IGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner with possible local sharer, may need to INV";
110 OGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, may need to INV";
111 IGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
112 IGMIOFS, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETS";
113 OGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, waiting for global acks, got Fwd_GETX";
115 II, AccessPermission:Busy, desc="Blocked, handling invalidations";
116 MM, AccessPermission:Busy, desc="Blocked, was M satisfying local GETX";
117 SS, AccessPermission:Busy, desc="Blocked, was S satisfying local GETS";
118 OO, AccessPermission:Busy, desc="Blocked, was O satisfying local GETS";
119 OLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
120 OLSXS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
121 SLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
123 OI, AccessPermission:Busy, desc="Blocked, doing writeback, was O";
124 MI, AccessPermission:Busy, desc="Blocked, doing writeback, was M";
125 MII, AccessPermission:Busy, desc="Blocked, doing writeback, was M, got Fwd_GETX";
126 OLSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS";
127 ILSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
129 // DMA blocking states
130 ILOSD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
131 ILOSXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
132 ILOD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
133 ILXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
134 ILOXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
138 enumeration(Event, desc="Cache events") {
141 L1_GETS, desc="local L1 GETS request";
142 L1_GETX, desc="local L1 GETX request";
143 L1_PUTO, desc="local owner wants to writeback";
144 L1_PUTX, desc="local exclusive wants to writeback";
145 L1_PUTS_only, desc="only local sharer wants to writeback";
146 L1_PUTS, desc="local sharer wants to writeback";
147 Fwd_GETX, desc="A GetX from another processor";
148 Fwd_GETS, desc="A GetS from another processor";
149 Fwd_DMA, desc="A request from DMA";
150 Own_GETX, desc="A GetX from this node";
151 Inv, desc="Invalidations from the directory";
154 IntAck, desc="Received an ack message";
155 ExtAck, desc="Received an ack message";
156 All_Acks, desc="Received all ack messages";
157 Data, desc="Received a data message, responder has a shared copy";
158 Data_Exclusive, desc="Received a data message";
159 L1_WBCLEANDATA, desc="Writeback from L1, with data";
160 L1_WBDIRTYDATA, desc="Writeback from L1, with data";
162 Writeback_Ack, desc="Writeback O.K. from directory";
163 Writeback_Nack, desc="Writeback not O.K. from directory";
165 Unblock, desc="Local L1 is telling L2 dir to unblock";
166 Exclusive_Unblock, desc="Local L1 is telling L2 dir to unblock";
168 DmaAck, desc="DMA ack from local L1";
169 // events initiated by this L2
170 L2_Replacement, desc="L2 Replacement", format="!r";
177 structure(Entry, desc="...", interface="AbstractCacheEntry") {
178 State CacheState, desc="cache state";
179 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
180 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
181 bool OwnerValid, default="false", desc="true if Owner means something";
182 bool Dirty, desc="Is the data dirty (different than memory)?";
183 DataBlock DataBlk, desc="data for the block";
187 structure(DirEntry, desc="...", interface="AbstractEntry") {
188 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
189 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
190 bool OwnerValid, default="false", desc="true if Owner means something";
191 State DirState, desc="directory state";
195 structure(TBE, desc="...") {
196 Addr addr, desc="Physical address for this TBE";
197 State TBEState, desc="Transient state";
198 Addr PC, desc="Program counter of request";
199 DataBlock DataBlk, desc="Buffer for the data block";
200 bool Dirty, desc="Is the data dirty (different than memory)?";
202 int NumExtPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
203 int NumIntPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
204 int Fwd_GETX_ExtAcks, default="0", desc="Number of acks that requestor will need";
205 int Local_GETX_IntAcks, default="0", desc="Number of acks that requestor will need";
207 NetDest L1_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
208 MachineID L1_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
209 NetDest Fwd_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
210 MachineID Fwd_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
213 structure(TBETable, external = "yes") {
216 void deallocate(Addr);
217 bool isPresent(Addr);
220 structure(PerfectCacheMemory, external = "yes") {
222 void deallocate(Addr);
223 DirEntry lookup(Addr);
224 bool isTagPresent(Addr);
227 TBETable TBEs, template="<L2Cache_TBE>", constructor="m_number_of_TBEs";
228 PerfectCacheMemory localDirectory, template="<L2Cache_DirEntry>";
231 Tick cyclesToTicks(Cycles c);
232 void set_cache_entry(AbstractCacheEntry b);
233 void unset_cache_entry();
236 MachineID mapAddressToMachine(Addr addr, MachineType mtype);
238 Entry getCacheEntry(Addr address), return_by_pointer="yes" {
239 return static_cast(Entry, "pointer", L2cache[address]);
242 bool isDirTagPresent(Addr addr) {
243 return (localDirectory.isTagPresent(addr) );
246 DirEntry getDirEntry(Addr address), return_by_pointer="yes" {
247 return localDirectory.lookup(address);
250 bool isOnlySharer(Entry cache_entry, Addr addr, MachineID shar_id) {
251 if (is_valid(cache_entry)) {
252 assert (localDirectory.isTagPresent(addr) == false);
253 if (cache_entry.Sharers.count() > 1) {
256 else if (cache_entry.Sharers.count() == 1) {
257 if (cache_entry.Sharers.isElement(shar_id)) {
261 return false; // something happened which should cause this PUTS to be nacked
269 else if (localDirectory.isTagPresent(addr)){
270 DirEntry dir_entry := getDirEntry(addr);
271 if (dir_entry.Sharers.count() > 1) {
274 else if (dir_entry.Sharers.count() == 1) {
275 if (dir_entry.Sharers.isElement(shar_id)) {
279 return false; // something happened which should cause this PUTS to be nacked
287 // shouldn't happen unless L1 issues PUTS before unblock received
292 void copyCacheStateToDir(Entry cache_entry, Addr addr) {
293 assert(localDirectory.isTagPresent(addr) == false);
294 assert(is_valid(cache_entry));
295 localDirectory.allocate(addr);
296 DirEntry dir_entry := getDirEntry(addr);
297 dir_entry.DirState := cache_entry.CacheState;
298 dir_entry.Sharers := cache_entry.Sharers;
299 dir_entry.Owner := cache_entry.Owner;
300 dir_entry.OwnerValid := cache_entry.OwnerValid;
304 void copyDirToCache(Entry cache_entry, Addr addr) {
305 assert(is_valid(cache_entry));
306 DirEntry dir_entry := getDirEntry(addr);
307 cache_entry.Sharers := dir_entry.Sharers;
308 cache_entry.Owner := dir_entry.Owner;
309 cache_entry.OwnerValid := dir_entry.OwnerValid;
313 void recordLocalSharerInDir(Entry cache_entry, Addr addr, MachineID shar_id) {
314 if (is_valid(cache_entry)) {
315 assert (localDirectory.isTagPresent(addr) == false);
316 cache_entry.Sharers.add(shar_id);
319 if (localDirectory.isTagPresent(addr) == false) {
320 localDirectory.allocate(addr);
321 DirEntry dir_entry := getDirEntry(addr);
322 dir_entry.Sharers.clear();
323 dir_entry.OwnerValid := false;
325 DirEntry dir_entry := getDirEntry(addr);
326 dir_entry.Sharers.add(shar_id);
330 void recordNewLocalExclusiveInDir(Entry cache_entry, Addr addr, MachineID exc_id) {
332 if (is_valid(cache_entry)) {
333 assert (localDirectory.isTagPresent(addr) == false);
334 cache_entry.Sharers.clear();
335 cache_entry.OwnerValid := true;
336 cache_entry.Owner := exc_id;
339 if (localDirectory.isTagPresent(addr) == false) {
340 localDirectory.allocate(addr);
342 DirEntry dir_entry := getDirEntry(addr);
343 dir_entry.Sharers.clear();
344 dir_entry.OwnerValid := true;
345 dir_entry.Owner := exc_id;
349 void removeAllLocalSharersFromDir(Entry cache_entry, Addr addr) {
350 if (is_valid(cache_entry)) {
351 assert (localDirectory.isTagPresent(addr) == false);
352 cache_entry.Sharers.clear();
353 cache_entry.OwnerValid := false;
356 DirEntry dir_entry := getDirEntry(addr);
357 dir_entry.Sharers.clear();
358 dir_entry.OwnerValid := false;
362 void removeSharerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
363 if (is_valid(cache_entry)) {
364 assert (localDirectory.isTagPresent(addr) == false);
365 cache_entry.Sharers.remove(sender);
368 DirEntry dir_entry := getDirEntry(addr);
369 dir_entry.Sharers.remove(sender);
373 void removeOwnerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
374 if (is_valid(cache_entry)) {
375 assert (localDirectory.isTagPresent(addr) == false);
376 cache_entry.OwnerValid := false;
379 DirEntry dir_entry := getDirEntry(addr);
380 dir_entry.OwnerValid := false;
384 bool isLocalSharer(Entry cache_entry, Addr addr, MachineID shar_id) {
385 if (is_valid(cache_entry)) {
386 assert (localDirectory.isTagPresent(addr) == false);
387 return cache_entry.Sharers.isElement(shar_id);
390 DirEntry dir_entry := getDirEntry(addr);
391 return dir_entry.Sharers.isElement(shar_id);
395 NetDest getLocalSharers(Entry cache_entry, Addr addr) {
396 if (is_valid(cache_entry)) {
397 assert (localDirectory.isTagPresent(addr) == false);
398 return cache_entry.Sharers;
401 DirEntry dir_entry := getDirEntry(addr);
402 return dir_entry.Sharers;
406 MachineID getLocalOwner(Entry cache_entry, Addr addr) {
407 if (is_valid(cache_entry)) {
408 assert (localDirectory.isTagPresent(addr) == false);
409 return cache_entry.Owner;
412 DirEntry dir_entry := getDirEntry(addr);
413 return dir_entry.Owner;
417 int countLocalSharers(Entry cache_entry, Addr addr) {
418 if (is_valid(cache_entry)) {
419 assert (localDirectory.isTagPresent(addr) == false);
420 return cache_entry.Sharers.count();
423 DirEntry dir_entry := getDirEntry(addr);
424 return dir_entry.Sharers.count();
428 bool isLocalOwnerValid(Entry cache_entry, Addr addr) {
429 if (is_valid(cache_entry)) {
430 assert (localDirectory.isTagPresent(addr) == false);
431 return cache_entry.OwnerValid;
434 DirEntry dir_entry := getDirEntry(addr);
435 return dir_entry.OwnerValid;
439 int countLocalSharersExceptRequestor(Entry cache_entry, Addr addr, MachineID requestor) {
440 if (is_valid(cache_entry)) {
441 assert (localDirectory.isTagPresent(addr) == false);
442 if (cache_entry.Sharers.isElement(requestor)) {
443 return ( cache_entry.Sharers.count() - 1 );
446 return cache_entry.Sharers.count();
450 DirEntry dir_entry := getDirEntry(addr);
451 if (dir_entry.Sharers.isElement(requestor)) {
452 return ( dir_entry.Sharers.count() - 1 );
455 return dir_entry.Sharers.count();
460 State getState(TBE tbe, Entry cache_entry, Addr addr) {
464 } else if (is_valid(cache_entry)) {
465 return cache_entry.CacheState;
466 } else if (isDirTagPresent(addr)) {
467 DirEntry dir_entry := getDirEntry(addr);
468 return dir_entry.DirState;
474 std::string getCoherenceRequestTypeStr(CoherenceRequestType type) {
475 return CoherenceRequestType_to_string(type);
478 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
479 assert((localDirectory.isTagPresent(addr) && L2cache.isTagPresent(addr)) == false);
482 tbe.TBEState := state;
486 (state == State:M) ||
487 (state == State:O) ||
488 (state == State:S) ||
489 (state == State:OLS) ||
490 (state == State:SLS) ||
491 (state == State:OLSX) ||
494 assert(is_valid(cache_entry));
497 (state == State:ILS) ||
498 (state == State:ILX) ||
499 (state == State:ILO) ||
500 (state == State:ILOX) ||
501 (state == State:ILOS) ||
502 (state == State:ILOSX)
504 // assert(isCacheTagPresent(addr) == false);
507 if (is_valid(cache_entry)) {
508 if ( ((cache_entry.CacheState != State:M) && (state == State:M)) ||
509 ((cache_entry.CacheState != State:S) && (state == State:S)) ||
510 ((cache_entry.CacheState != State:O) && (state == State:O)) ) {
511 cache_entry.CacheState := state;
512 // disable Coherence Checker for now
513 // sequencer.checkCoherence(addr);
516 cache_entry.CacheState := state;
519 else if (localDirectory.isTagPresent(addr)) {
520 DirEntry dir_entry := getDirEntry(addr);
521 dir_entry.DirState := state;
525 AccessPermission getAccessPermission(Addr addr) {
526 TBE tbe := TBEs[addr];
528 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
529 return L2Cache_State_to_permission(tbe.TBEState);
532 Entry cache_entry := getCacheEntry(addr);
533 if(is_valid(cache_entry)) {
534 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
535 return L2Cache_State_to_permission(cache_entry.CacheState);
538 DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
539 return AccessPermission:NotPresent;
542 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
543 if (is_valid(cache_entry)) {
544 cache_entry.changePermission(L2Cache_State_to_permission(state));
548 void functionalRead(Addr addr, Packet *pkt) {
549 TBE tbe := TBEs[addr];
551 testAndRead(addr, tbe.DataBlk, pkt);
553 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
557 int functionalWrite(Addr addr, Packet *pkt) {
558 int num_functional_writes := 0;
560 TBE tbe := TBEs[addr];
562 num_functional_writes := num_functional_writes +
563 testAndWrite(addr, tbe.DataBlk, pkt);
564 return num_functional_writes;
567 num_functional_writes := num_functional_writes +
568 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
569 return num_functional_writes;
572 out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache);
573 out_port(localRequestNetwork_out, RequestMsg, L1RequestFromL2Cache);
574 out_port(responseNetwork_out, ResponseMsg, responseFromL2Cache);
576 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
582 in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
583 if (triggerQueue_in.isReady(clockEdge())) {
584 peek(triggerQueue_in, TriggerMsg) {
585 if (in_msg.Type == TriggerType:ALL_ACKS) {
586 trigger(Event:All_Acks, in_msg.addr,
587 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
589 error("Unexpected message");
596 in_port(responseNetwork_in, ResponseMsg, responseToL2Cache) {
597 if (responseNetwork_in.isReady(clockEdge())) {
598 peek(responseNetwork_in, ResponseMsg) {
599 assert(in_msg.Destination.isElement(machineID));
600 if (in_msg.Type == CoherenceResponseType:ACK) {
601 if (in_msg.SenderMachine == MachineType:L2Cache) {
602 trigger(Event:ExtAck, in_msg.addr,
603 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
606 trigger(Event:IntAck, in_msg.addr,
607 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
609 } else if (in_msg.Type == CoherenceResponseType:DATA) {
610 trigger(Event:Data, in_msg.addr,
611 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
612 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
613 trigger(Event:Data_Exclusive, in_msg.addr,
614 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
615 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
616 DPRINTF(ProtocolTrace, "Received Unblock from L1 addr: %x\n", in_msg.addr);
617 trigger(Event:Unblock, in_msg.addr,
618 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
619 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
620 trigger(Event:Exclusive_Unblock, in_msg.addr,
621 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
622 } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) {
623 Entry cache_entry := getCacheEntry(in_msg.addr);
624 if (is_invalid(cache_entry) &&
625 L2cache.cacheAvail(in_msg.addr) == false) {
626 trigger(Event:L2_Replacement, L2cache.cacheProbe(in_msg.addr),
627 getCacheEntry(L2cache.cacheProbe(in_msg.addr)),
628 TBEs[L2cache.cacheProbe(in_msg.addr)]);
631 trigger(Event:L1_WBDIRTYDATA, in_msg.addr,
632 cache_entry, TBEs[in_msg.addr]);
634 } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_DATA) {
635 Entry cache_entry := getCacheEntry(in_msg.addr);
636 if (is_invalid(cache_entry) &&
637 L2cache.cacheAvail(in_msg.addr) == false) {
638 trigger(Event:L2_Replacement, L2cache.cacheProbe(in_msg.addr),
639 getCacheEntry(L2cache.cacheProbe(in_msg.addr)),
640 TBEs[L2cache.cacheProbe(in_msg.addr)]);
643 trigger(Event:L1_WBCLEANDATA, in_msg.addr,
644 cache_entry, TBEs[in_msg.addr]);
646 } else if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
647 trigger(Event:DmaAck, in_msg.addr,
648 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
650 error("Unexpected message");
658 in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache) {
659 if (requestNetwork_in.isReady(clockEdge())) {
660 peek(requestNetwork_in, RequestMsg) {
661 if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
662 if (in_msg.Requestor == machineID) {
663 trigger(Event:Own_GETX, in_msg.addr,
664 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
666 trigger(Event:Fwd_GETX, in_msg.addr,
667 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
669 } else if (in_msg.Type == CoherenceRequestType:GETS) {
670 trigger(Event:Fwd_GETS, in_msg.addr,
671 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
672 } else if(in_msg.Type == CoherenceRequestType:DMA_READ) {
673 trigger(Event:Fwd_DMA, in_msg.addr,
674 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
675 } else if (in_msg.Type == CoherenceRequestType:INV) {
676 trigger(Event:Inv, in_msg.addr,
677 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
678 } else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
679 trigger(Event:Writeback_Ack, in_msg.addr,
680 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
681 } else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
682 trigger(Event:Writeback_Nack, in_msg.addr,
683 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
685 error("Unexpected message");
691 in_port(L1requestNetwork_in, RequestMsg, L1RequestToL2Cache) {
692 if (L1requestNetwork_in.isReady(clockEdge())) {
693 peek(L1requestNetwork_in, RequestMsg) {
694 assert(in_msg.Destination.isElement(machineID));
695 if (in_msg.Type == CoherenceRequestType:GETX) {
696 trigger(Event:L1_GETX, in_msg.addr,
697 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
698 } else if (in_msg.Type == CoherenceRequestType:GETS) {
699 trigger(Event:L1_GETS, in_msg.addr,
700 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
701 } else if (in_msg.Type == CoherenceRequestType:PUTO) {
702 trigger(Event:L1_PUTO, in_msg.addr,
703 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
704 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
705 trigger(Event:L1_PUTX, in_msg.addr,
706 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
707 } else if (in_msg.Type == CoherenceRequestType:PUTS) {
708 Entry cache_entry := getCacheEntry(in_msg.addr);
709 if (isOnlySharer(cache_entry, in_msg.addr, in_msg.Requestor)) {
710 trigger(Event:L1_PUTS_only, in_msg.addr,
711 cache_entry, TBEs[in_msg.addr]);
714 trigger(Event:L1_PUTS, in_msg.addr,
715 cache_entry, TBEs[in_msg.addr]);
718 error("Unexpected message");
727 action(a_issueGETS, "a", desc="issue local request globally") {
728 peek(L1requestNetwork_in, RequestMsg) {
729 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
730 out_msg.addr := address;
731 out_msg.Type := CoherenceRequestType:GETS;
732 out_msg.RequestorMachine := MachineType:L2Cache;
733 out_msg.Requestor := machineID;
734 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
735 out_msg.MessageSize := MessageSizeType:Request_Control;
740 action(a_issueGETX, "\a", desc="issue local request globally") {
741 peek(L1requestNetwork_in, RequestMsg) {
742 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
743 out_msg.addr := address;
744 out_msg.Type := CoherenceRequestType:GETX;
745 out_msg.RequestorMachine := MachineType:L2Cache;
746 out_msg.Requestor := machineID;
747 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
748 out_msg.MessageSize := MessageSizeType:Request_Control;
753 action(b_issuePUTX, "b", desc="Issue PUTX") {
754 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
755 out_msg.addr := address;
756 out_msg.Type := CoherenceRequestType:PUTX;
757 out_msg.RequestorMachine := MachineType:L2Cache;
758 out_msg.Requestor := machineID;
759 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
760 out_msg.MessageSize := MessageSizeType:Writeback_Control;
764 action(b_issuePUTO, "\b", desc="Issue PUTO") {
765 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
766 out_msg.addr := address;
767 out_msg.Type := CoherenceRequestType:PUTO;
768 out_msg.Requestor := machineID;
769 out_msg.RequestorMachine := MachineType:L2Cache;
770 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
771 out_msg.MessageSize := MessageSizeType:Writeback_Control;
775 /* PUTO, but local sharers exist */
776 action(b_issuePUTO_ls, "\bb", desc="Issue PUTO") {
777 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
778 out_msg.addr := address;
779 out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
780 out_msg.Requestor := machineID;
781 out_msg.RequestorMachine := MachineType:L2Cache;
782 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
783 out_msg.MessageSize := MessageSizeType:Writeback_Control;
787 action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") {
788 assert(is_valid(tbe));
789 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
790 out_msg.addr := address;
791 out_msg.Type := CoherenceResponseType:DATA;
792 out_msg.Sender := machineID;
793 out_msg.SenderMachine := MachineType:L2Cache;
794 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
795 out_msg.DataBlk := tbe.DataBlk;
796 // out_msg.Dirty := tbe.Dirty;
797 // shared data should be clean
798 out_msg.Dirty := false;
799 out_msg.MessageSize := MessageSizeType:Response_Data;
801 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
802 address, tbe.DataBlk);
805 action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") {
806 assert(is_valid(tbe));
807 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
808 out_msg.addr := address;
809 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
810 out_msg.Sender := machineID;
811 out_msg.SenderMachine := MachineType:L2Cache;
812 out_msg.Destination.add(tbe.L1_GetX_ID);
813 out_msg.DataBlk := tbe.DataBlk;
814 out_msg.Dirty := tbe.Dirty;
815 out_msg.Acks := tbe.Local_GETX_IntAcks;
816 out_msg.MessageSize := MessageSizeType:Response_Data;
818 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
819 address, tbe.DataBlk);
822 action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") {
823 assert(is_valid(tbe));
824 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
825 out_msg.addr := address;
826 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
827 out_msg.Sender := machineID;
828 out_msg.SenderMachine := MachineType:L2Cache;
829 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
830 out_msg.DataBlk := tbe.DataBlk;
831 out_msg.Dirty := tbe.Dirty;
832 out_msg.MessageSize := MessageSizeType:Response_Data;
836 action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") {
837 assert(is_valid(tbe));
838 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
839 out_msg.addr := address;
840 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
841 out_msg.Sender := machineID;
842 out_msg.SenderMachine := MachineType:L2Cache;
843 out_msg.Destination.add(tbe.Fwd_GetX_ID);
844 out_msg.DataBlk := tbe.DataBlk;
845 out_msg.Dirty := tbe.Dirty;
846 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
847 out_msg.MessageSize := MessageSizeType:Response_Data;
851 action(cd_sendDataFromTBEToFwdDma, "cd", desc="Send data from TBE to external GETX") {
852 assert(is_valid(tbe));
853 peek(requestNetwork_in, RequestMsg) {
854 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
855 out_msg.addr := address;
856 out_msg.Type := CoherenceResponseType:DATA;
857 out_msg.Sender := machineID;
858 out_msg.SenderMachine := MachineType:L2Cache;
859 out_msg.Destination.add(in_msg.Requestor);
860 out_msg.DataBlk := tbe.DataBlk;
861 // out_msg.Dirty := tbe.Dirty;
862 // shared data should be clean
863 out_msg.Dirty := false;
864 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
865 out_msg.MessageSize := MessageSizeType:Response_Data;
868 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
869 address, tbe.DataBlk);
872 action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") {
873 assert(is_valid(tbe));
874 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
875 out_msg.addr := address;
876 out_msg.Type := CoherenceResponseType:DATA;
877 out_msg.Sender := machineID;
878 out_msg.SenderMachine := MachineType:L2Cache;
879 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
880 out_msg.DataBlk := tbe.DataBlk;
881 // out_msg.Dirty := tbe.Dirty;
882 // shared data should be clean
883 out_msg.Dirty := false;
884 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
885 out_msg.MessageSize := MessageSizeType:Response_Data;
887 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
888 address, tbe.DataBlk);
891 action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") {
892 assert(is_valid(tbe));
893 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
894 out_msg.addr := address;
895 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
896 out_msg.Sender := machineID;
897 out_msg.SenderMachine := MachineType:L2Cache;
898 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
899 out_msg.DataBlk := tbe.DataBlk;
900 out_msg.Dirty := tbe.Dirty;
901 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
902 out_msg.MessageSize := MessageSizeType:Response_Data;
904 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
905 address, tbe.DataBlk);
908 action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") {
909 assert(is_valid(cache_entry));
910 peek(L1requestNetwork_in, RequestMsg) {
911 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
912 out_msg.addr := address;
913 out_msg.Type := CoherenceResponseType:DATA;
914 out_msg.Sender := machineID;
915 out_msg.SenderMachine := MachineType:L2Cache;
916 out_msg.Destination.add(in_msg.Requestor);
917 out_msg.DataBlk := cache_entry.DataBlk;
918 // out_msg.Dirty := cache_entry.Dirty;
919 // shared data should be clean
920 out_msg.Dirty := false;
921 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
924 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
925 address, cache_entry.DataBlk);
928 action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") {
929 assert(is_valid(cache_entry));
930 peek(L1requestNetwork_in, RequestMsg) {
931 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
932 assert(is_valid(tbe));
933 out_msg.addr := address;
934 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
935 out_msg.Sender := machineID;
936 out_msg.SenderMachine := MachineType:L2Cache;
937 out_msg.Destination.add(in_msg.Requestor);
938 out_msg.DataBlk := cache_entry.DataBlk;
939 out_msg.Dirty := cache_entry.Dirty;
940 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
941 out_msg.Acks := tbe.Local_GETX_IntAcks;
944 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
945 address, cache_entry.DataBlk);
948 action(dd_sendDataToFwdGETX, "dd", desc="send data") {
949 assert(is_valid(cache_entry));
950 peek(requestNetwork_in, RequestMsg) {
951 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
952 out_msg.addr := address;
953 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
954 out_msg.Sender := machineID;
955 out_msg.SenderMachine := MachineType:L2Cache;
956 out_msg.Destination.add(in_msg.Requestor);
957 out_msg.DataBlk := cache_entry.DataBlk;
958 out_msg.Dirty := cache_entry.Dirty;
959 out_msg.MessageSize := MessageSizeType:Response_Data;
960 out_msg.Acks := in_msg.Acks;
963 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
964 address, cache_entry.DataBlk);
968 action(dd_sendDataToFwdGETS, "\dd", desc="send data") {
969 assert(is_valid(cache_entry));
970 peek(requestNetwork_in, RequestMsg) {
971 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
972 out_msg.addr := address;
973 out_msg.Type := CoherenceResponseType:DATA;
974 out_msg.Sender := machineID;
975 out_msg.SenderMachine := MachineType:L2Cache;
976 out_msg.Destination.add(in_msg.Requestor);
977 out_msg.DataBlk := cache_entry.DataBlk;
978 // out_msg.Dirty := cache_entry.Dirty;
979 // shared data should be clean
980 out_msg.Dirty := false;
981 out_msg.MessageSize := MessageSizeType:Response_Data;
984 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
985 address, cache_entry.DataBlk);
988 action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") {
989 assert(is_valid(cache_entry));
990 peek(requestNetwork_in, RequestMsg) {
991 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
992 out_msg.addr := address;
993 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
994 out_msg.Sender := machineID;
995 out_msg.SenderMachine := MachineType:L2Cache;
996 out_msg.Destination.add(in_msg.Requestor);
997 out_msg.DataBlk := cache_entry.DataBlk;
998 out_msg.Dirty := cache_entry.Dirty;
999 out_msg.MessageSize := MessageSizeType:Response_Data;
1004 action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") {
1005 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1006 assert(is_valid(tbe));
1007 out_msg.addr := address;
1008 out_msg.Type := CoherenceResponseType:ACK;
1009 out_msg.Sender := machineID;
1010 out_msg.SenderMachine := MachineType:L2Cache;
1012 out_msg.Destination.add( tbe.Fwd_GetX_ID);
1013 out_msg.Acks := 0 - 1;
1014 out_msg.MessageSize := MessageSizeType:Response_Control;
1018 action(e_sendAckToL1Requestor, "\e", desc="Send ack with the tokens we've collected thus far.") {
1019 peek(L1requestNetwork_in, RequestMsg) {
1020 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1021 out_msg.addr := address;
1022 out_msg.Type := CoherenceResponseType:ACK;
1023 out_msg.Sender := machineID;
1024 out_msg.SenderMachine := MachineType:L2Cache;
1025 out_msg.Destination.add(in_msg.Requestor);
1026 out_msg.Acks := 0 - 1;
1027 out_msg.MessageSize := MessageSizeType:Response_Control;
1032 action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") {
1033 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1034 assert(is_valid(tbe));
1035 out_msg.addr := address;
1036 out_msg.Type := CoherenceResponseType:ACK;
1037 out_msg.Sender := machineID;
1038 out_msg.SenderMachine := MachineType:L2Cache;
1039 out_msg.Destination.add(tbe.L1_GetX_ID);
1040 out_msg.Acks := 0 - 1;
1041 out_msg.MessageSize := MessageSizeType:Response_Control;
1045 action(ee_sendLocalInv, "\ee", desc="Send local invalidates") {
1046 assert(is_valid(tbe));
1047 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1048 DPRINTF(RubySlicc, "Address: %#x, Local Sharers: %s, Pending Acks: %d\n",
1049 address, getLocalSharers(cache_entry, address),
1050 tbe.NumIntPendingAcks);
1051 if (isLocalOwnerValid(cache_entry, address)) {
1052 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1053 DPRINTF(RubySlicc, "%s\n", getLocalOwner(cache_entry, address));
1056 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1057 out_msg.addr := address;
1058 out_msg.Type := CoherenceRequestType:INV;
1059 out_msg.Requestor := machineID;
1060 out_msg.RequestorMachine := MachineType:L2Cache;
1061 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1062 if (isLocalOwnerValid(cache_entry, address))
1064 out_msg.Destination.add(getLocalOwner(cache_entry, address));
1066 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1070 action(ee_sendLocalInvSharersOnly, "\eee", desc="Send local invalidates to sharers if they exist") {
1072 // assert(countLocalSharers(address) > 0);
1073 assert(is_valid(tbe));
1074 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1076 if (countLocalSharers(cache_entry, address) > 0) {
1077 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1078 out_msg.addr := address;
1079 out_msg.Type := CoherenceRequestType:INV;
1080 out_msg.Requestor := machineID;
1081 out_msg.RequestorMachine := MachineType:L2Cache;
1082 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1083 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1088 action(ee_addLocalIntAck, "e\ee", desc="add a local ack to wait for") {
1089 assert(is_valid(tbe));
1090 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1093 action(ee_issueLocalInvExceptL1Requestor, "\eeee", desc="Send local invalidates to sharers if they exist") {
1094 peek(L1requestNetwork_in, RequestMsg) {
1096 // assert(countLocalSharers(address) > 0);
1097 if (countLocalSharers(cache_entry, address) == 0) {
1098 tbe.NumIntPendingAcks := 0;
1102 if (isLocalSharer(cache_entry, address, in_msg.Requestor)) {
1103 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1106 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1109 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1110 out_msg.addr := address;
1111 out_msg.Type := CoherenceRequestType:INV;
1112 out_msg.Requestor := in_msg.Requestor;
1113 out_msg.RequestorMachine := MachineType:L1Cache;
1114 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1115 out_msg.Destination.remove(in_msg.Requestor);
1116 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1122 action(ee_issueLocalInvExceptL1RequestorInTBE, "\eeeeee", desc="Send local invalidates to sharers if they exist") {
1123 assert(is_valid(tbe));
1124 if (countLocalSharers(cache_entry, address) == 0) {
1125 tbe.NumIntPendingAcks := 0;
1128 if (isLocalSharer(cache_entry, address, tbe.L1_GetX_ID)) {
1129 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1132 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1135 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1136 out_msg.addr := address;
1137 out_msg.Type := CoherenceRequestType:INV;
1138 out_msg.Requestor := tbe.L1_GetX_ID;
1139 out_msg.RequestorMachine := MachineType:L1Cache;
1140 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1141 out_msg.Destination.remove(tbe.L1_GetX_ID);
1142 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1147 action(f_sendUnblock, "f", desc="Send unblock to global directory") {
1148 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1149 out_msg.addr := address;
1150 out_msg.Type := CoherenceResponseType:UNBLOCK;
1151 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1152 out_msg.Sender := machineID;
1153 out_msg.SenderMachine := MachineType:L2Cache;
1154 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1159 action(f_sendExclusiveUnblock, "\f", desc="Send unblock to global directory") {
1160 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1161 out_msg.addr := address;
1162 out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
1163 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1164 out_msg.Sender := machineID;
1165 out_msg.SenderMachine := MachineType:L2Cache;
1166 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1171 action(g_recordLocalSharer, "g", desc="Record new local sharer from unblock message") {
1172 peek(responseNetwork_in, ResponseMsg) {
1173 recordLocalSharerInDir(cache_entry, in_msg.addr, in_msg.Sender);
1177 action(g_recordLocalExclusive, "\g", desc="Record new local exclusive sharer from unblock message") {
1178 peek(responseNetwork_in, ResponseMsg) {
1179 recordNewLocalExclusiveInDir(cache_entry, address, in_msg.Sender);
1183 action(gg_clearLocalSharers, "gg", desc="Clear local sharers") {
1184 removeAllLocalSharersFromDir(cache_entry, address);
1187 action(gg_clearSharerFromL1Response, "\gg", desc="Clear sharer from L1 response queue") {
1188 peek(responseNetwork_in, ResponseMsg) {
1189 removeSharerFromDir(cache_entry, in_msg.addr, in_msg.Sender);
1193 action(gg_clearOwnerFromL1Response, "g\g", desc="Clear sharer from L1 response queue") {
1194 peek(responseNetwork_in, ResponseMsg) {
1195 removeOwnerFromDir(cache_entry, in_msg.addr, in_msg.Sender);
1199 action(h_countLocalSharersExceptRequestor, "h", desc="counts number of acks needed for L1 GETX") {
1200 peek(L1requestNetwork_in, RequestMsg) {
1201 assert(is_valid(tbe));
1202 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, in_msg.Requestor);
1206 action(h_clearIntAcks, "\h", desc="clear IntAcks") {
1207 assert(is_valid(tbe));
1208 tbe.Local_GETX_IntAcks := 0;
1211 action(hh_countLocalSharersExceptL1GETXRequestorInTBE, "hh", desc="counts number of acks needed for L1 GETX") {
1212 assert(is_valid(tbe));
1213 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, tbe.L1_GetX_ID);
1216 action(i_copyDataToTBE, "\i", desc="Copy data from response queue to TBE") {
1217 peek(responseNetwork_in, ResponseMsg) {
1218 assert(is_valid(tbe));
1219 tbe.DataBlk := in_msg.DataBlk;
1220 tbe.Dirty := in_msg.Dirty;
1221 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1225 action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") {
1226 check_allocate(TBEs);
1227 TBEs.allocate(address);
1228 set_tbe(TBEs[address]);
1229 if(is_valid(cache_entry)) {
1230 tbe.DataBlk := cache_entry.DataBlk;
1231 tbe.Dirty := cache_entry.Dirty;
1233 tbe.NumIntPendingAcks := 0; // default value
1234 tbe.NumExtPendingAcks := 0; // default value
1235 tbe.Fwd_GetS_IDs.clear();
1236 tbe.L1_GetS_IDs.clear();
1241 action(j_forwardGlobalRequestToLocalOwner, "j", desc="Forward external request to local owner") {
1242 peek(requestNetwork_in, RequestMsg) {
1243 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1244 out_msg.addr := in_msg.addr;
1245 out_msg.Type := in_msg.Type;
1246 out_msg.Requestor := machineID;
1247 out_msg.RequestorMachine := MachineType:L2Cache;
1248 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1249 out_msg.Type := in_msg.Type;
1250 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1251 out_msg.Acks := 0 - 1;
1256 action(jd_forwardDmaRequestToLocalOwner, "jd", desc="Forward dma request to local owner") {
1257 peek(requestNetwork_in, RequestMsg) {
1258 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1259 out_msg.addr := in_msg.addr;
1260 out_msg.Type := in_msg.Type;
1261 out_msg.Requestor := in_msg.Requestor;
1262 out_msg.RequestorMachine := in_msg.RequestorMachine;
1263 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1264 out_msg.Type := in_msg.Type;
1265 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1266 out_msg.Acks := 0 - 1;
1272 action(k_forwardLocalGETSToLocalSharer, "k", desc="Forward local request to local sharer/owner") {
1273 peek(L1requestNetwork_in, RequestMsg) {
1274 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1275 out_msg.addr := in_msg.addr;
1276 out_msg.Type := CoherenceRequestType:GETS;
1277 out_msg.Requestor := in_msg.Requestor;
1278 out_msg.RequestorMachine := MachineType:L1Cache;
1279 // should randomize this so one node doesn't get abused more than others
1280 DirEntry dir_entry := getDirEntry(in_msg.addr);
1281 out_msg.Destination.add(dir_entry.Sharers.smallestElement(MachineType:L1Cache));
1282 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1287 action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") {
1288 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1289 assert(is_valid(tbe));
1290 out_msg.addr := address;
1291 out_msg.Type := CoherenceRequestType:GETX;
1292 out_msg.Requestor := tbe.L1_GetX_ID;
1293 out_msg.RequestorMachine := MachineType:L1Cache;
1294 DirEntry dir_entry := getDirEntry(address);
1295 out_msg.Destination.add(dir_entry.Owner);
1296 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1297 out_msg.Acks := 1 + tbe.Local_GETX_IntAcks;
1301 // same as previous except that it assumes to TBE is present to get number of acks
1302 action(kk_forwardLocalGETXToLocalExclusive, "kk", desc="Forward local request to local owner") {
1303 peek(L1requestNetwork_in, RequestMsg) {
1304 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1305 out_msg.addr := in_msg.addr;
1306 out_msg.Type := CoherenceRequestType:GETX;
1307 out_msg.Requestor := in_msg.Requestor;
1308 out_msg.RequestorMachine := MachineType:L1Cache;
1309 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1310 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1316 action(kk_forwardLocalGETSToLocalOwner, "\kk", desc="Forward local request to local owner") {
1317 peek(L1requestNetwork_in, RequestMsg) {
1318 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1319 out_msg.addr := in_msg.addr;
1320 out_msg.Type := CoherenceRequestType:GETS;
1321 out_msg.Requestor := in_msg.Requestor;
1322 out_msg.RequestorMachine := MachineType:L1Cache;
1323 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1324 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1330 action(l_writebackAckNeedData, "l", desc="Send writeback ack to L1 requesting data") {
1331 peek(L1requestNetwork_in, RequestMsg) {
1332 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1333 out_msg.addr := in_msg.addr;
1334 // out_msg.Type := CoherenceResponseType:WRITEBACK_SEND_DATA;
1335 out_msg.Type := CoherenceRequestType:WB_ACK_DATA;
1336 out_msg.Requestor := machineID;
1337 out_msg.RequestorMachine := MachineType:L2Cache;
1338 out_msg.Destination.add(in_msg.Requestor);
1339 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1344 action(l_writebackAckDropData, "\l", desc="Send writeback ack to L1 indicating to drop data") {
1345 peek(L1requestNetwork_in, RequestMsg) {
1346 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1347 out_msg.addr := in_msg.addr;
1348 // out_msg.Type := CoherenceResponseType:WRITEBACK_ACK;
1349 out_msg.Type := CoherenceRequestType:WB_ACK;
1350 out_msg.Requestor := machineID;
1351 out_msg.RequestorMachine := MachineType:L2Cache;
1352 out_msg.Destination.add(in_msg.Requestor);
1353 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1358 action(ll_writebackNack, "\ll", desc="Send writeback nack to L1") {
1359 peek(L1requestNetwork_in, RequestMsg) {
1360 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1361 out_msg.addr := in_msg.addr;
1362 out_msg.Type := CoherenceRequestType:WB_NACK;
1363 out_msg.Requestor := machineID;
1364 out_msg.RequestorMachine := MachineType:L2Cache;
1365 out_msg.Destination.add(in_msg.Requestor);
1366 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1371 action(m_popRequestQueue, "m", desc="Pop request queue.") {
1372 requestNetwork_in.dequeue(clockEdge());
1375 action(m_decrementNumberOfMessagesInt, "\m", desc="Decrement the number of messages for which we're waiting") {
1376 peek(responseNetwork_in, ResponseMsg) {
1377 assert(is_valid(tbe));
1378 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + in_msg.Acks;
1382 action(m_decrementNumberOfMessagesExt, "\mmm", desc="Decrement the number of messages for which we're waiting") {
1383 peek(responseNetwork_in, ResponseMsg) {
1384 assert(is_valid(tbe));
1385 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1389 action(mm_decrementNumberOfMessagesExt, "\mm", desc="Decrement the number of messages for which we're waiting") {
1390 peek(requestNetwork_in, RequestMsg) {
1391 assert(is_valid(tbe));
1392 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1396 action(n_popResponseQueue, "n", desc="Pop response queue") {
1397 responseNetwork_in.dequeue(clockEdge());
1400 action(n_popTriggerQueue, "\n", desc="Pop trigger queue.") {
1401 triggerQueue_in.dequeue(clockEdge());
1404 action(o_popL1RequestQueue, "o", desc="Pop L1 request queue.") {
1405 L1requestNetwork_in.dequeue(clockEdge());
1409 action(o_checkForIntCompletion, "\o", desc="Check if we have received all the messages required for completion") {
1410 assert(is_valid(tbe));
1411 if (tbe.NumIntPendingAcks == 0) {
1412 enqueue(triggerQueue_out, TriggerMsg) {
1413 out_msg.addr := address;
1414 out_msg.Type := TriggerType:ALL_ACKS;
1419 action(o_checkForExtCompletion, "\oo", desc="Check if we have received all the messages required for completion") {
1420 assert(is_valid(tbe));
1421 if (tbe.NumExtPendingAcks == 0) {
1422 enqueue(triggerQueue_out, TriggerMsg) {
1423 out_msg.addr := address;
1424 out_msg.Type := TriggerType:ALL_ACKS;
1430 action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") {
1431 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1432 assert(is_valid(tbe));
1433 out_msg.addr := address;
1434 out_msg.Sender := machineID;
1435 out_msg.SenderMachine := MachineType:L2Cache;
1436 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1437 out_msg.Dirty := tbe.Dirty;
1439 out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA;
1440 out_msg.DataBlk := tbe.DataBlk;
1441 out_msg.MessageSize := MessageSizeType:Writeback_Data;
1443 out_msg.Type := CoherenceResponseType:WRITEBACK_CLEAN_ACK;
1444 // NOTE: in a real system this would not send data. We send
1445 // data here only so we can check it at the memory
1446 out_msg.DataBlk := tbe.DataBlk;
1447 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1452 action( r_setMRU, "\rrr", desc="manually set the MRU bit for cache line" ) {
1453 if(is_valid(cache_entry)) {
1454 L2cache.setMRU(address);
1458 action( s_recordGetXL1ID, "ss", desc="record local GETX requestor") {
1459 peek(L1requestNetwork_in, RequestMsg) {
1460 assert(is_valid(tbe));
1461 tbe.L1_GetX_ID := in_msg.Requestor;
1465 action(s_deallocateTBE, "s", desc="Deallocate external TBE") {
1466 TBEs.deallocate(address);
1470 action( s_recordGetSL1ID, "\ss", desc="record local GETS requestor") {
1471 peek(L1requestNetwork_in, RequestMsg) {
1472 assert(is_valid(tbe));
1473 tbe.L1_GetS_IDs.add(in_msg.Requestor);
1477 action(t_recordFwdXID, "t", desc="record global GETX requestor") {
1478 peek(requestNetwork_in, RequestMsg) {
1479 assert(is_valid(tbe));
1480 tbe.Fwd_GetX_ID := in_msg.Requestor;
1481 tbe.Fwd_GETX_ExtAcks := in_msg.Acks;
1485 action(t_recordFwdSID, "\t", desc="record global GETS requestor") {
1486 peek(requestNetwork_in, RequestMsg) {
1487 assert(is_valid(tbe));
1488 tbe.Fwd_GetS_IDs.clear();
1489 tbe.Fwd_GetS_IDs.add(in_msg.Requestor);
1494 action(u_writeDataToCache, "u", desc="Write data to cache") {
1495 peek(responseNetwork_in, ResponseMsg) {
1496 assert(is_valid(cache_entry));
1497 cache_entry.DataBlk := in_msg.DataBlk;
1498 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1499 address, cache_entry.DataBlk);
1500 if ((cache_entry.Dirty == false) && in_msg.Dirty) {
1501 cache_entry.Dirty := in_msg.Dirty;
1506 action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") {
1507 set_cache_entry(L2cache.allocate(address, new Entry));
1510 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
1511 L2cache.deallocate(address);
1512 unset_cache_entry();
1516 action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") {
1517 peek(responseNetwork_in, ResponseMsg) {
1518 assert(is_valid(cache_entry));
1519 assert(cache_entry.DataBlk == in_msg.DataBlk);
1523 action(uu_profileMiss, "\um", desc="Profile the demand miss") {
1524 ++L2cache.demand_misses;
1527 action(uu_profileHit, "\uh", desc="Profile the demand hit") {
1528 ++L2cache.demand_hits;
1531 action(y_copyCacheStateToDir, "y", desc="Copy cache state to directory state") {
1532 copyCacheStateToDir(cache_entry, address);
1535 action(y_copyDirToCacheAndRemove, "/y", desc="Copy dir state to cache and remove") {
1536 copyDirToCache(cache_entry, address);
1537 localDirectory.deallocate(address);
1540 action(zz_recycleL1RequestQueue, "zz", desc="Send the head of the mandatory queue to the back of the queue.") {
1541 peek(L1requestNetwork_in, RequestMsg) {
1542 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1544 L1requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1547 action(zz_recycleRequestQueue, "\zz", desc="Send the head of the mandatory queue to the back of the queue.") {
1548 peek(requestNetwork_in, RequestMsg) {
1549 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1551 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1554 action(zz_recycleResponseQueue, "\z\z", desc="Send the head of the mandatory queue to the back of the queue.") {
1555 peek(responseNetwork_in, ResponseMsg) {
1556 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1558 responseNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1561 action(da_sendDmaAckUnblock, "da", desc="Send dma ack to global directory") {
1562 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1563 out_msg.addr := address;
1564 out_msg.Type := CoherenceResponseType:DMA_ACK;
1565 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1566 out_msg.Sender := machineID;
1567 out_msg.SenderMachine := MachineType:L2Cache;
1568 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1574 //*****************************************************
1576 //*****************************************************
1578 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, OFGX, 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}) {
1579 zz_recycleL1RequestQueue;
1582 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, OFGX, 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}) {
1583 zz_recycleL1RequestQueue;
1586 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, OFGX, 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) {
1587 zz_recycleResponseQueue;
1590 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, OFGX, 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}) {
1591 zz_recycleRequestQueue;
1594 transition({OGMIO, IGMIO, IGMO}, Fwd_DMA) {
1595 zz_recycleRequestQueue;
1598 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, OFGX, 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}) {
1599 zz_recycleRequestQueue;
1602 transition({IGM, IGS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Own_GETX}) {
1603 zz_recycleRequestQueue;
1606 // must happened because we forwarded GETX to local exclusive trying to do wb
1607 transition({I, M, O, ILS, ILOX, OLS, OLSX, SLS, S}, L1_PUTX) {
1609 o_popL1RequestQueue;
1612 transition({M}, {L1_PUTS, L1_PUTO} ) {
1614 o_popL1RequestQueue;
1617 transition({ILS, OLSX}, L1_PUTO){
1619 o_popL1RequestQueue;
1622 // happened if we forwarded GETS to exclusive who tried to do writeback
1623 // ?? should we just Nack these instead? Could be a bugs here
1624 transition(ILO, L1_PUTX, ILOW) {
1625 l_writebackAckNeedData;
1626 o_popL1RequestQueue;
1629 // this can happen if we forwarded a L1_GETX to exclusiver after it issued a PUTX
1630 transition(ILOS, L1_PUTX, ILOSW) {
1631 l_writebackAckNeedData;
1632 o_popL1RequestQueue;
1635 transition(ILOSX, L1_PUTX, ILOSXW) {
1636 l_writebackAckNeedData;
1637 o_popL1RequestQueue;
1640 // must happened because we got Inv when L1 attempted PUTS
1641 transition(I, L1_PUTS) {
1643 o_popL1RequestQueue;
1646 transition(I, L1_PUTO) {
1648 o_popL1RequestQueue;
1651 // FORWARDED REQUESTS
1653 transition({ILO, ILX, ILOX}, Fwd_GETS, IFGS) {
1656 j_forwardGlobalRequestToLocalOwner;
1660 transition({ILOS, ILOSX}, Fwd_GETS, ISFGS) {
1663 j_forwardGlobalRequestToLocalOwner;
1667 transition(ILOS, Fwd_DMA, ILOSD) {
1669 jd_forwardDmaRequestToLocalOwner;
1673 transition(ILOSD, DmaAck, ILOS) {
1675 da_sendDmaAckUnblock;
1679 transition(ILOSX, Fwd_DMA, ILOSXD) {
1682 jd_forwardDmaRequestToLocalOwner;
1686 transition(ILOSXD, DmaAck, ILOSX) {
1688 da_sendDmaAckUnblock;
1692 transition(ILO, Fwd_DMA, ILOD) {
1695 jd_forwardDmaRequestToLocalOwner;
1699 transition(ILOD, DmaAck, ILO) {
1701 da_sendDmaAckUnblock;
1705 transition(ILX, Fwd_DMA, ILXD) {
1708 jd_forwardDmaRequestToLocalOwner;
1712 transition(ILXD, DmaAck, ILX) {
1714 da_sendDmaAckUnblock;
1718 transition(ILOX, Fwd_DMA, ILOXD) {
1721 jd_forwardDmaRequestToLocalOwner;
1725 transition(ILOXD, DmaAck, ILOX) {
1727 da_sendDmaAckUnblock;
1731 transition({ILOS, ILOSX, ILO, ILX, ILOX, ILXW}, Data) {
1733 c_sendDataFromTBEToFwdGETS;
1738 transition(IFGS, Data, ILO) {
1740 c_sendDataFromTBEToFwdGETS;
1745 transition(ISFGS, Data, ILOS) {
1747 c_sendDataFromTBEToFwdGETS;
1752 transition(IFGS, Data_Exclusive, I) {
1754 c_sendExclusiveDataFromTBEToFwdGETS;
1755 gg_clearLocalSharers;
1761 transition({ILX, ILO, ILOX}, Fwd_GETX, IFGX) {
1764 j_forwardGlobalRequestToLocalOwner;
1768 transition(IFGX, {Data_Exclusive, Data}, I) {
1770 c_sendDataFromTBEToFwdGETX;
1771 gg_clearLocalSharers;
1776 transition({ILOSX, ILOS}, Fwd_GETX, IFGXX) {
1779 j_forwardGlobalRequestToLocalOwner;
1780 ee_sendLocalInvSharersOnly;
1786 transition(IFGXX, IntAck) {
1787 m_decrementNumberOfMessagesInt;
1788 o_checkForIntCompletion;
1792 transition(IFGXX, Data_Exclusive) {
1794 m_decrementNumberOfMessagesInt;
1795 o_checkForIntCompletion;
1799 transition(IFGXX, All_Acks, I) {
1800 c_sendDataFromTBEToFwdGETX;
1801 gg_clearLocalSharers;
1807 // transition({O, OX}, Fwd_GETX, I) {
1808 transition(O, Fwd_GETX, I) {
1809 dd_sendDataToFwdGETX;
1810 y_copyCacheStateToDir;
1811 rr_deallocateL2CacheBlock;
1815 transition({O, OLS}, Fwd_GETS) {
1816 dd_sendDataToFwdGETS;
1820 transition({O, OLS}, Fwd_DMA) {
1821 dd_sendDataToFwdGETS;
1822 da_sendDmaAckUnblock;
1826 // transition({OLSX, OX}, Fwd_GETS, O) {
1827 transition(OLSX, Fwd_GETS, OLS) {
1828 dd_sendDataToFwdGETS;
1832 transition(OLSX, Fwd_DMA) {
1833 dd_sendDataToFwdGETS;
1834 da_sendDmaAckUnblock;
1838 transition(M, Fwd_GETX, I) {
1839 dd_sendDataToFwdGETX;
1840 rr_deallocateL2CacheBlock;
1844 // MAKE THIS THE SAME POLICY FOR NOW
1846 // transition(M, Fwd_GETS, O) {
1847 // dd_sendDataToFwdGETS;
1848 // m_popRequestQueue;
1851 transition(M, Fwd_GETS, I) {
1852 dd_sendExclusiveDataToFwdGETS;
1853 rr_deallocateL2CacheBlock;
1857 transition(M, Fwd_DMA) {
1858 dd_sendExclusiveDataToFwdGETS;
1859 da_sendDmaAckUnblock;
1863 transition({OLS, OLSX}, Fwd_GETX, OLSF) {
1870 transition(OLSF, IntAck) {
1871 m_decrementNumberOfMessagesInt;
1872 o_checkForIntCompletion;
1876 transition(OLSF, All_Acks, I) {
1877 c_sendDataFromTBEToFwdGETX;
1878 gg_clearLocalSharers;
1880 rr_deallocateL2CacheBlock;
1886 // INVALIDATIONS FROM GLOBAL DIRECTORY
1888 transition({IGM, IGS}, Inv) {
1894 transition({I,NP}, Inv) {
1902 // NEED INV for S state
1904 transition({ILS, ILO, ILX}, Inv, II) {
1908 gg_clearLocalSharers;
1912 transition(SLS, Inv, II) {
1916 rr_deallocateL2CacheBlock;
1920 transition(II, IntAck) {
1921 m_decrementNumberOfMessagesInt;
1922 o_checkForIntCompletion;
1926 transition(II, All_Acks, I) {
1932 transition(S, Inv, I) {
1937 rr_deallocateL2CacheBlock;
1942 // LOCAL REQUESTS SATISFIED LOCALLY
1944 transition(OLSX, L1_GETX, IFLOX) {
1947 // count number of INVs needed that doesn't include requestor
1948 h_countLocalSharersExceptRequestor;
1949 // issue INVs to everyone except requestor
1950 ee_issueLocalInvExceptL1Requestor;
1952 y_copyCacheStateToDir;
1954 rr_deallocateL2CacheBlock;
1956 o_popL1RequestQueue;
1959 transition(IFLOX, Exclusive_Unblock, ILX) {
1960 g_recordLocalExclusive;
1965 transition(OLSX, L1_GETS, OLSXS) {
1969 o_popL1RequestQueue;
1972 transition(OLSXS, Unblock, OLSX) {
1973 g_recordLocalSharer;
1977 // after this, can't get Fwd_GETX
1978 transition(IGMO, Own_GETX) {
1979 mm_decrementNumberOfMessagesExt;
1980 o_checkForExtCompletion;
1986 transition(ILX, L1_GETS, IFLOXX) {
1987 kk_forwardLocalGETSToLocalOwner;
1989 o_popL1RequestQueue;
1992 transition(ILOSX, L1_GETS, IFLOSX) {
1993 kk_forwardLocalGETSToLocalOwner;
1995 o_popL1RequestQueue;
1998 transition({ILOS, ILO}, L1_GETS, IFLO) {
1999 kk_forwardLocalGETSToLocalOwner;
2001 o_popL1RequestQueue;
2004 transition(ILS, L1_GETS, IFLS) {
2005 k_forwardLocalGETSToLocalSharer;
2007 o_popL1RequestQueue;
2010 transition({ILX, ILOX}, L1_GETX, IFLOXX) {
2011 kk_forwardLocalGETXToLocalExclusive;
2012 e_sendAckToL1Requestor;
2014 o_popL1RequestQueue;
2017 transition(ILOX, L1_GETS, IFLOX) {
2018 kk_forwardLocalGETSToLocalOwner;
2020 o_popL1RequestQueue;
2023 transition(IFLOX, Unblock, ILOSX) {
2024 g_recordLocalSharer;
2028 transition(IFLS, Unblock, ILS) {
2029 g_recordLocalSharer;
2033 transition(IFLOXX, Unblock, ILOSX) {
2034 g_recordLocalSharer;
2038 transition(IFLOSX, Unblock, ILOSX) {
2039 g_recordLocalSharer;
2043 transition({IFLOSX, IFLOXX}, Exclusive_Unblock, ILX) {
2044 g_recordLocalExclusive;
2048 transition(IFLO, Unblock, ILOS) {
2049 g_recordLocalSharer;
2054 transition(ILOSX, L1_GETX, IFLXO) {
2057 h_countLocalSharersExceptRequestor;
2058 ee_issueLocalInvExceptL1Requestor;
2059 k_forwardLocalGETXToLocalOwner;
2060 e_sendAckToL1RequestorFromTBE;
2062 o_popL1RequestQueue;
2065 transition(IFLXO, Exclusive_Unblock, ILX) {
2066 g_recordLocalExclusive;
2071 // LOCAL REQUESTS THAT MUST ISSUE
2073 transition(NP, {L1_PUTS, L1_PUTX, L1_PUTO}) {
2075 o_popL1RequestQueue;
2078 transition({NP, I}, L1_GETS, IGS) {
2083 o_popL1RequestQueue;
2086 transition({NP, I}, L1_GETX, IGM) {
2091 o_popL1RequestQueue;
2094 transition(S, L1_GETX, IGM) {
2098 y_copyCacheStateToDir;
2100 rr_deallocateL2CacheBlock;
2102 o_popL1RequestQueue;
2105 transition(ILS, L1_GETX, IGMLS) {
2109 // count number of INVs (just sharers?) needed that doesn't include requestor
2110 h_countLocalSharersExceptRequestor;
2112 o_popL1RequestQueue;
2115 transition(IGMLS, Inv) {
2121 transition(IGMLS, IntAck) {
2122 m_decrementNumberOfMessagesInt;
2123 o_checkForIntCompletion;
2127 transition(IGMLS, All_Acks, IGM) {
2128 gg_clearLocalSharers;
2134 // transition(IGMLS, ExtAck, IGMO) {
2135 transition(IGMLS, ExtAck) {
2136 m_decrementNumberOfMessagesExt;
2137 o_checkForExtCompletion;
2141 transition(IGMLS, {Data, Data_Exclusive}, IGMO) {
2142 ee_issueLocalInvExceptL1RequestorInTBE;
2144 m_decrementNumberOfMessagesExt;
2145 o_checkForExtCompletion;
2150 transition(ILOS, L1_GETX, IGMIO) {
2155 o_popL1RequestQueue;
2158 // new exclusive happened while sharer attempted writeback
2159 transition(ILX, {L1_PUTS, L1_PUTS_only, L1_PUTO}) {
2161 o_popL1RequestQueue;
2164 transition(S, L1_PUTS) {
2166 o_popL1RequestQueue;
2169 transition(OLS, L1_GETX, OGMIO) {
2173 h_countLocalSharersExceptRequestor;
2174 // COPY DATA FROM CACHE TO TBE (happens during i_allocateTBE)
2175 y_copyCacheStateToDir;
2176 rr_deallocateL2CacheBlock;
2178 o_popL1RequestQueue;
2181 transition(OGMIO, Fwd_GETS) {
2183 c_sendDataFromTBEToFwdGETS;
2187 transition(ILO, L1_GETX, IGMIO) {
2191 // the following, of course, returns 0 sharers but do anyways for consistency
2192 h_countLocalSharersExceptRequestor;
2194 o_popL1RequestQueue;
2197 transition({ILO, ILOX}, L1_PUTS) {
2199 o_popL1RequestQueue;
2202 transition(IGMIO, Fwd_GETX, IGMIOF) {
2204 j_forwardGlobalRequestToLocalOwner;
2205 ee_sendLocalInvSharersOnly;
2210 transition(IGMIO, Fwd_GETS, IGMIOFS) {
2212 j_forwardGlobalRequestToLocalOwner;
2216 transition(IGMIOFS, Data, IGMIO) {
2218 c_sendDataFromTBEToFwdGETS;
2222 transition(OGMIO, Fwd_GETX, OGMIOF) {
2224 ee_sendLocalInvSharersOnly;
2228 transition(OGMIOF, IntAck) {
2229 m_decrementNumberOfMessagesInt;
2230 o_checkForIntCompletion;
2234 transition(OGMIOF, All_Acks, IGM) {
2235 gg_clearLocalSharers;
2236 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2237 c_sendDataFromTBEToFwdGETX;
2241 transition(IGMIOF, IntAck) {
2242 m_decrementNumberOfMessagesInt;
2243 o_checkForIntCompletion;
2247 transition(IGMIOF, Data_Exclusive) {
2249 m_decrementNumberOfMessagesInt;
2250 o_checkForIntCompletion;
2254 transition(IGMIOF, All_Acks, IGM) {
2255 gg_clearLocalSharers;
2256 c_sendDataFromTBEToFwdGETX;
2260 transition(IGMIO, All_Acks, IGMO) {
2261 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2262 ee_issueLocalInvExceptL1RequestorInTBE;
2263 k_forwardLocalGETXToLocalOwner;
2264 e_sendAckToL1RequestorFromTBE;
2268 transition(OGMIO, All_Acks, IGMO) {
2269 ee_issueLocalInvExceptL1RequestorInTBE;
2270 c_sendDataFromTBEToL1GETX;
2274 transition({IGMIO, OGMIO}, Own_GETX) {
2275 mm_decrementNumberOfMessagesExt;
2276 o_checkForExtCompletion;
2281 transition(IGM, {Data, Data_Exclusive}, IGMO) {
2283 m_decrementNumberOfMessagesExt;
2284 o_checkForExtCompletion;
2288 transition({IGM, IGMIO, OGMIO}, ExtAck) {
2289 m_decrementNumberOfMessagesExt;
2290 o_checkForExtCompletion;
2294 transition(IGMO, ExtAck) {
2295 m_decrementNumberOfMessagesExt;
2296 o_checkForExtCompletion;
2300 transition(IGS, Data) {
2302 m_decrementNumberOfMessagesExt;
2303 c_sendDataFromTBEToL1GETS;
2307 transition(IGS, Data_Exclusive) {
2309 m_decrementNumberOfMessagesExt;
2310 c_sendExclusiveDataFromTBEToL1GETS;
2314 transition(IGS, Unblock, ILS) {
2315 g_recordLocalSharer;
2321 transition(IGS, Exclusive_Unblock, ILX) {
2322 g_recordLocalExclusive;
2323 f_sendExclusiveUnblock;
2328 transition(IGMO, All_Acks) {
2329 c_sendDataFromTBEToL1GETX;
2333 transition(IGMO, Exclusive_Unblock, ILX) {
2334 g_recordLocalExclusive;
2335 f_sendExclusiveUnblock;
2341 transition(SLS, L1_GETX, IGMLS) {
2345 // count number of INVs needed that doesn't include requestor
2346 h_countLocalSharersExceptRequestor;
2347 // issue INVs to everyone except requestor
2348 y_copyCacheStateToDir;
2349 rr_deallocateL2CacheBlock;
2351 o_popL1RequestQueue;
2355 transition(SLS, L1_GETS, SLSS ) {
2359 o_popL1RequestQueue;
2362 transition(SLSS, Unblock, SLS) {
2363 g_recordLocalSharer;
2368 transition(O, L1_GETX, IGMO) {
2372 y_copyCacheStateToDir;
2373 rr_deallocateL2CacheBlock;
2375 o_popL1RequestQueue;
2378 transition(OLS, L1_GETS, OLSS) {
2382 o_popL1RequestQueue;
2385 transition(OLSS, Unblock, OLS) {
2386 g_recordLocalSharer;
2390 transition(IGMO, Fwd_GETX, IGM) {
2392 c_sendDataFromTBEToFwdGETX;
2397 transition(IGMO, Fwd_GETS) {
2399 c_sendDataFromTBEToFwdGETS;
2404 // LOCAL REQUESTS SATISFIED DIRECTLY BY L2
2406 transition(M, L1_GETX, MM) {
2408 // should count 0 of course
2409 h_countLocalSharersExceptRequestor;
2411 y_copyCacheStateToDir;
2412 rr_deallocateL2CacheBlock;
2415 o_popL1RequestQueue;
2418 transition(MM, Exclusive_Unblock, ILX) {
2419 g_recordLocalExclusive;
2423 transition(M, L1_GETS, OO) {
2425 // should count 0 of course
2426 h_countLocalSharersExceptRequestor;
2431 o_popL1RequestQueue;
2434 transition(S, L1_GETS, SS) {
2438 o_popL1RequestQueue;
2441 transition(SS, Unblock, SLS) {
2442 g_recordLocalSharer;
2446 transition(O, L1_GETS, OO) {
2450 o_popL1RequestQueue;
2453 transition(OO, Unblock, OLS) {
2454 g_recordLocalSharer;
2458 transition(OO, Exclusive_Unblock, ILX) {
2459 g_recordLocalExclusive
2460 y_copyCacheStateToDir;
2461 rr_deallocateL2CacheBlock;
2467 transition(ILO, L1_PUTO, ILOW) {
2468 l_writebackAckNeedData;
2469 o_popL1RequestQueue;
2472 transition(ILOX, L1_PUTO, ILOXW) {
2473 l_writebackAckNeedData;
2474 o_popL1RequestQueue;
2478 transition(ILOS, L1_PUTO, ILOSW) {
2479 l_writebackAckNeedData;
2480 o_popL1RequestQueue;
2483 transition(ILOSX, L1_PUTO, ILOSXW) {
2484 l_writebackAckNeedData;
2485 o_popL1RequestQueue;
2489 // hmmm...keep data or drop. Just drop for now
2490 transition(ILOS, L1_PUTS_only, ILOW) {
2491 l_writebackAckDropData;
2492 o_popL1RequestQueue;
2495 transition(ILSW, Unblock, ILS) {
2496 gg_clearSharerFromL1Response;
2500 transition(ILOW, Unblock, ILO) {
2501 gg_clearSharerFromL1Response;
2505 transition(ILOSX, L1_PUTS_only, ILOXW) {
2506 l_writebackAckDropData;
2507 o_popL1RequestQueue;
2510 transition(ILOXW, Unblock, ILOX) {
2511 gg_clearSharerFromL1Response;
2515 // hmmm...keep data or drop. Just drop for now
2516 transition(ILOS, L1_PUTS, ILOSW) {
2517 l_writebackAckDropData;
2518 o_popL1RequestQueue;
2521 transition(ILOSX, L1_PUTS, ILOSXW) {
2522 l_writebackAckDropData;
2523 o_popL1RequestQueue;
2526 transition(ILOSW, Unblock, ILOS) {
2527 gg_clearSharerFromL1Response;
2531 transition(ILOSXW, Unblock, ILOSX) {
2532 gg_clearSharerFromL1Response;
2536 transition(SLS, L1_PUTS, SLSW) {
2537 l_writebackAckDropData;
2538 o_popL1RequestQueue;
2541 transition(SLS, L1_PUTS_only, SW) {
2542 l_writebackAckDropData;
2543 o_popL1RequestQueue;
2546 transition(SW, {Unblock}, S) {
2547 gg_clearSharerFromL1Response;
2551 transition(OLS, L1_PUTS, OLSW) {
2552 l_writebackAckDropData;
2553 o_popL1RequestQueue;
2556 transition(ILS, L1_PUTS, ILSW) {
2557 l_writebackAckNeedData;
2558 o_popL1RequestQueue;
2561 transition(ILS, L1_PUTS_only, IW) {
2562 l_writebackAckNeedData;
2563 o_popL1RequestQueue;
2566 transition(OLS, L1_PUTS_only, OW) {
2567 l_writebackAckDropData;
2568 o_popL1RequestQueue;
2571 transition(OLSX, L1_PUTS_only, OXW) {
2572 l_writebackAckDropData;
2573 o_popL1RequestQueue;
2576 transition(OLSX, L1_PUTS, OLSXW) {
2577 l_writebackAckDropData;
2578 o_popL1RequestQueue;
2581 transition(OLSXW, {Unblock}, OLSX) {
2582 gg_clearSharerFromL1Response;
2586 transition(OW, {Unblock}, O) {
2587 gg_clearSharerFromL1Response;
2591 transition(OXW, {Unblock}, M) {
2592 gg_clearSharerFromL1Response;
2596 transition(ILX, L1_PUTX, ILXW ) {
2597 l_writebackAckNeedData;
2598 o_popL1RequestQueue;
2601 transition(ILXW, L1_WBDIRTYDATA, M) {
2602 gg_clearLocalSharers;
2603 vv_allocateL2CacheBlock;
2604 y_copyDirToCacheAndRemove;
2610 transition(ILXW, L1_WBCLEANDATA, M) {
2611 gg_clearLocalSharers;
2612 vv_allocateL2CacheBlock;
2613 y_copyDirToCacheAndRemove;
2618 transition(ILXW, Unblock, ILX) {
2619 // writeback canceled because L1 invalidated
2623 transition(ILSW, L1_WBCLEANDATA, SLS) {
2624 vv_allocateL2CacheBlock;
2625 y_copyDirToCacheAndRemove;
2627 gg_clearSharerFromL1Response;
2631 transition(IW, L1_WBCLEANDATA, S) {
2632 vv_allocateL2CacheBlock;
2633 y_copyDirToCacheAndRemove;
2635 gg_clearSharerFromL1Response;
2640 // Owner can have dirty data
2641 transition(ILOW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, O) {
2642 vv_allocateL2CacheBlock;
2643 y_copyDirToCacheAndRemove;
2644 gg_clearOwnerFromL1Response;
2649 transition(ILOXW, L1_WBDIRTYDATA, M) {
2650 vv_allocateL2CacheBlock;
2651 y_copyDirToCacheAndRemove;
2652 gg_clearOwnerFromL1Response;
2657 transition(ILOXW, L1_WBCLEANDATA, M) {
2658 vv_allocateL2CacheBlock;
2659 y_copyDirToCacheAndRemove;
2660 gg_clearOwnerFromL1Response;
2665 transition(ILOSW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, OLS) {
2666 vv_allocateL2CacheBlock;
2667 y_copyDirToCacheAndRemove;
2668 gg_clearOwnerFromL1Response;
2673 transition(ILOSXW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, OLSX) {
2674 vv_allocateL2CacheBlock;
2675 y_copyDirToCacheAndRemove;
2676 gg_clearOwnerFromL1Response;
2682 transition(SLSW, {Unblock}, SLS) {
2683 gg_clearSharerFromL1Response;
2687 transition(OLSW, {Unblock}, OLS) {
2688 gg_clearSharerFromL1Response;
2694 transition({I, S}, L2_Replacement, I) {
2695 rr_deallocateL2CacheBlock;
2698 transition(ILS, L2_Replacement) {
2699 y_copyCacheStateToDir;
2700 rr_deallocateL2CacheBlock;
2703 transition(ILX, L2_Replacement ) {
2704 y_copyCacheStateToDir;
2705 rr_deallocateL2CacheBlock;
2708 transition({ILO, ILOS}, L2_Replacement ) {
2709 y_copyCacheStateToDir;
2710 rr_deallocateL2CacheBlock;
2713 transition(SLS, L2_Replacement, ILS) {
2714 y_copyCacheStateToDir;
2715 rr_deallocateL2CacheBlock;
2718 transition({OLS, OLSX}, L2_Replacement, OLSI) {
2719 y_copyCacheStateToDir;
2722 rr_deallocateL2CacheBlock;
2726 transition(O, L2_Replacement, OI) {
2729 rr_deallocateL2CacheBlock;
2732 transition(M, L2_Replacement, MI) {
2735 rr_deallocateL2CacheBlock;
2738 transition(OLSI, Fwd_GETX, ILSI) {
2744 transition(ILSI, IntAck) {
2745 m_decrementNumberOfMessagesInt;
2746 o_checkForIntCompletion;
2750 transition(ILSI, All_Acks, MII) {
2751 gg_clearLocalSharers;
2752 c_sendDataFromTBEToFwdGETX;
2756 transition(OLSI, Fwd_GETS) {
2758 c_sendDataFromTBEToFwdGETS;
2762 transition({MI, OI}, Fwd_GETS, OI) {
2764 c_sendDataFromTBEToFwdGETS;
2768 transition({MI, OI}, Fwd_DMA, OI) {
2769 cd_sendDataFromTBEToFwdDma;
2770 da_sendDmaAckUnblock;
2774 transition(OLSI, Fwd_DMA) {
2775 cd_sendDataFromTBEToFwdDma;
2776 da_sendDmaAckUnblock;
2780 transition({MI, OI}, Fwd_GETX, MII) {
2782 c_sendDataFromTBEToFwdGETX;
2786 transition({MI, OI}, Writeback_Ack, I) {
2787 qq_sendDataFromTBEToMemory;
2792 transition(MII, Writeback_Nack, I) {
2797 transition(OI, Writeback_Nack) {
2802 transition(OLSI, Writeback_Ack, ILS) {
2803 qq_sendDataFromTBEToMemory;
2808 transition(MII, Writeback_Ack, I) {
2814 transition(ILSI, Writeback_Ack, ILS) {