3 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 machine(L2Cache, "Token protocol")
36 : CacheMemory * L2cacheMemory,
37 int response_latency = 2,
38 int request_latency = 2
42 // From local bank of L2 cache TO the network
43 MessageBuffer L1RequestFromL2Cache, network="To", virtual_network="0", ordered="false"; // this L2 bank -> a local L1
44 MessageBuffer GlobalRequestFromL2Cache, network="To", virtual_network="1", ordered="false"; // this L2 bank -> mod-directory
45 MessageBuffer responseFromL2Cache, network="To", virtual_network="2", ordered="false"; // this L2 bank -> a local L1 || mod-directory
47 // FROM the network to this local bank of L2 cache
48 MessageBuffer L1RequestToL2Cache, network="From", virtual_network="0", ordered="false"; // a local L1 -> this L2 bank, Lets try this???
49 MessageBuffer GlobalRequestToL2Cache, network="From", virtual_network="1", ordered="false"; // mod-directory -> this L2 bank
50 MessageBuffer responseToL2Cache, network="From", virtual_network="2", ordered="false"; // a local L1 || mod-directory -> this L2 bank
51 // MessageBuffer L1WritebackToL2Cache, network="From", virtual_network="3", ordered="false";
54 enumeration(State, desc="L2 Cache states", default="L2Cache_State_I") {
57 NP, desc="Not Present";
59 ILS, desc="Idle/NP, but local sharers exist";
60 ILX, desc="Idle/NP, but local exclusive exists";
61 ILO, desc="Idle/NP, but local owner exists";
62 ILOX, desc="Idle/NP, but local owner exists and chip is exclusive";
63 ILOS, desc="Idle/NP, but local owner exists and local sharers as well";
64 ILOSX, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
65 S, desc="Shared, no local sharers";
66 O, desc="Owned, no local sharers";
67 OLS, desc="Owned with local sharers";
68 OLSX, desc="Owned with local sharers, chip is exclusive";
69 SLS, desc="Shared with local sharers";
74 IFGX, desc="Blocked, forwarded global GETX to local owner/exclusive. No other on-chip invs needed";
75 IFGS, desc="Blocked, forwarded global GETS to local owner";
76 ISFGS, desc="Blocked, forwarded global GETS to local owner, local sharers exist";
78 IFGXX, desc="Blocked, forwarded global GETX to local owner but may need acks from other sharers";
79 OFGX, desc="Blocked, forwarded global GETX to owner and got data but may need acks";
81 OLSF, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
84 ILOW, desc="local WB request, was ILO";
85 ILOXW, desc="local WB request, was ILOX";
86 ILOSW, desc="local WB request, was ILOS";
87 ILOSXW, desc="local WB request, was ILOSX";
88 SLSW, desc="local WB request, was SLS";
89 OLSW, desc="local WB request, was OLS";
90 ILSW, desc="local WB request, was ILS";
91 IW, desc="local WB request from only sharer, was ILS";
92 OW, desc="local WB request from only sharer, was OLS";
93 SW, desc="local WB request from only sharer, was SLS";
94 OXW, desc="local WB request from only sharer, was OLSX";
95 OLSXW, desc="local WB request from sharer, was OLSX";
96 ILXW, desc="local WB request, was ILX";
98 IFLS, desc="Blocked, forwarded local GETS to _some_ local sharer";
99 IFLO, desc="Blocked, forwarded local GETS to local owner";
100 IFLOX, desc="Blocked, forwarded local GETS to local owner but chip is exclusive";
101 IFLOXX, desc="Blocked, forwarded local GETX to local owner/exclusive, chip is exclusive";
102 IFLOSX, desc="Blocked, forwarded local GETS to local owner w/ other sharers, chip is exclusive";
103 IFLXO, desc="Blocked, forwarded local GETX to local owner with other sharers, chip is exclusive";
105 IGS, desc="Semi-blocked, issued local GETS to directory";
106 IGM, desc="Blocked, issued local GETX to directory. Need global acks and data";
107 IGMLS, desc="Blocked, issued local GETX to directory but may need to INV local sharers";
108 IGMO, desc="Blocked, have data for local GETX but need all acks";
109 IGMIO, desc="Blocked, issued local GETX, local owner with possible local sharer, may need to INV";
110 OGMIO, desc="Blocked, issued local GETX, was owner, may need to INV";
111 IGMIOF, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
112 IGMIOFS, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETS";
113 OGMIOF, desc="Blocked, issued local GETX, was owner, waiting for global acks, got Fwd_GETX";
115 II, desc="Blocked, handling invalidations";
116 MM, desc="Blocked, was M satisfying local GETX";
117 SS, desc="Blocked, was S satisfying local GETS";
118 OO, desc="Blocked, was O satisfying local GETS";
119 OLSS, desc="Blocked, satisfying local GETS";
120 OLSXS, desc="Blocked, satisfying local GETS";
121 SLSS, desc="Blocked, satisfying local GETS";
123 OI, desc="Blocked, doing writeback, was O";
124 MI, desc="Blocked, doing writeback, was M";
125 MII, desc="Blocked, doing writeback, was M, got Fwd_GETX";
126 OLSI, desc="Blocked, doing writeback, was OLS";
127 ILSI, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
131 enumeration(Event, desc="Cache events") {
134 L1_GETS, desc="local L1 GETS request";
135 L1_GETX, desc="local L1 GETX request";
136 L1_PUTO, desc="local owner wants to writeback";
137 L1_PUTX, desc="local exclusive wants to writeback";
138 L1_PUTS_only, desc="only local sharer wants to writeback";
139 L1_PUTS, desc="local sharer wants to writeback";
140 Fwd_GETX, desc="A GetX from another processor";
141 Fwd_GETS, desc="A GetS from another processor";
142 Fwd_DMA, desc="A request from DMA";
143 Own_GETX, desc="A GetX from this node";
144 Inv, desc="Invalidations from the directory";
147 IntAck, desc="Received an ack message";
148 ExtAck, desc="Received an ack message";
149 All_Acks, desc="Received all ack messages";
150 Data, desc="Received a data message, responder has a shared copy";
151 Data_Exclusive, desc="Received a data message";
152 L1_WBCLEANDATA, desc="Writeback from L1, with data";
153 L1_WBDIRTYDATA, desc="Writeback from L1, with data";
155 Writeback_Ack, desc="Writeback O.K. from directory";
156 Writeback_Nack, desc="Writeback not O.K. from directory";
158 Unblock, desc="Local L1 is telling L2 dir to unblock";
159 Exclusive_Unblock, desc="Local L1 is telling L2 dir to unblock";
162 // events initiated by this L2
163 L2_Replacement, desc="L2 Replacement", format="!r";
170 structure(Entry, desc="...", interface="AbstractCacheEntry") {
171 State CacheState, desc="cache state";
172 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
173 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
174 bool OwnerValid, default="false", desc="true if Owner means something";
175 bool Dirty, desc="Is the data dirty (different than memory)?";
176 DataBlock DataBlk, desc="data for the block";
180 structure(DirEntry, desc="...") {
181 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
182 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
183 bool OwnerValid, default="false", desc="true if Owner means something";
184 State DirState, desc="directory state";
188 structure(TBE, desc="...") {
189 Address Address, desc="Physical address for this TBE";
190 State TBEState, desc="Transient state";
191 Address PC, desc="Program counter of request";
192 DataBlock DataBlk, desc="Buffer for the data block";
193 bool Dirty, desc="Is the data dirty (different than memory)?";
195 int NumExtPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
196 int NumIntPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
197 int Fwd_GETX_ExtAcks, default="0", desc="Number of acks that requestor will need";
198 int Local_GETX_IntAcks, default="0", desc="Number of acks that requestor will need";
200 NetDest L1_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
201 MachineID L1_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
202 NetDest Fwd_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
203 MachineID Fwd_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
206 external_type(TBETable) {
208 void allocate(Address);
209 void deallocate(Address);
210 bool isPresent(Address);
213 external_type(PerfectCacheMemory) {
214 void allocate(Address);
215 void deallocate(Address);
216 DirEntry lookup(Address);
217 bool isTagPresent(Address);
221 TBETable TBEs, template_hack="<L2Cache_TBE>";
222 PerfectCacheMemory localDirectory, template_hack="<L2Cache_DirEntry>";
224 void set_cache_entry(AbstractCacheEntry b);
225 void unset_cache_entry();
229 Entry getCacheEntry(Address address), return_by_pointer="yes" {
230 return static_cast(Entry, "pointer", L2cacheMemory[address]);
233 bool isDirTagPresent(Address addr) {
234 return (localDirectory.isTagPresent(addr) );
237 bool isOnlySharer(Entry cache_entry, Address addr, MachineID shar_id) {
238 if (is_valid(cache_entry)) {
239 assert (localDirectory.isTagPresent(addr) == false);
240 if (cache_entry.Sharers.count() > 1) {
243 else if (cache_entry.Sharers.count() == 1) {
244 if (cache_entry.Sharers.isElement(shar_id)) {
248 return false; // something happened which should cause this PUTS to be nacked
256 else if (localDirectory.isTagPresent(addr)){
257 if (localDirectory[addr].Sharers.count() > 1) {
260 else if (localDirectory[addr].Sharers.count() == 1) {
261 if (localDirectory[addr].Sharers.isElement(shar_id)) {
265 return false; // something happened which should cause this PUTS to be nacked
273 // shouldn't happen unless L1 issues PUTS before unblock received
278 void copyCacheStateToDir(Entry cache_entry, Address addr) {
279 assert(localDirectory.isTagPresent(addr) == false);
280 assert(is_valid(cache_entry));
281 localDirectory.allocate(addr);
282 localDirectory[addr].DirState := cache_entry.CacheState;
283 localDirectory[addr].Sharers := cache_entry.Sharers;
284 localDirectory[addr].Owner := cache_entry.Owner;
285 localDirectory[addr].OwnerValid := cache_entry.OwnerValid;
289 void copyDirToCache(Entry cache_entry, Address addr) {
290 assert(is_valid(cache_entry));
291 cache_entry.Sharers := localDirectory[addr].Sharers;
292 cache_entry.Owner := localDirectory[addr].Owner;
293 cache_entry.OwnerValid := localDirectory[addr].OwnerValid;
297 void recordLocalSharerInDir(Entry cache_entry, Address addr, MachineID shar_id) {
298 if (is_valid(cache_entry)) {
299 assert (localDirectory.isTagPresent(addr) == false);
300 cache_entry.Sharers.add(shar_id);
303 if (localDirectory.isTagPresent(addr) == false) {
304 localDirectory.allocate(addr);
305 localDirectory[addr].Sharers.clear();
306 localDirectory[addr].OwnerValid := false;
308 localDirectory[addr].Sharers.add(shar_id);
312 void recordNewLocalExclusiveInDir(Entry cache_entry, Address addr, MachineID exc_id) {
314 if (is_valid(cache_entry)) {
315 assert (localDirectory.isTagPresent(addr) == false);
316 cache_entry.Sharers.clear();
317 cache_entry.OwnerValid := true;
318 cache_entry.Owner := exc_id;
321 if (localDirectory.isTagPresent(addr) == false) {
322 localDirectory.allocate(addr);
324 localDirectory[addr].Sharers.clear();
325 localDirectory[addr].OwnerValid := true;
326 localDirectory[addr].Owner := exc_id;
330 void removeAllLocalSharersFromDir(Entry cache_entry, Address addr) {
331 if (is_valid(cache_entry)) {
332 assert (localDirectory.isTagPresent(addr) == false);
333 cache_entry.Sharers.clear();
334 cache_entry.OwnerValid := false;
337 localDirectory[addr].Sharers.clear();
338 localDirectory[addr].OwnerValid := false;
342 void removeSharerFromDir(Entry cache_entry, Address addr, MachineID sender) {
343 if (is_valid(cache_entry)) {
344 assert (localDirectory.isTagPresent(addr) == false);
345 cache_entry.Sharers.remove(sender);
348 localDirectory[addr].Sharers.remove(sender);
352 void removeOwnerFromDir(Entry cache_entry, Address addr, MachineID sender) {
353 if (is_valid(cache_entry)) {
354 assert (localDirectory.isTagPresent(addr) == false);
355 cache_entry.OwnerValid := false;
358 localDirectory[addr].OwnerValid := false;
362 bool isLocalSharer(Entry cache_entry, Address addr, MachineID shar_id) {
363 if (is_valid(cache_entry)) {
364 assert (localDirectory.isTagPresent(addr) == false);
365 return cache_entry.Sharers.isElement(shar_id);
368 return localDirectory[addr].Sharers.isElement(shar_id);
372 NetDest getLocalSharers(Entry cache_entry, Address addr) {
373 if (is_valid(cache_entry)) {
374 assert (localDirectory.isTagPresent(addr) == false);
375 return cache_entry.Sharers;
378 return localDirectory[addr].Sharers;
382 MachineID getLocalOwner(Entry cache_entry, Address addr) {
383 if (is_valid(cache_entry)) {
384 assert (localDirectory.isTagPresent(addr) == false);
385 return cache_entry.Owner;
388 return localDirectory[addr].Owner;
392 int countLocalSharers(Entry cache_entry, Address addr) {
393 if (is_valid(cache_entry)) {
394 assert (localDirectory.isTagPresent(addr) == false);
395 return cache_entry.Sharers.count();
398 return localDirectory[addr].Sharers.count();
402 bool isLocalOwnerValid(Entry cache_entry, Address addr) {
403 if (is_valid(cache_entry)) {
404 assert (localDirectory.isTagPresent(addr) == false);
405 return cache_entry.OwnerValid;
408 return localDirectory[addr].OwnerValid;
412 int countLocalSharersExceptRequestor(Entry cache_entry, Address addr, MachineID requestor) {
413 if (is_valid(cache_entry)) {
414 assert (localDirectory.isTagPresent(addr) == false);
415 if (cache_entry.Sharers.isElement(requestor)) {
416 return ( cache_entry.Sharers.count() - 1 );
419 return cache_entry.Sharers.count();
423 if (localDirectory[addr].Sharers.isElement(requestor)) {
424 return ( localDirectory[addr].Sharers.count() - 1 );
427 return localDirectory[addr].Sharers.count();
432 State getState(TBE tbe, Entry cache_entry, Address addr) {
436 } else if (is_valid(cache_entry)) {
437 return cache_entry.CacheState;
438 } else if (isDirTagPresent(addr)) {
439 return localDirectory[addr].DirState;
445 std::string getCoherenceRequestTypeStr(CoherenceRequestType type) {
446 return CoherenceRequestType_to_string(type);
449 void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
450 assert((localDirectory.isTagPresent(addr) && L2cacheMemory.isTagPresent(addr)) == false);
453 tbe.TBEState := state;
457 (state == State:M) ||
458 (state == State:O) ||
459 (state == State:S) ||
460 (state == State:OLS) ||
461 (state == State:SLS) ||
462 (state == State:OLSX) ||
465 assert(is_valid(cache_entry));
468 (state == State:ILS) ||
469 (state == State:ILX) ||
470 (state == State:ILO) ||
471 (state == State:ILOX) ||
472 (state == State:ILOS) ||
473 (state == State:ILOSX)
475 // assert(isCacheTagPresent(addr) == false);
478 if (is_valid(cache_entry)) {
479 if ( ((cache_entry.CacheState != State:M) && (state == State:M)) ||
480 ((cache_entry.CacheState != State:S) && (state == State:S)) ||
481 ((cache_entry.CacheState != State:O) && (state == State:O)) ) {
482 cache_entry.CacheState := state;
483 // disable Coherence Checker for now
484 // sequencer.checkCoherence(addr);
487 cache_entry.CacheState := state;
491 cache_entry.changePermission(AccessPermission:Read_Only);
493 else if (localDirectory.isTagPresent(addr)) {
494 localDirectory[addr].DirState := state;
498 MessageBuffer triggerQueue, ordered="true";
500 out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache);
501 out_port(localRequestNetwork_out, RequestMsg, L1RequestFromL2Cache);
502 out_port(responseNetwork_out, ResponseMsg, responseFromL2Cache);
504 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
510 in_port(triggerQueue_in, TriggerMsg, triggerQueue) {
511 if (triggerQueue_in.isReady()) {
512 peek(triggerQueue_in, TriggerMsg) {
513 if (in_msg.Type == TriggerType:ALL_ACKS) {
514 trigger(Event:All_Acks, in_msg.Address,
515 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
517 error("Unexpected message");
525 in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache) {
526 if (requestNetwork_in.isReady()) {
527 peek(requestNetwork_in, RequestMsg) {
528 if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
529 if (in_msg.Requestor == machineID) {
530 trigger(Event:Own_GETX, in_msg.Address,
531 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
533 trigger(Event:Fwd_GETX, in_msg.Address,
534 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
536 } else if (in_msg.Type == CoherenceRequestType:GETS) {
537 trigger(Event:Fwd_GETS, in_msg.Address,
538 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
539 } else if(in_msg.Type == CoherenceRequestType:DMA_READ) {
540 trigger(Event:Fwd_DMA, in_msg.Address,
541 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
542 } else if (in_msg.Type == CoherenceRequestType:INV) {
543 trigger(Event:Inv, in_msg.Address,
544 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
545 } else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
546 trigger(Event:Writeback_Ack, in_msg.Address,
547 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
548 } else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
549 trigger(Event:Writeback_Nack, in_msg.Address,
550 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
552 error("Unexpected message");
558 in_port(L1requestNetwork_in, RequestMsg, L1RequestToL2Cache) {
559 if (L1requestNetwork_in.isReady()) {
560 peek(L1requestNetwork_in, RequestMsg) {
561 assert(in_msg.Destination.isElement(machineID));
562 if (in_msg.Type == CoherenceRequestType:GETX) {
563 trigger(Event:L1_GETX, in_msg.Address,
564 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
565 } else if (in_msg.Type == CoherenceRequestType:GETS) {
566 trigger(Event:L1_GETS, in_msg.Address,
567 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
568 } else if (in_msg.Type == CoherenceRequestType:PUTO) {
569 trigger(Event:L1_PUTO, in_msg.Address,
570 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
571 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
572 trigger(Event:L1_PUTX, in_msg.Address,
573 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
574 } else if (in_msg.Type == CoherenceRequestType:PUTS) {
575 Entry cache_entry := getCacheEntry(in_msg.Address);
576 if (isOnlySharer(cache_entry, in_msg.Address, in_msg.Requestor)) {
577 trigger(Event:L1_PUTS_only, in_msg.Address,
578 cache_entry, TBEs[in_msg.Address]);
581 trigger(Event:L1_PUTS, in_msg.Address,
582 cache_entry, TBEs[in_msg.Address]);
585 error("Unexpected message");
593 in_port(responseNetwork_in, ResponseMsg, responseToL2Cache) {
594 if (responseNetwork_in.isReady()) {
595 peek(responseNetwork_in, ResponseMsg) {
596 assert(in_msg.Destination.isElement(machineID));
597 if (in_msg.Type == CoherenceResponseType:ACK) {
598 if (in_msg.SenderMachine == MachineType:L2Cache) {
599 trigger(Event:ExtAck, in_msg.Address,
600 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
603 trigger(Event:IntAck, in_msg.Address,
604 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
606 } else if (in_msg.Type == CoherenceResponseType:DATA) {
607 trigger(Event:Data, in_msg.Address,
608 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
609 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
610 trigger(Event:Data_Exclusive, in_msg.Address,
611 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
612 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
613 trigger(Event:Unblock, in_msg.Address,
614 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
615 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
616 trigger(Event:Exclusive_Unblock, in_msg.Address,
617 getCacheEntry(in_msg.Address), TBEs[in_msg.Address]);
618 } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) {
619 Entry cache_entry := getCacheEntry(in_msg.Address);
620 if (is_invalid(cache_entry) &&
621 L2cacheMemory.cacheAvail(in_msg.Address) == false) {
622 trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address),
623 getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address)),
624 TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]);
627 trigger(Event:L1_WBDIRTYDATA, in_msg.Address,
628 cache_entry, TBEs[in_msg.Address]);
630 } else if (in_msg.Type == CoherenceResponseType:WRITEBACK_CLEAN_DATA) {
631 Entry cache_entry := getCacheEntry(in_msg.Address);
632 if (is_invalid(cache_entry) &&
633 L2cacheMemory.cacheAvail(in_msg.Address) == false) {
634 trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address),
635 getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address)),
636 TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]);
639 trigger(Event:L1_WBCLEANDATA, in_msg.Address,
640 cache_entry, TBEs[in_msg.Address]);
643 error("Unexpected message");
652 action(a_issueGETS, "a", desc="issue local request globally") {
653 peek(L1requestNetwork_in, RequestMsg) {
654 enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
655 out_msg.Address := address;
656 out_msg.Type := CoherenceRequestType:GETS;
657 out_msg.RequestorMachine := MachineType:L2Cache;
658 out_msg.Requestor := machineID;
659 out_msg.Destination.add(map_Address_to_Directory(address));
660 out_msg.MessageSize := MessageSizeType:Request_Control;
665 action(a_issueGETX, "\a", desc="issue local request globally") {
666 peek(L1requestNetwork_in, RequestMsg) {
667 enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
668 out_msg.Address := address;
669 out_msg.Type := CoherenceRequestType:GETX;
670 out_msg.RequestorMachine := MachineType:L2Cache;
671 out_msg.Requestor := machineID;
672 out_msg.Destination.add(map_Address_to_Directory(address));
673 out_msg.MessageSize := MessageSizeType:Request_Control;
678 action(b_issuePUTX, "b", desc="Issue PUTX") {
679 enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
680 out_msg.Address := address;
681 out_msg.Type := CoherenceRequestType:PUTX;
682 out_msg.RequestorMachine := MachineType:L2Cache;
683 out_msg.Requestor := machineID;
684 out_msg.Destination.add(map_Address_to_Directory(address));
685 out_msg.MessageSize := MessageSizeType:Writeback_Control;
689 action(b_issuePUTO, "\b", desc="Issue PUTO") {
690 enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
691 out_msg.Address := address;
692 out_msg.Type := CoherenceRequestType:PUTO;
693 out_msg.Requestor := machineID;
694 out_msg.RequestorMachine := MachineType:L2Cache;
695 out_msg.Destination.add(map_Address_to_Directory(address));
696 out_msg.MessageSize := MessageSizeType:Writeback_Control;
700 /* PUTO, but local sharers exist */
701 action(b_issuePUTO_ls, "\bb", desc="Issue PUTO") {
702 enqueue(globalRequestNetwork_out, RequestMsg, latency=request_latency) {
703 out_msg.Address := address;
704 out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
705 out_msg.Requestor := machineID;
706 out_msg.RequestorMachine := MachineType:L2Cache;
707 out_msg.Destination.add(map_Address_to_Directory(address));
708 out_msg.MessageSize := MessageSizeType:Writeback_Control;
712 action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") {
713 assert(is_valid(tbe));
714 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
715 out_msg.Address := address;
716 out_msg.Type := CoherenceResponseType:DATA;
717 out_msg.Sender := machineID;
718 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
719 out_msg.DataBlk := tbe.DataBlk;
720 // out_msg.Dirty := tbe.Dirty;
721 // shared data should be clean
722 out_msg.Dirty := false;
723 out_msg.MessageSize := MessageSizeType:Response_Data;
725 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
726 address, tbe.DataBlk);
729 action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") {
730 assert(is_valid(tbe));
731 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
732 out_msg.Address := address;
733 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
734 out_msg.Sender := machineID;
735 out_msg.SenderMachine := MachineType:L2Cache;
736 out_msg.Destination.add(tbe.L1_GetX_ID);
737 out_msg.DataBlk := tbe.DataBlk;
738 out_msg.Dirty := tbe.Dirty;
739 out_msg.Acks := tbe.Local_GETX_IntAcks;
740 out_msg.MessageSize := MessageSizeType:Response_Data;
742 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
743 address, tbe.DataBlk);
746 action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") {
747 assert(is_valid(tbe));
748 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
749 out_msg.Address := address;
750 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
751 out_msg.Sender := machineID;
752 out_msg.SenderMachine := MachineType:L2Cache;
753 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
754 out_msg.DataBlk := tbe.DataBlk;
755 out_msg.Dirty := tbe.Dirty;
756 out_msg.MessageSize := MessageSizeType:Response_Data;
760 action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") {
761 assert(is_valid(tbe));
762 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
763 out_msg.Address := address;
764 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
765 out_msg.Sender := machineID;
766 out_msg.SenderMachine := MachineType:L2Cache;
767 out_msg.Destination.add(tbe.Fwd_GetX_ID);
768 out_msg.DataBlk := tbe.DataBlk;
769 out_msg.Dirty := tbe.Dirty;
770 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
771 out_msg.MessageSize := MessageSizeType:Response_Data;
775 action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") {
776 assert(is_valid(tbe));
777 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
778 out_msg.Address := address;
779 out_msg.Type := CoherenceResponseType:DATA;
780 out_msg.Sender := machineID;
781 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
782 out_msg.DataBlk := tbe.DataBlk;
783 // out_msg.Dirty := tbe.Dirty;
784 // shared data should be clean
785 out_msg.Dirty := false;
786 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
787 out_msg.MessageSize := MessageSizeType:Response_Data;
789 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
790 address, tbe.DataBlk);
793 action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") {
794 assert(is_valid(tbe));
795 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
796 out_msg.Address := address;
797 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
798 out_msg.Sender := machineID;
799 out_msg.SenderMachine := MachineType:L2Cache;
800 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
801 out_msg.DataBlk := tbe.DataBlk;
802 out_msg.Dirty := tbe.Dirty;
803 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
804 out_msg.MessageSize := MessageSizeType:Response_Data;
806 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
807 address, tbe.DataBlk);
810 action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") {
811 assert(is_valid(cache_entry));
812 peek(L1requestNetwork_in, RequestMsg) {
813 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
814 out_msg.Address := address;
815 out_msg.Type := CoherenceResponseType:DATA;
816 out_msg.Sender := machineID;
817 out_msg.Destination.add(in_msg.Requestor);
818 out_msg.DataBlk := cache_entry.DataBlk;
819 // out_msg.Dirty := cache_entry.Dirty;
820 // shared data should be clean
821 out_msg.Dirty := false;
822 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
825 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
826 address, cache_entry.DataBlk);
829 action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") {
830 assert(is_valid(cache_entry));
831 peek(L1requestNetwork_in, RequestMsg) {
832 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
833 assert(is_valid(tbe));
834 out_msg.Address := address;
835 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
836 out_msg.Sender := machineID;
837 out_msg.SenderMachine := MachineType:L2Cache;
838 out_msg.Destination.add(in_msg.Requestor);
839 out_msg.DataBlk := cache_entry.DataBlk;
840 out_msg.Dirty := cache_entry.Dirty;
841 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
842 out_msg.Acks := tbe.Local_GETX_IntAcks;
845 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
846 address, cache_entry.DataBlk);
849 action(dd_sendDataToFwdGETX, "dd", desc="send data") {
850 assert(is_valid(cache_entry));
851 peek(requestNetwork_in, RequestMsg) {
852 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
853 out_msg.Address := address;
854 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
855 out_msg.Sender := machineID;
856 out_msg.SenderMachine := MachineType:L2Cache;
857 out_msg.Destination.add(in_msg.Requestor);
858 out_msg.DataBlk := cache_entry.DataBlk;
859 out_msg.Dirty := cache_entry.Dirty;
860 out_msg.MessageSize := MessageSizeType:Response_Data;
861 out_msg.Acks := in_msg.Acks;
864 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
865 address, cache_entry.DataBlk);
869 action(dd_sendDataToFwdGETS, "\dd", desc="send data") {
870 assert(is_valid(cache_entry));
871 peek(requestNetwork_in, RequestMsg) {
872 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
873 out_msg.Address := address;
874 out_msg.Type := CoherenceResponseType:DATA;
875 out_msg.Sender := machineID;
876 out_msg.Destination.add(in_msg.Requestor);
877 out_msg.DataBlk := cache_entry.DataBlk;
878 // out_msg.Dirty := cache_entry.Dirty;
879 // shared data should be clean
880 out_msg.Dirty := false;
881 out_msg.MessageSize := MessageSizeType:Response_Data;
884 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
885 address, cache_entry.DataBlk);
888 action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") {
889 assert(is_valid(cache_entry));
890 peek(requestNetwork_in, RequestMsg) {
891 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
892 out_msg.Address := address;
893 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
894 out_msg.Sender := machineID;
895 out_msg.Destination.add(in_msg.Requestor);
896 out_msg.DataBlk := cache_entry.DataBlk;
897 out_msg.Dirty := cache_entry.Dirty;
898 out_msg.MessageSize := MessageSizeType:Response_Data;
903 action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") {
904 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
905 assert(is_valid(tbe));
906 out_msg.Address := address;
907 out_msg.Type := CoherenceResponseType:ACK;
908 out_msg.Sender := machineID;
909 out_msg.SenderMachine := MachineType:L2Cache;
911 out_msg.Destination.add( tbe.Fwd_GetX_ID);
912 out_msg.Acks := 0 - 1;
913 out_msg.MessageSize := MessageSizeType:Response_Control;
917 action(e_sendAckToL1Requestor, "\e", desc="Send ack with the tokens we've collected thus far.") {
918 peek(L1requestNetwork_in, RequestMsg) {
919 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
920 out_msg.Address := address;
921 out_msg.Type := CoherenceResponseType:ACK;
922 out_msg.Sender := machineID;
923 out_msg.SenderMachine := MachineType:L2Cache;
924 out_msg.Destination.add(in_msg.Requestor);
925 out_msg.Acks := 0 - 1;
926 out_msg.MessageSize := MessageSizeType:Response_Control;
931 action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") {
932 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
933 assert(is_valid(tbe));
934 out_msg.Address := address;
935 out_msg.Type := CoherenceResponseType:ACK;
936 out_msg.Sender := machineID;
937 out_msg.SenderMachine := MachineType:L2Cache;
938 out_msg.Destination.add(tbe.L1_GetX_ID);
939 out_msg.Acks := 0 - 1;
940 out_msg.MessageSize := MessageSizeType:Response_Control;
944 action(ee_sendLocalInv, "\ee", desc="Send local invalidates") {
945 assert(is_valid(tbe));
946 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
947 DPRINTF(RubySlicc, "Address: %s, Local Sharers: %s, Pending Acks: %d\n",
948 address, getLocalSharers(cache_entry, address),
949 tbe.NumIntPendingAcks);
950 if (isLocalOwnerValid(cache_entry, address)) {
951 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
952 DPRINTF(RubySlicc, "%s\n", getLocalOwner(cache_entry, address));
955 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
956 out_msg.Address := address;
957 out_msg.Type := CoherenceRequestType:INV;
958 out_msg.Requestor := machineID;
959 out_msg.RequestorMachine := MachineType:L2Cache;
960 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
961 if (isLocalOwnerValid(cache_entry, address))
963 out_msg.Destination.add(getLocalOwner(cache_entry, address));
965 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
969 action(ee_sendLocalInvSharersOnly, "\eee", desc="Send local invalidates to sharers if they exist") {
971 // assert(countLocalSharers(address) > 0);
972 assert(is_valid(tbe));
973 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
975 if (countLocalSharers(cache_entry, address) > 0) {
976 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
977 out_msg.Address := address;
978 out_msg.Type := CoherenceRequestType:INV;
979 out_msg.Requestor := machineID;
980 out_msg.RequestorMachine := MachineType:L2Cache;
981 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
982 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
987 action(ee_addLocalIntAck, "e\ee", desc="add a local ack to wait for") {
988 assert(is_valid(tbe));
989 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
992 action(ee_issueLocalInvExceptL1Requestor, "\eeee", desc="Send local invalidates to sharers if they exist") {
993 peek(L1requestNetwork_in, RequestMsg) {
995 // assert(countLocalSharers(address) > 0);
996 if (countLocalSharers(cache_entry, address) == 0) {
997 tbe.NumIntPendingAcks := 0;
1001 if (isLocalSharer(cache_entry, address, in_msg.Requestor)) {
1002 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1005 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1008 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1009 out_msg.Address := address;
1010 out_msg.Type := CoherenceRequestType:INV;
1011 out_msg.Requestor := in_msg.Requestor;
1012 out_msg.RequestorMachine := MachineType:L1Cache;
1013 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1014 out_msg.Destination.remove(in_msg.Requestor);
1015 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1021 action(ee_issueLocalInvExceptL1RequestorInTBE, "\eeeeee", desc="Send local invalidates to sharers if they exist") {
1022 assert(is_valid(tbe));
1023 if (countLocalSharers(cache_entry, address) == 0) {
1024 tbe.NumIntPendingAcks := 0;
1027 if (isLocalSharer(cache_entry, address, tbe.L1_GetX_ID)) {
1028 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1031 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1034 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1035 out_msg.Address := address;
1036 out_msg.Type := CoherenceRequestType:INV;
1037 out_msg.Requestor := tbe.L1_GetX_ID;
1038 out_msg.RequestorMachine := MachineType:L1Cache;
1039 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1040 out_msg.Destination.remove(tbe.L1_GetX_ID);
1041 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1046 action(f_sendUnblock, "f", desc="Send unblock to global directory") {
1047 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
1048 out_msg.Address := address;
1049 out_msg.Type := CoherenceResponseType:UNBLOCK;
1050 out_msg.Destination.add(map_Address_to_Directory(address));
1051 out_msg.Sender := machineID;
1052 out_msg.SenderMachine := MachineType:L2Cache;
1053 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1058 action(f_sendExclusiveUnblock, "\f", desc="Send unblock to global directory") {
1059 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
1060 out_msg.Address := address;
1061 out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
1062 out_msg.Destination.add(map_Address_to_Directory(address));
1063 out_msg.Sender := machineID;
1064 out_msg.SenderMachine := MachineType:L2Cache;
1065 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1070 action(g_recordLocalSharer, "g", desc="Record new local sharer from unblock message") {
1071 peek(responseNetwork_in, ResponseMsg) {
1072 recordLocalSharerInDir(cache_entry, in_msg.Address, in_msg.Sender);
1076 action(g_recordLocalExclusive, "\g", desc="Record new local exclusive sharer from unblock message") {
1077 peek(responseNetwork_in, ResponseMsg) {
1078 recordNewLocalExclusiveInDir(cache_entry, address, in_msg.Sender);
1082 action(gg_clearLocalSharers, "gg", desc="Clear local sharers") {
1083 removeAllLocalSharersFromDir(cache_entry, address);
1086 action(gg_clearSharerFromL1Response, "\gg", desc="Clear sharer from L1 response queue") {
1087 peek(responseNetwork_in, ResponseMsg) {
1088 removeSharerFromDir(cache_entry, in_msg.Address, in_msg.Sender);
1092 action(gg_clearOwnerFromL1Response, "g\g", desc="Clear sharer from L1 response queue") {
1093 peek(responseNetwork_in, ResponseMsg) {
1094 removeOwnerFromDir(cache_entry, in_msg.Address, in_msg.Sender);
1098 action(h_countLocalSharersExceptRequestor, "h", desc="counts number of acks needed for L1 GETX") {
1099 peek(L1requestNetwork_in, RequestMsg) {
1100 assert(is_valid(tbe));
1101 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, in_msg.Requestor);
1105 action(h_clearIntAcks, "\h", desc="clear IntAcks") {
1106 assert(is_valid(tbe));
1107 tbe.Local_GETX_IntAcks := 0;
1110 action(hh_countLocalSharersExceptL1GETXRequestorInTBE, "hh", desc="counts number of acks needed for L1 GETX") {
1111 assert(is_valid(tbe));
1112 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, tbe.L1_GetX_ID);
1115 action(i_copyDataToTBE, "\i", desc="Copy data from response queue to TBE") {
1116 peek(responseNetwork_in, ResponseMsg) {
1117 assert(is_valid(tbe));
1118 tbe.DataBlk := in_msg.DataBlk;
1119 tbe.Dirty := in_msg.Dirty;
1123 action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") {
1124 check_allocate(TBEs);
1125 TBEs.allocate(address);
1126 set_tbe(TBEs[address]);
1127 if(is_valid(cache_entry)) {
1128 tbe.DataBlk := cache_entry.DataBlk;
1129 tbe.Dirty := cache_entry.Dirty;
1131 tbe.NumIntPendingAcks := 0; // default value
1132 tbe.NumExtPendingAcks := 0; // default value
1133 tbe.Fwd_GetS_IDs.clear();
1134 tbe.L1_GetS_IDs.clear();
1139 action(j_forwardGlobalRequestToLocalOwner, "j", desc="Forward external request to local owner") {
1140 peek(requestNetwork_in, RequestMsg) {
1141 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1142 out_msg.Address := in_msg.Address;
1143 out_msg.Type := in_msg.Type;
1144 out_msg.Requestor := machineID;
1145 out_msg.RequestorMachine := MachineType:L2Cache;
1146 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address));
1147 out_msg.Type := in_msg.Type;
1148 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1149 out_msg.Acks := 0 - 1;
1155 action(k_forwardLocalGETSToLocalSharer, "k", desc="Forward local request to local sharer/owner") {
1156 peek(L1requestNetwork_in, RequestMsg) {
1157 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1158 out_msg.Address := in_msg.Address;
1159 out_msg.Type := CoherenceRequestType:GETS;
1160 out_msg.Requestor := in_msg.Requestor;
1161 out_msg.RequestorMachine := MachineType:L1Cache;
1162 // should randomize this so one node doesn't get abused more than others
1163 out_msg.Destination.add(localDirectory[in_msg.Address].Sharers.smallestElement(MachineType:L1Cache));
1164 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1169 action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") {
1170 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1171 assert(is_valid(tbe));
1172 out_msg.Address := address;
1173 out_msg.Type := CoherenceRequestType:GETX;
1174 out_msg.Requestor := tbe.L1_GetX_ID;
1175 out_msg.RequestorMachine := MachineType:L1Cache;
1176 out_msg.Destination.add(localDirectory[address].Owner);
1177 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1178 out_msg.Acks := 1 + tbe.Local_GETX_IntAcks;
1182 // same as previous except that it assumes to TBE is present to get number of acks
1183 action(kk_forwardLocalGETXToLocalExclusive, "kk", desc="Forward local request to local owner") {
1184 peek(L1requestNetwork_in, RequestMsg) {
1185 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1186 out_msg.Address := in_msg.Address;
1187 out_msg.Type := CoherenceRequestType:GETX;
1188 out_msg.Requestor := in_msg.Requestor;
1189 out_msg.RequestorMachine := MachineType:L1Cache;
1190 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address));
1191 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1197 action(kk_forwardLocalGETSToLocalOwner, "\kk", desc="Forward local request to local owner") {
1198 peek(L1requestNetwork_in, RequestMsg) {
1199 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1200 out_msg.Address := in_msg.Address;
1201 out_msg.Type := CoherenceRequestType:GETS;
1202 out_msg.Requestor := in_msg.Requestor;
1203 out_msg.RequestorMachine := MachineType:L1Cache;
1204 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.Address));
1205 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1211 action(l_writebackAckNeedData, "l", desc="Send writeback ack to L1 requesting data") {
1212 peek(L1requestNetwork_in, RequestMsg) {
1213 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1214 out_msg.Address := in_msg.Address;
1215 // out_msg.Type := CoherenceResponseType:WRITEBACK_SEND_DATA;
1216 out_msg.Type := CoherenceRequestType:WB_ACK_DATA;
1217 out_msg.Requestor := machineID;
1218 out_msg.RequestorMachine := MachineType:L2Cache;
1219 out_msg.Destination.add(in_msg.Requestor);
1220 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1225 action(l_writebackAckDropData, "\l", desc="Send writeback ack to L1 indicating to drop data") {
1226 peek(L1requestNetwork_in, RequestMsg) {
1227 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1228 out_msg.Address := in_msg.Address;
1229 // out_msg.Type := CoherenceResponseType:WRITEBACK_ACK;
1230 out_msg.Type := CoherenceRequestType:WB_ACK;
1231 out_msg.Requestor := machineID;
1232 out_msg.RequestorMachine := MachineType:L2Cache;
1233 out_msg.Destination.add(in_msg.Requestor);
1234 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1239 action(ll_writebackNack, "\ll", desc="Send writeback nack to L1") {
1240 peek(L1requestNetwork_in, RequestMsg) {
1241 enqueue( localRequestNetwork_out, RequestMsg, latency=response_latency ) {
1242 out_msg.Address := in_msg.Address;
1243 out_msg.Type := CoherenceRequestType:WB_NACK;
1244 out_msg.Requestor := machineID;
1245 out_msg.RequestorMachine := MachineType:L2Cache;
1246 out_msg.Destination.add(in_msg.Requestor);
1247 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1252 action(m_popRequestQueue, "m", desc="Pop request queue.") {
1253 requestNetwork_in.dequeue();
1256 action(m_decrementNumberOfMessagesInt, "\m", desc="Decrement the number of messages for which we're waiting") {
1257 peek(responseNetwork_in, ResponseMsg) {
1258 assert(is_valid(tbe));
1259 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + in_msg.Acks;
1263 action(m_decrementNumberOfMessagesExt, "\mmm", desc="Decrement the number of messages for which we're waiting") {
1264 peek(responseNetwork_in, ResponseMsg) {
1265 assert(is_valid(tbe));
1266 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1270 action(mm_decrementNumberOfMessagesExt, "\mm", desc="Decrement the number of messages for which we're waiting") {
1271 peek(requestNetwork_in, RequestMsg) {
1272 assert(is_valid(tbe));
1273 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1277 action(n_popResponseQueue, "n", desc="Pop response queue") {
1278 responseNetwork_in.dequeue();
1281 action(n_popTriggerQueue, "\n", desc="Pop trigger queue.") {
1282 triggerQueue_in.dequeue();
1285 action(o_popL1RequestQueue, "o", desc="Pop L1 request queue.") {
1286 L1requestNetwork_in.dequeue();
1290 action(o_checkForIntCompletion, "\o", desc="Check if we have received all the messages required for completion") {
1291 assert(is_valid(tbe));
1292 if (tbe.NumIntPendingAcks == 0) {
1293 enqueue(triggerQueue_out, TriggerMsg) {
1294 out_msg.Address := address;
1295 out_msg.Type := TriggerType:ALL_ACKS;
1300 action(o_checkForExtCompletion, "\oo", desc="Check if we have received all the messages required for completion") {
1301 assert(is_valid(tbe));
1302 if (tbe.NumExtPendingAcks == 0) {
1303 enqueue(triggerQueue_out, TriggerMsg) {
1304 out_msg.Address := address;
1305 out_msg.Type := TriggerType:ALL_ACKS;
1311 action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") {
1312 enqueue(responseNetwork_out, ResponseMsg, latency=response_latency) {
1313 assert(is_valid(tbe));
1314 out_msg.Address := address;
1315 out_msg.Sender := machineID;
1316 out_msg.SenderMachine := MachineType:L2Cache;
1317 out_msg.Destination.add(map_Address_to_Directory(address));
1318 out_msg.Dirty := tbe.Dirty;
1320 out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA;
1321 out_msg.DataBlk := tbe.DataBlk;
1322 out_msg.MessageSize := MessageSizeType:Writeback_Data;
1324 out_msg.Type := CoherenceResponseType:WRITEBACK_CLEAN_ACK;
1325 // NOTE: in a real system this would not send data. We send
1326 // data here only so we can check it at the memory
1327 out_msg.DataBlk := tbe.DataBlk;
1328 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1333 action( r_setMRU, "\rrr", desc="manually set the MRU bit for cache line" ) {
1334 if(is_valid(cache_entry)) {
1335 L2cacheMemory.setMRU(address);
1339 action( s_recordGetXL1ID, "ss", desc="record local GETX requestor") {
1340 peek(L1requestNetwork_in, RequestMsg) {
1341 assert(is_valid(tbe));
1342 tbe.L1_GetX_ID := in_msg.Requestor;
1346 action(s_deallocateTBE, "s", desc="Deallocate external TBE") {
1347 TBEs.deallocate(address);
1351 action( s_recordGetSL1ID, "\ss", desc="record local GETS requestor") {
1352 peek(L1requestNetwork_in, RequestMsg) {
1353 assert(is_valid(tbe));
1354 tbe.L1_GetS_IDs.add(in_msg.Requestor);
1358 action(t_recordFwdXID, "t", desc="record global GETX requestor") {
1359 peek(requestNetwork_in, RequestMsg) {
1360 assert(is_valid(tbe));
1361 tbe.Fwd_GetX_ID := in_msg.Requestor;
1362 tbe.Fwd_GETX_ExtAcks := in_msg.Acks;
1366 action(t_recordFwdSID, "\t", desc="record global GETS requestor") {
1367 peek(requestNetwork_in, RequestMsg) {
1368 assert(is_valid(tbe));
1369 tbe.Fwd_GetS_IDs.clear();
1370 tbe.Fwd_GetS_IDs.add(in_msg.Requestor);
1375 action(u_writeDataToCache, "u", desc="Write data to cache") {
1376 peek(responseNetwork_in, ResponseMsg) {
1377 assert(is_valid(cache_entry));
1378 cache_entry.DataBlk := in_msg.DataBlk;
1379 if ((cache_entry.Dirty == false) && in_msg.Dirty) {
1380 cache_entry.Dirty := in_msg.Dirty;
1385 action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") {
1386 set_cache_entry(L2cacheMemory.allocate(address, new Entry));
1389 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
1390 L2cacheMemory.deallocate(address);
1391 unset_cache_entry();
1395 action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") {
1396 peek(responseNetwork_in, ResponseMsg) {
1397 assert(is_valid(cache_entry));
1398 assert(cache_entry.DataBlk == in_msg.DataBlk);
1402 action(uu_profileMiss, "\u", desc="Profile the demand miss") {
1403 peek(L1requestNetwork_in, RequestMsg) {
1404 // AccessModeType not implemented
1405 // profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
1409 action(y_copyCacheStateToDir, "y", desc="Copy cache state to directory state") {
1410 copyCacheStateToDir(cache_entry, address);
1413 action(y_copyDirToCacheAndRemove, "/y", desc="Copy dir state to cache and remove") {
1414 copyDirToCache(cache_entry, address);
1415 localDirectory.deallocate(address);
1418 action(z_stall, "z", desc="Stall") {
1421 action(zz_recycleL1RequestQueue, "zz", desc="Send the head of the mandatory queue to the back of the queue.") {
1422 peek(L1requestNetwork_in, RequestMsg) {
1423 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1425 L1requestNetwork_in.recycle();
1428 action(zz_recycleRequestQueue, "\zz", desc="Send the head of the mandatory queue to the back of the queue.") {
1429 peek(requestNetwork_in, RequestMsg) {
1430 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1432 requestNetwork_in.recycle();
1435 action(zz_recycleResponseQueue, "\z\z", desc="Send the head of the mandatory queue to the back of the queue.") {
1436 peek(responseNetwork_in, ResponseMsg) {
1437 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1439 responseNetwork_in.recycle();
1444 //*****************************************************
1446 //*****************************************************
1448 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}, {L1_PUTO, L1_PUTS, L1_PUTS_only, L1_PUTX}) {
1449 zz_recycleL1RequestQueue;
1452 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}, {L1_GETX, L1_GETS}) {
1453 zz_recycleL1RequestQueue;
1456 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}, L2_Replacement) {
1457 zz_recycleResponseQueue;
1460 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}, {Fwd_GETX, Fwd_GETS, Fwd_DMA}) {
1461 zz_recycleRequestQueue;
1464 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}, {Inv}) {
1465 zz_recycleRequestQueue;
1468 transition({IGM, IGS}, {Own_GETX}) {
1469 zz_recycleRequestQueue;
1472 // must happened because we forwarded GETX to local exclusive trying to do wb
1473 transition({I, M, O, ILS, ILOX, OLS, OLSX, SLS, S}, L1_PUTX) {
1475 o_popL1RequestQueue;
1478 transition({M}, {L1_PUTS, L1_PUTO} ) {
1480 o_popL1RequestQueue;
1483 transition({ILS, OLSX}, L1_PUTO){
1485 o_popL1RequestQueue;
1488 // happened if we forwarded GETS to exclusive who tried to do writeback
1489 // ?? should we just Nack these instead? Could be a bugs here
1490 transition(ILO, L1_PUTX, ILOW) {
1491 l_writebackAckNeedData;
1492 o_popL1RequestQueue;
1495 // this can happen if we forwarded a L1_GETX to exclusiver after it issued a PUTX
1496 transition(ILOS, L1_PUTX, ILOSW) {
1497 l_writebackAckNeedData;
1498 o_popL1RequestQueue;
1501 transition(ILOSX, L1_PUTX, ILOSXW) {
1502 l_writebackAckNeedData;
1503 o_popL1RequestQueue;
1506 // must happened because we got Inv when L1 attempted PUTS
1507 transition(I, L1_PUTS) {
1509 o_popL1RequestQueue;
1512 transition(I, L1_PUTO) {
1514 o_popL1RequestQueue;
1517 // FORWARDED REQUESTS
1519 transition({ILO, ILX, ILOX}, Fwd_GETS, IFGS) {
1522 j_forwardGlobalRequestToLocalOwner;
1526 transition({ILOS, ILOSX}, Fwd_GETS, ISFGS) {
1529 j_forwardGlobalRequestToLocalOwner;
1533 transition({ILOS, ILOSX}, Fwd_DMA) {
1536 j_forwardGlobalRequestToLocalOwner;
1540 transition({ILO, ILX, ILOX}, Fwd_DMA) {
1543 j_forwardGlobalRequestToLocalOwner;
1547 transition({ILOS, ILOSX, ILO, ILX, ILOX, ILXW}, Data) {
1549 c_sendDataFromTBEToFwdGETS;
1554 transition(IFGS, Data, ILO) {
1556 c_sendDataFromTBEToFwdGETS;
1561 transition(ISFGS, Data, ILOS) {
1563 c_sendDataFromTBEToFwdGETS;
1568 transition(IFGS, Data_Exclusive, I) {
1570 c_sendExclusiveDataFromTBEToFwdGETS;
1571 gg_clearLocalSharers;
1577 transition({ILX, ILO, ILOX}, Fwd_GETX, IFGX) {
1580 j_forwardGlobalRequestToLocalOwner;
1584 transition(IFGX, {Data_Exclusive, Data}, I) {
1586 c_sendDataFromTBEToFwdGETX;
1587 gg_clearLocalSharers;
1592 transition({ILOSX, ILOS}, Fwd_GETX, IFGXX) {
1595 j_forwardGlobalRequestToLocalOwner;
1596 ee_sendLocalInvSharersOnly;
1602 transition(IFGXX, IntAck) {
1603 m_decrementNumberOfMessagesInt;
1604 o_checkForIntCompletion;
1608 transition(IFGXX, Data_Exclusive) {
1610 m_decrementNumberOfMessagesInt;
1611 o_checkForIntCompletion;
1615 transition(IFGXX, All_Acks, I) {
1616 c_sendDataFromTBEToFwdGETX;
1617 gg_clearLocalSharers;
1623 // transition({O, OX}, Fwd_GETX, I) {
1624 transition(O, Fwd_GETX, I) {
1625 dd_sendDataToFwdGETX;
1626 y_copyCacheStateToDir;
1627 rr_deallocateL2CacheBlock;
1631 transition({O, OLS}, {Fwd_GETS, Fwd_DMA}) {
1632 dd_sendDataToFwdGETS;
1636 // transition({OLSX, OX}, Fwd_GETS, O) {
1637 transition(OLSX, Fwd_GETS, OLS) {
1638 dd_sendDataToFwdGETS;
1642 transition(OLSX, Fwd_DMA) {
1643 dd_sendDataToFwdGETS;
1647 transition(M, Fwd_GETX, I) {
1648 dd_sendDataToFwdGETX;
1649 rr_deallocateL2CacheBlock;
1653 // MAKE THIS THE SAME POLICY FOR NOW
1655 // transition(M, Fwd_GETS, O) {
1656 // dd_sendDataToFwdGETS;
1657 // m_popRequestQueue;
1660 transition(M, Fwd_GETS, I) {
1661 dd_sendExclusiveDataToFwdGETS;
1662 rr_deallocateL2CacheBlock;
1666 transition(M, Fwd_DMA) {
1667 dd_sendExclusiveDataToFwdGETS;
1671 transition({OLS, OLSX}, Fwd_GETX, OLSF) {
1678 transition(OLSF, IntAck) {
1679 m_decrementNumberOfMessagesInt;
1680 o_checkForIntCompletion;
1684 transition(OLSF, All_Acks, I) {
1685 c_sendDataFromTBEToFwdGETX;
1686 gg_clearLocalSharers;
1688 rr_deallocateL2CacheBlock;
1694 // INVALIDATIONS FROM GLOBAL DIRECTORY
1696 transition({IGM, IGS}, Inv) {
1702 transition({I,NP}, Inv) {
1710 // NEED INV for S state
1712 transition({ILS, ILO, ILX}, Inv, II) {
1716 gg_clearLocalSharers;
1720 transition(SLS, Inv, II) {
1724 rr_deallocateL2CacheBlock;
1728 transition(II, IntAck) {
1729 m_decrementNumberOfMessagesInt;
1730 o_checkForIntCompletion;
1734 transition(II, All_Acks, I) {
1740 transition(S, Inv, I) {
1745 rr_deallocateL2CacheBlock;
1750 // LOCAL REQUESTS SATISFIED LOCALLY
1752 transition(OLSX, L1_GETX, IFLOX) {
1755 // count number of INVs needed that doesn't include requestor
1756 h_countLocalSharersExceptRequestor;
1757 // issue INVs to everyone except requestor
1758 ee_issueLocalInvExceptL1Requestor;
1760 y_copyCacheStateToDir;
1762 rr_deallocateL2CacheBlock;
1764 o_popL1RequestQueue;
1767 transition(IFLOX, Exclusive_Unblock, ILX) {
1768 g_recordLocalExclusive;
1773 transition(OLSX, L1_GETS, OLSXS) {
1776 o_popL1RequestQueue;
1779 transition(OLSXS, Unblock, OLSX) {
1780 g_recordLocalSharer;
1784 // after this, can't get Fwd_GETX
1785 transition(IGMO, Own_GETX) {
1786 mm_decrementNumberOfMessagesExt;
1787 o_checkForExtCompletion;
1793 transition(ILX, L1_GETS, IFLOXX) {
1794 kk_forwardLocalGETSToLocalOwner;
1796 o_popL1RequestQueue;
1799 transition(ILOSX, L1_GETS, IFLOSX) {
1800 kk_forwardLocalGETSToLocalOwner;
1802 o_popL1RequestQueue;
1805 transition({ILOS, ILO}, L1_GETS, IFLO) {
1806 kk_forwardLocalGETSToLocalOwner;
1808 o_popL1RequestQueue;
1811 transition(ILS, L1_GETS, IFLS) {
1812 k_forwardLocalGETSToLocalSharer;
1814 o_popL1RequestQueue;
1817 transition({ILX, ILOX}, L1_GETX, IFLOXX) {
1818 kk_forwardLocalGETXToLocalExclusive;
1819 e_sendAckToL1Requestor;
1821 o_popL1RequestQueue;
1824 transition(ILOX, L1_GETS, IFLOX) {
1825 kk_forwardLocalGETSToLocalOwner;
1827 o_popL1RequestQueue;
1830 transition(IFLOX, Unblock, ILOSX) {
1831 g_recordLocalSharer;
1835 transition(IFLS, Unblock, ILS) {
1836 g_recordLocalSharer;
1840 transition(IFLOXX, Unblock, ILOSX) {
1841 g_recordLocalSharer;
1845 transition(IFLOSX, Unblock, ILOSX) {
1846 g_recordLocalSharer;
1850 transition({IFLOSX, IFLOXX}, Exclusive_Unblock, ILX) {
1851 g_recordLocalExclusive;
1855 transition(IFLO, Unblock, ILOS) {
1856 g_recordLocalSharer;
1861 transition(ILOSX, L1_GETX, IFLXO) {
1864 h_countLocalSharersExceptRequestor;
1865 ee_issueLocalInvExceptL1Requestor;
1866 k_forwardLocalGETXToLocalOwner;
1867 e_sendAckToL1RequestorFromTBE;
1869 o_popL1RequestQueue;
1872 transition(IFLXO, Exclusive_Unblock, ILX) {
1873 g_recordLocalExclusive;
1878 // LOCAL REQUESTS THAT MUST ISSUE
1880 transition(NP, {L1_PUTS, L1_PUTX, L1_PUTO}) {
1882 o_popL1RequestQueue;
1885 transition({NP, I}, L1_GETS, IGS) {
1890 o_popL1RequestQueue;
1893 transition({NP, I}, L1_GETX, IGM) {
1898 o_popL1RequestQueue;
1901 transition(S, L1_GETX, IGM) {
1905 y_copyCacheStateToDir;
1907 rr_deallocateL2CacheBlock;
1909 o_popL1RequestQueue;
1912 transition(ILS, L1_GETX, IGMLS) {
1916 // count number of INVs (just sharers?) needed that doesn't include requestor
1917 h_countLocalSharersExceptRequestor;
1919 o_popL1RequestQueue;
1922 transition(IGMLS, Inv) {
1928 transition(IGMLS, IntAck) {
1929 m_decrementNumberOfMessagesInt;
1930 o_checkForIntCompletion;
1934 transition(IGMLS, All_Acks, IGM) {
1935 gg_clearLocalSharers;
1941 // transition(IGMLS, ExtAck, IGMO) {
1942 transition(IGMLS, ExtAck) {
1943 m_decrementNumberOfMessagesExt;
1944 o_checkForExtCompletion;
1948 transition(IGMLS, {Data, Data_Exclusive}, IGMO) {
1949 ee_issueLocalInvExceptL1RequestorInTBE;
1951 m_decrementNumberOfMessagesExt;
1952 o_checkForExtCompletion;
1957 transition(ILOS, L1_GETX, IGMIO) {
1962 o_popL1RequestQueue;
1965 // new exclusive happened while sharer attempted writeback
1966 transition(ILX, {L1_PUTS, L1_PUTS_only, L1_PUTO}) {
1968 o_popL1RequestQueue;
1971 transition(S, L1_PUTS) {
1973 o_popL1RequestQueue;
1976 transition(OLS, L1_GETX, OGMIO) {
1980 h_countLocalSharersExceptRequestor;
1981 // COPY DATA FROM CACHE TO TBE (happens during i_allocateTBE)
1982 y_copyCacheStateToDir;
1983 rr_deallocateL2CacheBlock;
1985 o_popL1RequestQueue;
1988 transition(OGMIO, {Fwd_GETS, Fwd_DMA}) {
1990 c_sendDataFromTBEToFwdGETS;
1994 transition(ILO, L1_GETX, IGMIO) {
1998 // the following, of course, returns 0 sharers but do anyways for consistency
1999 h_countLocalSharersExceptRequestor;
2001 o_popL1RequestQueue;
2004 transition({ILO, ILOX}, L1_PUTS) {
2006 o_popL1RequestQueue;
2009 transition(IGMIO, Fwd_GETX, IGMIOF) {
2011 j_forwardGlobalRequestToLocalOwner;
2012 ee_sendLocalInvSharersOnly;
2017 transition(IGMIO, Fwd_GETS, IGMIOFS) {
2019 j_forwardGlobalRequestToLocalOwner;
2023 transition(IGMIO, Fwd_DMA) {
2025 j_forwardGlobalRequestToLocalOwner;
2029 transition(IGMIOFS, Data, IGMIO) {
2031 c_sendDataFromTBEToFwdGETS;
2035 transition(OGMIO, Fwd_GETX, OGMIOF) {
2037 ee_sendLocalInvSharersOnly;
2041 transition(OGMIOF, IntAck) {
2042 m_decrementNumberOfMessagesInt;
2043 o_checkForIntCompletion;
2047 transition(OGMIOF, All_Acks, IGM) {
2048 gg_clearLocalSharers;
2049 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2050 c_sendDataFromTBEToFwdGETX;
2054 transition(IGMIOF, IntAck) {
2055 m_decrementNumberOfMessagesInt;
2056 o_checkForIntCompletion;
2060 transition(IGMIOF, Data_Exclusive) {
2062 m_decrementNumberOfMessagesInt;
2063 o_checkForIntCompletion;
2067 transition(IGMIOF, All_Acks, IGM) {
2068 gg_clearLocalSharers;
2069 c_sendDataFromTBEToFwdGETX;
2073 transition(IGMIO, All_Acks, IGMO) {
2074 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2075 ee_issueLocalInvExceptL1RequestorInTBE;
2076 k_forwardLocalGETXToLocalOwner;
2077 e_sendAckToL1RequestorFromTBE;
2081 transition(OGMIO, All_Acks, IGMO) {
2082 ee_issueLocalInvExceptL1RequestorInTBE;
2083 c_sendDataFromTBEToL1GETX;
2087 transition({IGMIO, OGMIO}, Own_GETX) {
2088 mm_decrementNumberOfMessagesExt;
2089 o_checkForExtCompletion;
2094 transition(IGM, {Data, Data_Exclusive}, IGMO) {
2096 m_decrementNumberOfMessagesExt;
2097 o_checkForExtCompletion;
2101 transition({IGM, IGMIO, OGMIO}, ExtAck) {
2102 m_decrementNumberOfMessagesExt;
2103 o_checkForExtCompletion;
2107 transition(IGMO, ExtAck) {
2108 m_decrementNumberOfMessagesExt;
2109 o_checkForExtCompletion;
2113 transition(IGS, Data) {
2115 m_decrementNumberOfMessagesExt;
2116 c_sendDataFromTBEToL1GETS;
2120 transition(IGS, Data_Exclusive) {
2122 m_decrementNumberOfMessagesExt;
2123 c_sendExclusiveDataFromTBEToL1GETS;
2127 transition(IGS, Unblock, ILS) {
2128 g_recordLocalSharer;
2134 transition(IGS, Exclusive_Unblock, ILX) {
2135 g_recordLocalExclusive;
2136 f_sendExclusiveUnblock;
2141 transition(IGMO, All_Acks) {
2142 c_sendDataFromTBEToL1GETX;
2146 transition(IGMO, Exclusive_Unblock, ILX) {
2147 g_recordLocalExclusive;
2148 f_sendExclusiveUnblock;
2154 transition(SLS, L1_GETX, IGMLS) {
2158 // count number of INVs needed that doesn't include requestor
2159 h_countLocalSharersExceptRequestor;
2160 // issue INVs to everyone except requestor
2161 y_copyCacheStateToDir;
2162 rr_deallocateL2CacheBlock;
2164 o_popL1RequestQueue;
2168 transition(SLS, L1_GETS, SLSS ) {
2171 o_popL1RequestQueue;
2174 transition(SLSS, Unblock, SLS) {
2175 g_recordLocalSharer;
2180 transition(O, L1_GETX, IGMO) {
2184 y_copyCacheStateToDir;
2185 rr_deallocateL2CacheBlock;
2187 o_popL1RequestQueue;
2190 transition(OLS, L1_GETS, OLSS) {
2193 o_popL1RequestQueue;
2196 transition(OLSS, Unblock, OLS) {
2197 g_recordLocalSharer;
2201 transition(IGMO, Fwd_GETX, IGM) {
2203 c_sendDataFromTBEToFwdGETX;
2208 transition(IGMO, {Fwd_GETS, Fwd_DMA}) {
2210 c_sendDataFromTBEToFwdGETS;
2215 // LOCAL REQUESTS SATISFIED DIRECTLY BY L2
2217 transition(M, L1_GETX, MM) {
2219 // should count 0 of course
2220 h_countLocalSharersExceptRequestor;
2222 y_copyCacheStateToDir;
2223 rr_deallocateL2CacheBlock;
2225 o_popL1RequestQueue;
2228 transition(MM, Exclusive_Unblock, ILX) {
2229 g_recordLocalExclusive;
2233 transition(M, L1_GETS, OO) {
2235 // should count 0 of course
2236 h_countLocalSharersExceptRequestor;
2240 o_popL1RequestQueue;
2243 transition(S, L1_GETS, SS) {
2246 o_popL1RequestQueue;
2249 transition(SS, Unblock, SLS) {
2250 g_recordLocalSharer;
2254 transition(O, L1_GETS, OO) {
2257 o_popL1RequestQueue;
2260 transition(OO, Unblock, OLS) {
2261 g_recordLocalSharer;
2265 transition(OO, Exclusive_Unblock, ILX) {
2266 g_recordLocalExclusive
2267 y_copyCacheStateToDir;
2268 rr_deallocateL2CacheBlock;
2274 transition(ILO, L1_PUTO, ILOW) {
2275 l_writebackAckNeedData;
2276 o_popL1RequestQueue;
2279 transition(ILOX, L1_PUTO, ILOXW) {
2280 l_writebackAckNeedData;
2281 o_popL1RequestQueue;
2285 transition(ILOS, L1_PUTO, ILOSW) {
2286 l_writebackAckNeedData;
2287 o_popL1RequestQueue;
2290 transition(ILOSX, L1_PUTO, ILOSXW) {
2291 l_writebackAckNeedData;
2292 o_popL1RequestQueue;
2296 // hmmm...keep data or drop. Just drop for now
2297 transition(ILOS, L1_PUTS_only, ILOW) {
2298 l_writebackAckDropData;
2299 o_popL1RequestQueue;
2302 transition(ILSW, Unblock, ILS) {
2303 gg_clearSharerFromL1Response;
2307 transition(ILOW, Unblock, ILO) {
2308 gg_clearSharerFromL1Response;
2312 transition(ILOSX, L1_PUTS_only, ILOXW) {
2313 l_writebackAckDropData;
2314 o_popL1RequestQueue;
2317 transition(ILOXW, Unblock, ILOX) {
2318 gg_clearSharerFromL1Response;
2322 // hmmm...keep data or drop. Just drop for now
2323 transition(ILOS, L1_PUTS, ILOSW) {
2324 l_writebackAckDropData;
2325 o_popL1RequestQueue;
2328 transition(ILOSX, L1_PUTS, ILOSXW) {
2329 l_writebackAckDropData;
2330 o_popL1RequestQueue;
2333 transition(ILOSW, Unblock, ILOS) {
2334 gg_clearSharerFromL1Response;
2338 transition(ILOSXW, Unblock, ILOSX) {
2339 gg_clearSharerFromL1Response;
2343 transition(SLS, L1_PUTS, SLSW) {
2344 l_writebackAckDropData;
2345 o_popL1RequestQueue;
2348 transition(SLS, L1_PUTS_only, SW) {
2349 l_writebackAckDropData;
2350 o_popL1RequestQueue;
2353 transition(SW, {Unblock}, S) {
2354 gg_clearSharerFromL1Response;
2358 transition(OLS, L1_PUTS, OLSW) {
2359 l_writebackAckDropData;
2360 o_popL1RequestQueue;
2363 transition(ILS, L1_PUTS, ILSW) {
2364 l_writebackAckNeedData;
2365 o_popL1RequestQueue;
2368 transition(ILS, L1_PUTS_only, IW) {
2369 l_writebackAckNeedData;
2370 o_popL1RequestQueue;
2373 transition(OLS, L1_PUTS_only, OW) {
2374 l_writebackAckDropData;
2375 o_popL1RequestQueue;
2378 transition(OLSX, L1_PUTS_only, OXW) {
2379 l_writebackAckDropData;
2380 o_popL1RequestQueue;
2383 transition(OLSX, L1_PUTS, OLSXW) {
2384 l_writebackAckDropData;
2385 o_popL1RequestQueue;
2388 transition(OLSXW, {Unblock}, OLSX) {
2389 gg_clearSharerFromL1Response;
2393 transition(OW, {Unblock}, O) {
2394 gg_clearSharerFromL1Response;
2398 transition(OXW, {Unblock}, M) {
2399 gg_clearSharerFromL1Response;
2403 transition(ILX, L1_PUTX, ILXW ) {
2404 l_writebackAckNeedData;
2405 o_popL1RequestQueue;
2408 transition(ILXW, L1_WBDIRTYDATA, M) {
2409 gg_clearLocalSharers;
2410 vv_allocateL2CacheBlock;
2411 y_copyDirToCacheAndRemove;
2417 transition(ILXW, L1_WBCLEANDATA, M) {
2418 gg_clearLocalSharers;
2419 vv_allocateL2CacheBlock;
2420 y_copyDirToCacheAndRemove;
2425 transition(ILXW, Unblock, ILX) {
2426 // writeback canceled because L1 invalidated
2430 transition(ILSW, L1_WBCLEANDATA, SLS) {
2431 vv_allocateL2CacheBlock;
2432 y_copyDirToCacheAndRemove;
2434 gg_clearSharerFromL1Response;
2438 transition(IW, L1_WBCLEANDATA, S) {
2439 vv_allocateL2CacheBlock;
2440 y_copyDirToCacheAndRemove;
2442 gg_clearSharerFromL1Response;
2447 // Owner can have dirty data
2448 transition(ILOW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, O) {
2449 vv_allocateL2CacheBlock;
2450 y_copyDirToCacheAndRemove;
2451 gg_clearOwnerFromL1Response;
2456 transition(ILOXW, L1_WBDIRTYDATA, M) {
2457 vv_allocateL2CacheBlock;
2458 y_copyDirToCacheAndRemove;
2459 gg_clearOwnerFromL1Response;
2464 transition(ILOXW, L1_WBCLEANDATA, M) {
2465 vv_allocateL2CacheBlock;
2466 y_copyDirToCacheAndRemove;
2467 gg_clearOwnerFromL1Response;
2472 transition(ILOSW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, OLS) {
2473 vv_allocateL2CacheBlock;
2474 y_copyDirToCacheAndRemove;
2475 gg_clearOwnerFromL1Response;
2480 transition(ILOSXW, {L1_WBCLEANDATA, L1_WBDIRTYDATA}, OLSX) {
2481 vv_allocateL2CacheBlock;
2482 y_copyDirToCacheAndRemove;
2483 gg_clearOwnerFromL1Response;
2489 transition(SLSW, {Unblock}, SLS) {
2490 gg_clearSharerFromL1Response;
2494 transition(OLSW, {Unblock}, OLS) {
2495 gg_clearSharerFromL1Response;
2501 transition({I, S}, L2_Replacement, I) {
2502 rr_deallocateL2CacheBlock;
2505 transition(ILS, L2_Replacement) {
2506 y_copyCacheStateToDir;
2507 rr_deallocateL2CacheBlock;
2510 transition(ILX, L2_Replacement ) {
2511 y_copyCacheStateToDir;
2512 rr_deallocateL2CacheBlock;
2515 transition({ILO, ILOS}, L2_Replacement ) {
2516 y_copyCacheStateToDir;
2517 rr_deallocateL2CacheBlock;
2520 transition(SLS, L2_Replacement, ILS) {
2521 y_copyCacheStateToDir;
2522 rr_deallocateL2CacheBlock;
2525 transition({OLS, OLSX}, L2_Replacement, OLSI) {
2526 y_copyCacheStateToDir;
2529 rr_deallocateL2CacheBlock;
2533 transition(O, L2_Replacement, OI) {
2536 rr_deallocateL2CacheBlock;
2539 transition(M, L2_Replacement, MI) {
2542 rr_deallocateL2CacheBlock;
2545 transition(OLSI, Fwd_GETX, ILSI) {
2551 transition(ILSI, IntAck) {
2552 m_decrementNumberOfMessagesInt;
2553 o_checkForIntCompletion;
2557 transition(ILSI, All_Acks, MII) {
2558 gg_clearLocalSharers;
2559 c_sendDataFromTBEToFwdGETX;
2563 transition(OLSI, {Fwd_GETS, Fwd_DMA}) {
2565 c_sendDataFromTBEToFwdGETS;
2569 transition({MI, OI}, {Fwd_GETS, Fwd_DMA}, OI) {
2571 c_sendDataFromTBEToFwdGETS;
2575 transition({MI, OI}, Fwd_GETX, MII) {
2577 c_sendDataFromTBEToFwdGETX;
2581 transition({MI, OI}, Writeback_Ack, I) {
2582 qq_sendDataFromTBEToMemory;
2587 transition(MII, Writeback_Nack, I) {
2592 transition(OI, Writeback_Nack) {
2597 transition(OLSI, Writeback_Ack, ILS) {
2598 qq_sendDataFromTBEToMemory;
2603 transition(MII, Writeback_Ack, I) {
2609 transition(ILSI, Writeback_Ack, ILS) {