MOESI_CMP_directory-L2cache.sm (14184:11ac1337c5e2) MOESI_CMP_directory-L2cache.sm (14300:22183ae13998)
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41machine(MachineType:L2Cache, "Token protocol")
42: CacheMemory * L2cache;
43 Cycles response_latency := 1;
44 Cycles request_latency := 1;
45
46 // L2 BANK QUEUES
47 // From local bank of L2 cache TO the network
48 MessageBuffer * L1RequestFromL2Cache, network="To", virtual_network="0",
49 vnet_type="request"; // this L2 bank -> a local L1
50 MessageBuffer * GlobalRequestFromL2Cache, network="To", virtual_network="1",
51 vnet_type="request"; // this L2 bank -> mod-directory
52 MessageBuffer * responseFromL2Cache, network="To", virtual_network="2",
53 vnet_type="response"; // this L2 bank -> a local L1 || mod-directory
54
55 // FROM the network to this local bank of L2 cache
56 MessageBuffer * L1RequestToL2Cache, network="From", virtual_network="0",
57 vnet_type="request"; // a local L1 -> this L2 bank, Lets try this???
58 MessageBuffer * GlobalRequestToL2Cache, network="From", virtual_network="1",
59 vnet_type="request"; // mod-directory -> this L2 bank
60 MessageBuffer * responseToL2Cache, network="From", virtual_network="2",
61 vnet_type="response"; // a local L1 || mod-directory -> this L2 bank
62
63 MessageBuffer * triggerQueue;
64{
65 // STATES
66 state_declaration(State, desc="L2 Cache states", default="L2Cache_State_I") {
67
68 // Stable states
69 NP, AccessPermission:Invalid, desc="Not Present";
70 I, AccessPermission:Invalid, desc="Invalid";
71 ILS, AccessPermission:Invalid, desc="Idle/NP, but local sharers exist";
72 ILX, AccessPermission:Invalid, desc="Idle/NP, but local exclusive exists";
73 ILO, AccessPermission:Invalid, desc="Idle/NP, but local owner exists";
74 ILOX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and chip is exclusive";
75 ILOS, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and local sharers as well";
76 ILOSX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
77 S, AccessPermission:Read_Only, desc="Shared, no local sharers";
78 O, AccessPermission:Read_Only, desc="Owned, no local sharers";
79 OLS, AccessPermission:Read_Only, desc="Owned with local sharers";
80 OLSX, AccessPermission:Read_Only, desc="Owned with local sharers, chip is exclusive";
81 SLS, AccessPermission:Read_Only, desc="Shared with local sharers";
82 M, AccessPermission:Read_Write, desc="Modified";
83
84 // Transient States
85
86 IFGX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner/exclusive. No other on-chip invs needed";
87 IFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner";
88 ISFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner, local sharers exist";
89 IFGXX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner but may need acks from other sharers";
90 OLSF, AccessPermission:Busy, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
91
92 // writebacks
93 ILOW, AccessPermission:Busy, desc="local WB request, was ILO";
94 ILOXW, AccessPermission:Busy, desc="local WB request, was ILOX";
95 ILOSW, AccessPermission:Busy, desc="local WB request, was ILOS";
96 ILOSXW, AccessPermission:Busy, desc="local WB request, was ILOSX";
97 SLSW, AccessPermission:Busy, desc="local WB request, was SLS";
98 OLSW, AccessPermission:Busy, desc="local WB request, was OLS";
99 ILSW, AccessPermission:Busy, desc="local WB request, was ILS";
100 IW, AccessPermission:Busy, desc="local WB request from only sharer, was ILS";
101 OW, AccessPermission:Busy, desc="local WB request from only sharer, was OLS";
102 SW, AccessPermission:Busy, desc="local WB request from only sharer, was SLS";
103 OXW, AccessPermission:Busy, desc="local WB request from only sharer, was OLSX";
104 OLSXW, AccessPermission:Busy, desc="local WB request from sharer, was OLSX";
105 ILXW, AccessPermission:Busy, desc="local WB request, was ILX";
106
107 IFLS, AccessPermission:Busy, desc="Blocked, forwarded local GETS to _some_ local sharer";
108 IFLO, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner";
109 IFLOX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner but chip is exclusive";
110 IFLOXX, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner/exclusive, chip is exclusive";
111 IFLOSX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner w/ other sharers, chip is exclusive";
112 IFLXO, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner with other sharers, chip is exclusive";
113
114 IGS, AccessPermission:Busy, desc="Semi-blocked, issued local GETS to directory";
115 IGM, AccessPermission:Busy, desc="Blocked, issued local GETX to directory. Need global acks and data";
116 IGMLS, AccessPermission:Busy, desc="Blocked, issued local GETX to directory but may need to INV local sharers";
117 IGMO, AccessPermission:Busy, desc="Blocked, have data for local GETX but need all acks";
118 IGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner with possible local sharer, may need to INV";
119 OGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, may need to INV";
120 IGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
121 IGMIOFS, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETS";
122 OGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, waiting for global acks, got Fwd_GETX";
123
124 II, AccessPermission:Busy, desc="Blocked, handling invalidations";
125 MM, AccessPermission:Busy, desc="Blocked, was M satisfying local GETX";
126 SS, AccessPermission:Busy, desc="Blocked, was S satisfying local GETS";
127 OO, AccessPermission:Busy, desc="Blocked, was O satisfying local GETS";
128 OLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
129 OLSXS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
130 SLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
131
132 OI, AccessPermission:Busy, desc="Blocked, doing writeback, was O";
133 MI, AccessPermission:Busy, desc="Blocked, doing writeback, was M";
134 MII, AccessPermission:Busy, desc="Blocked, doing writeback, was M, got Fwd_GETX";
135 OLSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS";
136 ILSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
137
138 // DMA blocking states
139 ILOSD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
140 ILOSXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
141 ILOD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
142 ILXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
143 ILOXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
144 }
145
146 // EVENTS
147 enumeration(Event, desc="Cache events") {
148
149 // Requests
150 L1_GETS, desc="local L1 GETS request";
151 L1_GETX, desc="local L1 GETX request";
152 L1_PUTO, desc="local owner wants to writeback";
153 L1_PUTX, desc="local exclusive wants to writeback";
154 L1_PUTS_only, desc="only local sharer wants to writeback";
155 L1_PUTS, desc="local sharer wants to writeback";
156 Fwd_GETX, desc="A GetX from another processor";
157 Fwd_GETS, desc="A GetS from another processor";
158 Fwd_DMA, desc="A request from DMA";
159 Own_GETX, desc="A GetX from this node";
160 Inv, desc="Invalidations from the directory";
161
162 // Responses
163 IntAck, desc="Received an ack message";
164 ExtAck, desc="Received an ack message";
165 All_Acks, desc="Received all ack messages";
166 Data, desc="Received a data message, responder has a shared copy";
167 Data_Exclusive, desc="Received a data message";
168 L1_WBCLEANDATA, desc="Writeback from L1, with data";
169 L1_WBDIRTYDATA, desc="Writeback from L1, with data";
170
171 Writeback_Ack, desc="Writeback O.K. from directory";
172 Writeback_Nack, desc="Writeback not O.K. from directory";
173
174 Unblock, desc="Local L1 is telling L2 dir to unblock";
175 Exclusive_Unblock, desc="Local L1 is telling L2 dir to unblock";
176
177 DmaAck, desc="DMA ack from local L1";
178 // events initiated by this L2
179 L2_Replacement, desc="L2 Replacement", format="!r";
180
181 }
182
183 // TYPES
184
185 // CacheEntry
186 structure(Entry, desc="...", interface="AbstractCacheEntry") {
187 State CacheState, desc="cache state";
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 bool Dirty, desc="Is the data dirty (different than memory)?";
192 DataBlock DataBlk, desc="data for the block";
193 }
194
195
196 structure(DirEntry, desc="...", interface="AbstractEntry") {
197 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
198 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
199 bool OwnerValid, default="false", desc="true if Owner means something";
200 State DirState, desc="directory state";
201 }
202
203 // TBE fields
204 structure(TBE, desc="...") {
205 Addr addr, desc="Physical address for this TBE";
206 State TBEState, desc="Transient state";
207 Addr PC, desc="Program counter of request";
208 DataBlock DataBlk, desc="Buffer for the data block";
209 bool Dirty, desc="Is the data dirty (different than memory)?";
210
211 int NumExtPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
212 int NumIntPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
213 int Fwd_GETX_ExtAcks, default="0", desc="Number of acks that requestor will need";
214 int Local_GETX_IntAcks, default="0", desc="Number of acks that requestor will need";
215
216 NetDest L1_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
217 MachineID L1_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
218 NetDest Fwd_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
219 MachineID Fwd_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
220 }
221
222 structure(TBETable, external = "yes") {
223 TBE lookup(Addr);
224 void allocate(Addr);
225 void deallocate(Addr);
226 bool isPresent(Addr);
227 }
228
229 structure(PerfectCacheMemory, external = "yes") {
230 void allocate(Addr);
231 void deallocate(Addr);
232 DirEntry lookup(Addr);
233 bool isTagPresent(Addr);
234 }
235
236 TBETable TBEs, template="<L2Cache_TBE>", constructor="m_number_of_TBEs";
237 PerfectCacheMemory localDirectory, template="<L2Cache_DirEntry>";
238
239 Tick clockEdge();
240 Tick cyclesToTicks(Cycles c);
241 void set_cache_entry(AbstractCacheEntry b);
242 void unset_cache_entry();
243 void set_tbe(TBE b);
244 void unset_tbe();
245 MachineID mapAddressToMachine(Addr addr, MachineType mtype);
246 void wakeUpAllBuffers(Addr a);
247
248 // Latency for responses that fetch data from cache
249 Cycles cacheResponseLatency() {
250 if (L2cache.getTagLatency() > response_latency) {
251 return L2cache.getTagLatency();
252 }
253 else {
254 return response_latency;
255 }
256 }
257
258 Entry getCacheEntry(Addr address), return_by_pointer="yes" {
259 return static_cast(Entry, "pointer", L2cache[address]);
260 }
261
262 bool isDirTagPresent(Addr addr) {
263 return (localDirectory.isTagPresent(addr) );
264 }
265
266 DirEntry getDirEntry(Addr address), return_by_pointer="yes" {
267 return localDirectory.lookup(address);
268 }
269
270 bool isOnlySharer(Entry cache_entry, Addr addr, MachineID shar_id) {
271 if (is_valid(cache_entry)) {
272 assert (localDirectory.isTagPresent(addr) == false);
273 if (cache_entry.Sharers.count() > 1) {
274 return false;
275 }
276 else if (cache_entry.Sharers.count() == 1) {
277 if (cache_entry.Sharers.isElement(shar_id)) {
278 return true;
279 }
280 else {
281 return false; // something happened which should cause this PUTS to be nacked
282 }
283 return true;
284 }
285 else {
286 return false;
287 }
288 }
289 else if (localDirectory.isTagPresent(addr)){
290 DirEntry dir_entry := getDirEntry(addr);
291 if (dir_entry.Sharers.count() > 1) {
292 return false;
293 }
294 else if (dir_entry.Sharers.count() == 1) {
295 if (dir_entry.Sharers.isElement(shar_id)) {
296 return true;
297 }
298 else {
299 return false; // something happened which should cause this PUTS to be nacked
300 }
301 }
302 else {
303 return false;
304 }
305 }
306 else {
307 // shouldn't happen unless L1 issues PUTS before unblock received
308 return false;
309 }
310 }
311
312 void copyCacheStateToDir(Entry cache_entry, Addr addr) {
313 assert(localDirectory.isTagPresent(addr) == false);
314 assert(is_valid(cache_entry));
315 localDirectory.allocate(addr);
316 DirEntry dir_entry := getDirEntry(addr);
317 dir_entry.DirState := cache_entry.CacheState;
318 dir_entry.Sharers := cache_entry.Sharers;
319 dir_entry.Owner := cache_entry.Owner;
320 dir_entry.OwnerValid := cache_entry.OwnerValid;
321
322 }
323
324 void copyDirToCache(Entry cache_entry, Addr addr) {
325 assert(is_valid(cache_entry));
326 DirEntry dir_entry := getDirEntry(addr);
327 cache_entry.Sharers := dir_entry.Sharers;
328 cache_entry.Owner := dir_entry.Owner;
329 cache_entry.OwnerValid := dir_entry.OwnerValid;
330 }
331
332
333 void recordLocalSharerInDir(Entry cache_entry, Addr addr, MachineID shar_id) {
334 if (is_valid(cache_entry)) {
335 assert (localDirectory.isTagPresent(addr) == false);
336 cache_entry.Sharers.add(shar_id);
337 }
338 else {
339 if (localDirectory.isTagPresent(addr) == false) {
340 localDirectory.allocate(addr);
341 DirEntry dir_entry := getDirEntry(addr);
342 dir_entry.Sharers.clear();
343 dir_entry.OwnerValid := false;
344 }
345 DirEntry dir_entry := getDirEntry(addr);
346 dir_entry.Sharers.add(shar_id);
347 }
348 }
349
350 void recordNewLocalExclusiveInDir(Entry cache_entry, Addr addr, MachineID exc_id) {
351
352 if (is_valid(cache_entry)) {
353 assert (localDirectory.isTagPresent(addr) == false);
354 cache_entry.Sharers.clear();
355 cache_entry.OwnerValid := true;
356 cache_entry.Owner := exc_id;
357 }
358 else {
359 if (localDirectory.isTagPresent(addr) == false) {
360 localDirectory.allocate(addr);
361 }
362 DirEntry dir_entry := getDirEntry(addr);
363 dir_entry.Sharers.clear();
364 dir_entry.OwnerValid := true;
365 dir_entry.Owner := exc_id;
366 }
367 }
368
369 void removeAllLocalSharersFromDir(Entry cache_entry, Addr addr) {
370 if (is_valid(cache_entry)) {
371 assert (localDirectory.isTagPresent(addr) == false);
372 cache_entry.Sharers.clear();
373 cache_entry.OwnerValid := false;
374 }
375 else {
376 DirEntry dir_entry := getDirEntry(addr);
377 dir_entry.Sharers.clear();
378 dir_entry.OwnerValid := false;
379 }
380 }
381
382 void removeSharerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
383 if (is_valid(cache_entry)) {
384 assert (localDirectory.isTagPresent(addr) == false);
385 cache_entry.Sharers.remove(sender);
386 }
387 else {
388 DirEntry dir_entry := getDirEntry(addr);
389 dir_entry.Sharers.remove(sender);
390 }
391 }
392
393 void removeOwnerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
394 if (is_valid(cache_entry)) {
395 assert (localDirectory.isTagPresent(addr) == false);
396 cache_entry.OwnerValid := false;
397 }
398 else {
399 DirEntry dir_entry := getDirEntry(addr);
400 dir_entry.OwnerValid := false;
401 }
402 }
403
404 bool isLocalSharer(Entry cache_entry, Addr addr, MachineID shar_id) {
405 if (is_valid(cache_entry)) {
406 assert (localDirectory.isTagPresent(addr) == false);
407 return cache_entry.Sharers.isElement(shar_id);
408 }
409 else {
410 DirEntry dir_entry := getDirEntry(addr);
411 return dir_entry.Sharers.isElement(shar_id);
412 }
413 }
414
415 NetDest getLocalSharers(Entry cache_entry, Addr addr) {
416 if (is_valid(cache_entry)) {
417 assert (localDirectory.isTagPresent(addr) == false);
418 return cache_entry.Sharers;
419 }
420 else {
421 DirEntry dir_entry := getDirEntry(addr);
422 return dir_entry.Sharers;
423 }
424 }
425
426 MachineID getLocalOwner(Entry cache_entry, Addr addr) {
427 if (is_valid(cache_entry)) {
428 assert (localDirectory.isTagPresent(addr) == false);
429 return cache_entry.Owner;
430 }
431 else {
432 DirEntry dir_entry := getDirEntry(addr);
433 return dir_entry.Owner;
434 }
435 }
436
437 int countLocalSharers(Entry cache_entry, Addr addr) {
438 if (is_valid(cache_entry)) {
439 assert (localDirectory.isTagPresent(addr) == false);
440 return cache_entry.Sharers.count();
441 }
442 else {
443 DirEntry dir_entry := getDirEntry(addr);
444 return dir_entry.Sharers.count();
445 }
446 }
447
448 bool isLocalOwnerValid(Entry cache_entry, Addr addr) {
449 if (is_valid(cache_entry)) {
450 assert (localDirectory.isTagPresent(addr) == false);
451 return cache_entry.OwnerValid;
452 }
453 else {
454 DirEntry dir_entry := getDirEntry(addr);
455 return dir_entry.OwnerValid;
456 }
457 }
458
459 int countLocalSharersExceptRequestor(Entry cache_entry, Addr addr, MachineID requestor) {
460 if (is_valid(cache_entry)) {
461 assert (localDirectory.isTagPresent(addr) == false);
462 if (cache_entry.Sharers.isElement(requestor)) {
463 return ( cache_entry.Sharers.count() - 1 );
464 }
465 else {
466 return cache_entry.Sharers.count();
467 }
468 }
469 else {
470 DirEntry dir_entry := getDirEntry(addr);
471 if (dir_entry.Sharers.isElement(requestor)) {
472 return ( dir_entry.Sharers.count() - 1 );
473 }
474 else {
475 return dir_entry.Sharers.count();
476 }
477 }
478 }
479
480 State getState(TBE tbe, Entry cache_entry, Addr addr) {
481
482 if (is_valid(tbe)) {
483 return tbe.TBEState;
484 } else if (is_valid(cache_entry)) {
485 return cache_entry.CacheState;
486 } else if (isDirTagPresent(addr)) {
487 DirEntry dir_entry := getDirEntry(addr);
488 return dir_entry.DirState;
489 } else {
490 return State:NP;
491 }
492 }
493
494 std::string getCoherenceRequestTypeStr(CoherenceRequestType type) {
495 return CoherenceRequestType_to_string(type);
496 }
497
498 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
499 assert((localDirectory.isTagPresent(addr) && L2cache.isTagPresent(addr)) == false);
500
501 if (is_valid(tbe)) {
502 tbe.TBEState := state;
503 }
504
505 if (
506 (state == State:M) ||
507 (state == State:O) ||
508 (state == State:S) ||
509 (state == State:OLS) ||
510 (state == State:SLS) ||
511 (state == State:OLSX) ||
512 (state == State:SLS)
513 ) {
514 assert(is_valid(cache_entry));
515 }
516 else if (
517 (state == State:ILS) ||
518 (state == State:ILX) ||
519 (state == State:ILO) ||
520 (state == State:ILOX) ||
521 (state == State:ILOS) ||
522 (state == State:ILOSX)
523 ) {
524 // assert(isCacheTagPresent(addr) == false);
525 }
526
527 if (is_valid(cache_entry)) {
528 if ( ((cache_entry.CacheState != State:M) && (state == State:M)) ||
529 ((cache_entry.CacheState != State:S) && (state == State:S)) ||
530 ((cache_entry.CacheState != State:O) && (state == State:O)) ) {
531 cache_entry.CacheState := state;
532 // disable Coherence Checker for now
533 // sequencer.checkCoherence(addr);
534 }
535 else {
536 cache_entry.CacheState := state;
537 }
538 }
539 else if (localDirectory.isTagPresent(addr)) {
540 DirEntry dir_entry := getDirEntry(addr);
541 dir_entry.DirState := state;
542 }
543 }
544
545 AccessPermission getAccessPermission(Addr addr) {
546 TBE tbe := TBEs[addr];
547 if(is_valid(tbe)) {
548 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
549 return L2Cache_State_to_permission(tbe.TBEState);
550 }
551
552 Entry cache_entry := getCacheEntry(addr);
553 if(is_valid(cache_entry)) {
554 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
555 return L2Cache_State_to_permission(cache_entry.CacheState);
556 }
557
558 DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
559 return AccessPermission:NotPresent;
560 }
561
562 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
563 if (is_valid(cache_entry)) {
564 cache_entry.changePermission(L2Cache_State_to_permission(state));
565 }
566 }
567
568 void functionalRead(Addr addr, Packet *pkt) {
569 TBE tbe := TBEs[addr];
570 if(is_valid(tbe)) {
571 testAndRead(addr, tbe.DataBlk, pkt);
572 } else {
573 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
574 }
575 }
576
577 int functionalWrite(Addr addr, Packet *pkt) {
578 int num_functional_writes := 0;
579
580 TBE tbe := TBEs[addr];
581 if(is_valid(tbe)) {
582 num_functional_writes := num_functional_writes +
583 testAndWrite(addr, tbe.DataBlk, pkt);
584 return num_functional_writes;
585 }
586
587 num_functional_writes := num_functional_writes +
588 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
589 return num_functional_writes;
590 }
591
592 out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache);
593 out_port(localRequestNetwork_out, RequestMsg, L1RequestFromL2Cache);
594 out_port(responseNetwork_out, ResponseMsg, responseFromL2Cache);
595
596 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
597
598
599 // ** IN_PORTS **
600
601 // Trigger Queue
602 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=3) {
603 if (triggerQueue_in.isReady(clockEdge())) {
604 peek(triggerQueue_in, TriggerMsg) {
605 if (in_msg.Type == TriggerType:ALL_ACKS) {
606 trigger(Event:All_Acks, in_msg.addr,
607 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
608 } else {
609 error("Unexpected message");
610 }
611 }
612 }
613 }
614
615 // Response Network
616 in_port(responseNetwork_in, ResponseMsg, responseToL2Cache, rank=2) {
617 if (responseNetwork_in.isReady(clockEdge())) {
618 peek(responseNetwork_in, ResponseMsg) {
619 assert(in_msg.Destination.isElement(machineID));
620 if (in_msg.Type == CoherenceResponseType:ACK) {
621 if (in_msg.SenderMachine == MachineType:L2Cache) {
622 trigger(Event:ExtAck, in_msg.addr,
623 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
624 }
625 else {
626 trigger(Event:IntAck, in_msg.addr,
627 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
628 }
629 } else if (in_msg.Type == CoherenceResponseType:DATA) {
630 trigger(Event:Data, in_msg.addr,
631 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
632 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
633 trigger(Event:Data_Exclusive, in_msg.addr,
634 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
635 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
636 DPRINTF(RubySlicc, "Received Unblock from L1 addr: %x\n", in_msg.addr);
637 trigger(Event:Unblock, in_msg.addr,
638 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
639 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
640 trigger(Event:Exclusive_Unblock, in_msg.addr,
641 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
642 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) {
643 trigger(Event:Writeback_Ack, in_msg.addr,
644 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
645 } else if (in_msg.Type == CoherenceResponseType:WB_NACK) {
646 trigger(Event:Writeback_Nack, in_msg.addr,
647 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
648 } else if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
649 trigger(Event:DmaAck, in_msg.addr,
650 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
651 } else {
652 error("Unexpected message");
653 }
654 }
655 }
656 }
657
658
659 // Request Network
660 in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache, rank=1) {
661 if (requestNetwork_in.isReady(clockEdge())) {
662 peek(requestNetwork_in, RequestMsg) {
663 if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
664 if (in_msg.Requestor == machineID) {
665 trigger(Event:Own_GETX, in_msg.addr,
666 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
667 } else {
668 trigger(Event:Fwd_GETX, in_msg.addr,
669 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
670 }
671 } else if (in_msg.Type == CoherenceRequestType:GETS) {
672 trigger(Event:Fwd_GETS, in_msg.addr,
673 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
674 } else if(in_msg.Type == CoherenceRequestType:DMA_READ) {
675 trigger(Event:Fwd_DMA, in_msg.addr,
676 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
677 } else if (in_msg.Type == CoherenceRequestType:INV) {
678 trigger(Event:Inv, in_msg.addr,
679 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
680 } else {
681 error("Unexpected message");
682 }
683 }
684 }
685 }
686
687 in_port(L1requestNetwork_in, RequestMsg, L1RequestToL2Cache, rank=0) {
688 if (L1requestNetwork_in.isReady(clockEdge())) {
689 peek(L1requestNetwork_in, RequestMsg) {
690 assert(in_msg.Destination.isElement(machineID));
691 if (in_msg.Type == CoherenceRequestType:GETX) {
692 trigger(Event:L1_GETX, in_msg.addr,
693 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
694 } else if (in_msg.Type == CoherenceRequestType:GETS) {
695 trigger(Event:L1_GETS, in_msg.addr,
696 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
697 } else if (in_msg.Type == CoherenceRequestType:PUTO) {
698 trigger(Event:L1_PUTO, in_msg.addr,
699 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
700 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
701 trigger(Event:L1_PUTX, in_msg.addr,
702 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
703 } else if (in_msg.Type == CoherenceRequestType:PUTS) {
704 Entry cache_entry := getCacheEntry(in_msg.addr);
705 if (isOnlySharer(cache_entry, in_msg.addr, in_msg.Requestor)) {
706 trigger(Event:L1_PUTS_only, in_msg.addr,
707 cache_entry, TBEs[in_msg.addr]);
708 }
709 else {
710 trigger(Event:L1_PUTS, in_msg.addr,
711 cache_entry, TBEs[in_msg.addr]);
712 }
713 } else if (in_msg.Type == CoherenceRequestType:WRITEBACK_DIRTY_DATA) {
714 Entry cache_entry := getCacheEntry(in_msg.addr);
715 if (is_invalid(cache_entry) &&
716 L2cache.cacheAvail(in_msg.addr) == false) {
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41machine(MachineType:L2Cache, "Token protocol")
42: CacheMemory * L2cache;
43 Cycles response_latency := 1;
44 Cycles request_latency := 1;
45
46 // L2 BANK QUEUES
47 // From local bank of L2 cache TO the network
48 MessageBuffer * L1RequestFromL2Cache, network="To", virtual_network="0",
49 vnet_type="request"; // this L2 bank -> a local L1
50 MessageBuffer * GlobalRequestFromL2Cache, network="To", virtual_network="1",
51 vnet_type="request"; // this L2 bank -> mod-directory
52 MessageBuffer * responseFromL2Cache, network="To", virtual_network="2",
53 vnet_type="response"; // this L2 bank -> a local L1 || mod-directory
54
55 // FROM the network to this local bank of L2 cache
56 MessageBuffer * L1RequestToL2Cache, network="From", virtual_network="0",
57 vnet_type="request"; // a local L1 -> this L2 bank, Lets try this???
58 MessageBuffer * GlobalRequestToL2Cache, network="From", virtual_network="1",
59 vnet_type="request"; // mod-directory -> this L2 bank
60 MessageBuffer * responseToL2Cache, network="From", virtual_network="2",
61 vnet_type="response"; // a local L1 || mod-directory -> this L2 bank
62
63 MessageBuffer * triggerQueue;
64{
65 // STATES
66 state_declaration(State, desc="L2 Cache states", default="L2Cache_State_I") {
67
68 // Stable states
69 NP, AccessPermission:Invalid, desc="Not Present";
70 I, AccessPermission:Invalid, desc="Invalid";
71 ILS, AccessPermission:Invalid, desc="Idle/NP, but local sharers exist";
72 ILX, AccessPermission:Invalid, desc="Idle/NP, but local exclusive exists";
73 ILO, AccessPermission:Invalid, desc="Idle/NP, but local owner exists";
74 ILOX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and chip is exclusive";
75 ILOS, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and local sharers as well";
76 ILOSX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
77 S, AccessPermission:Read_Only, desc="Shared, no local sharers";
78 O, AccessPermission:Read_Only, desc="Owned, no local sharers";
79 OLS, AccessPermission:Read_Only, desc="Owned with local sharers";
80 OLSX, AccessPermission:Read_Only, desc="Owned with local sharers, chip is exclusive";
81 SLS, AccessPermission:Read_Only, desc="Shared with local sharers";
82 M, AccessPermission:Read_Write, desc="Modified";
83
84 // Transient States
85
86 IFGX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner/exclusive. No other on-chip invs needed";
87 IFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner";
88 ISFGS, AccessPermission:Busy, desc="Blocked, forwarded global GETS to local owner, local sharers exist";
89 IFGXX, AccessPermission:Busy, desc="Blocked, forwarded global GETX to local owner but may need acks from other sharers";
90 OLSF, AccessPermission:Busy, desc="Blocked, got Fwd_GETX with local sharers, waiting for local inv acks";
91
92 // writebacks
93 ILOW, AccessPermission:Busy, desc="local WB request, was ILO";
94 ILOXW, AccessPermission:Busy, desc="local WB request, was ILOX";
95 ILOSW, AccessPermission:Busy, desc="local WB request, was ILOS";
96 ILOSXW, AccessPermission:Busy, desc="local WB request, was ILOSX";
97 SLSW, AccessPermission:Busy, desc="local WB request, was SLS";
98 OLSW, AccessPermission:Busy, desc="local WB request, was OLS";
99 ILSW, AccessPermission:Busy, desc="local WB request, was ILS";
100 IW, AccessPermission:Busy, desc="local WB request from only sharer, was ILS";
101 OW, AccessPermission:Busy, desc="local WB request from only sharer, was OLS";
102 SW, AccessPermission:Busy, desc="local WB request from only sharer, was SLS";
103 OXW, AccessPermission:Busy, desc="local WB request from only sharer, was OLSX";
104 OLSXW, AccessPermission:Busy, desc="local WB request from sharer, was OLSX";
105 ILXW, AccessPermission:Busy, desc="local WB request, was ILX";
106
107 IFLS, AccessPermission:Busy, desc="Blocked, forwarded local GETS to _some_ local sharer";
108 IFLO, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner";
109 IFLOX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner but chip is exclusive";
110 IFLOXX, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner/exclusive, chip is exclusive";
111 IFLOSX, AccessPermission:Busy, desc="Blocked, forwarded local GETS to local owner w/ other sharers, chip is exclusive";
112 IFLXO, AccessPermission:Busy, desc="Blocked, forwarded local GETX to local owner with other sharers, chip is exclusive";
113
114 IGS, AccessPermission:Busy, desc="Semi-blocked, issued local GETS to directory";
115 IGM, AccessPermission:Busy, desc="Blocked, issued local GETX to directory. Need global acks and data";
116 IGMLS, AccessPermission:Busy, desc="Blocked, issued local GETX to directory but may need to INV local sharers";
117 IGMO, AccessPermission:Busy, desc="Blocked, have data for local GETX but need all acks";
118 IGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner with possible local sharer, may need to INV";
119 OGMIO, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, may need to INV";
120 IGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETX";
121 IGMIOFS, AccessPermission:Busy, desc="Blocked, issued local GETX, local owner, waiting for global acks, got Fwd_GETS";
122 OGMIOF, AccessPermission:Busy, desc="Blocked, issued local GETX, was owner, waiting for global acks, got Fwd_GETX";
123
124 II, AccessPermission:Busy, desc="Blocked, handling invalidations";
125 MM, AccessPermission:Busy, desc="Blocked, was M satisfying local GETX";
126 SS, AccessPermission:Busy, desc="Blocked, was S satisfying local GETS";
127 OO, AccessPermission:Busy, desc="Blocked, was O satisfying local GETS";
128 OLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
129 OLSXS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
130 SLSS, AccessPermission:Busy, desc="Blocked, satisfying local GETS";
131
132 OI, AccessPermission:Busy, desc="Blocked, doing writeback, was O";
133 MI, AccessPermission:Busy, desc="Blocked, doing writeback, was M";
134 MII, AccessPermission:Busy, desc="Blocked, doing writeback, was M, got Fwd_GETX";
135 OLSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS";
136 ILSI, AccessPermission:Busy, desc="Blocked, doing writeback, was OLS got Fwd_GETX";
137
138 // DMA blocking states
139 ILOSD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
140 ILOSXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
141 ILOD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
142 ILXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
143 ILOXD, AccessPermission:Busy, desc="Blocked, waiting for DMA ack";
144 }
145
146 // EVENTS
147 enumeration(Event, desc="Cache events") {
148
149 // Requests
150 L1_GETS, desc="local L1 GETS request";
151 L1_GETX, desc="local L1 GETX request";
152 L1_PUTO, desc="local owner wants to writeback";
153 L1_PUTX, desc="local exclusive wants to writeback";
154 L1_PUTS_only, desc="only local sharer wants to writeback";
155 L1_PUTS, desc="local sharer wants to writeback";
156 Fwd_GETX, desc="A GetX from another processor";
157 Fwd_GETS, desc="A GetS from another processor";
158 Fwd_DMA, desc="A request from DMA";
159 Own_GETX, desc="A GetX from this node";
160 Inv, desc="Invalidations from the directory";
161
162 // Responses
163 IntAck, desc="Received an ack message";
164 ExtAck, desc="Received an ack message";
165 All_Acks, desc="Received all ack messages";
166 Data, desc="Received a data message, responder has a shared copy";
167 Data_Exclusive, desc="Received a data message";
168 L1_WBCLEANDATA, desc="Writeback from L1, with data";
169 L1_WBDIRTYDATA, desc="Writeback from L1, with data";
170
171 Writeback_Ack, desc="Writeback O.K. from directory";
172 Writeback_Nack, desc="Writeback not O.K. from directory";
173
174 Unblock, desc="Local L1 is telling L2 dir to unblock";
175 Exclusive_Unblock, desc="Local L1 is telling L2 dir to unblock";
176
177 DmaAck, desc="DMA ack from local L1";
178 // events initiated by this L2
179 L2_Replacement, desc="L2 Replacement", format="!r";
180
181 }
182
183 // TYPES
184
185 // CacheEntry
186 structure(Entry, desc="...", interface="AbstractCacheEntry") {
187 State CacheState, desc="cache state";
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 bool Dirty, desc="Is the data dirty (different than memory)?";
192 DataBlock DataBlk, desc="data for the block";
193 }
194
195
196 structure(DirEntry, desc="...", interface="AbstractEntry") {
197 NetDest Sharers, desc="Set of the internal processors that want the block in shared state";
198 MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response";
199 bool OwnerValid, default="false", desc="true if Owner means something";
200 State DirState, desc="directory state";
201 }
202
203 // TBE fields
204 structure(TBE, desc="...") {
205 Addr addr, desc="Physical address for this TBE";
206 State TBEState, desc="Transient state";
207 Addr PC, desc="Program counter of request";
208 DataBlock DataBlk, desc="Buffer for the data block";
209 bool Dirty, desc="Is the data dirty (different than memory)?";
210
211 int NumExtPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
212 int NumIntPendingAcks, default="0", desc="Number of global acks/data messages waiting for";
213 int Fwd_GETX_ExtAcks, default="0", desc="Number of acks that requestor will need";
214 int Local_GETX_IntAcks, default="0", desc="Number of acks that requestor will need";
215
216 NetDest L1_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
217 MachineID L1_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
218 NetDest Fwd_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
219 MachineID Fwd_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
220 }
221
222 structure(TBETable, external = "yes") {
223 TBE lookup(Addr);
224 void allocate(Addr);
225 void deallocate(Addr);
226 bool isPresent(Addr);
227 }
228
229 structure(PerfectCacheMemory, external = "yes") {
230 void allocate(Addr);
231 void deallocate(Addr);
232 DirEntry lookup(Addr);
233 bool isTagPresent(Addr);
234 }
235
236 TBETable TBEs, template="<L2Cache_TBE>", constructor="m_number_of_TBEs";
237 PerfectCacheMemory localDirectory, template="<L2Cache_DirEntry>";
238
239 Tick clockEdge();
240 Tick cyclesToTicks(Cycles c);
241 void set_cache_entry(AbstractCacheEntry b);
242 void unset_cache_entry();
243 void set_tbe(TBE b);
244 void unset_tbe();
245 MachineID mapAddressToMachine(Addr addr, MachineType mtype);
246 void wakeUpAllBuffers(Addr a);
247
248 // Latency for responses that fetch data from cache
249 Cycles cacheResponseLatency() {
250 if (L2cache.getTagLatency() > response_latency) {
251 return L2cache.getTagLatency();
252 }
253 else {
254 return response_latency;
255 }
256 }
257
258 Entry getCacheEntry(Addr address), return_by_pointer="yes" {
259 return static_cast(Entry, "pointer", L2cache[address]);
260 }
261
262 bool isDirTagPresent(Addr addr) {
263 return (localDirectory.isTagPresent(addr) );
264 }
265
266 DirEntry getDirEntry(Addr address), return_by_pointer="yes" {
267 return localDirectory.lookup(address);
268 }
269
270 bool isOnlySharer(Entry cache_entry, Addr addr, MachineID shar_id) {
271 if (is_valid(cache_entry)) {
272 assert (localDirectory.isTagPresent(addr) == false);
273 if (cache_entry.Sharers.count() > 1) {
274 return false;
275 }
276 else if (cache_entry.Sharers.count() == 1) {
277 if (cache_entry.Sharers.isElement(shar_id)) {
278 return true;
279 }
280 else {
281 return false; // something happened which should cause this PUTS to be nacked
282 }
283 return true;
284 }
285 else {
286 return false;
287 }
288 }
289 else if (localDirectory.isTagPresent(addr)){
290 DirEntry dir_entry := getDirEntry(addr);
291 if (dir_entry.Sharers.count() > 1) {
292 return false;
293 }
294 else if (dir_entry.Sharers.count() == 1) {
295 if (dir_entry.Sharers.isElement(shar_id)) {
296 return true;
297 }
298 else {
299 return false; // something happened which should cause this PUTS to be nacked
300 }
301 }
302 else {
303 return false;
304 }
305 }
306 else {
307 // shouldn't happen unless L1 issues PUTS before unblock received
308 return false;
309 }
310 }
311
312 void copyCacheStateToDir(Entry cache_entry, Addr addr) {
313 assert(localDirectory.isTagPresent(addr) == false);
314 assert(is_valid(cache_entry));
315 localDirectory.allocate(addr);
316 DirEntry dir_entry := getDirEntry(addr);
317 dir_entry.DirState := cache_entry.CacheState;
318 dir_entry.Sharers := cache_entry.Sharers;
319 dir_entry.Owner := cache_entry.Owner;
320 dir_entry.OwnerValid := cache_entry.OwnerValid;
321
322 }
323
324 void copyDirToCache(Entry cache_entry, Addr addr) {
325 assert(is_valid(cache_entry));
326 DirEntry dir_entry := getDirEntry(addr);
327 cache_entry.Sharers := dir_entry.Sharers;
328 cache_entry.Owner := dir_entry.Owner;
329 cache_entry.OwnerValid := dir_entry.OwnerValid;
330 }
331
332
333 void recordLocalSharerInDir(Entry cache_entry, Addr addr, MachineID shar_id) {
334 if (is_valid(cache_entry)) {
335 assert (localDirectory.isTagPresent(addr) == false);
336 cache_entry.Sharers.add(shar_id);
337 }
338 else {
339 if (localDirectory.isTagPresent(addr) == false) {
340 localDirectory.allocate(addr);
341 DirEntry dir_entry := getDirEntry(addr);
342 dir_entry.Sharers.clear();
343 dir_entry.OwnerValid := false;
344 }
345 DirEntry dir_entry := getDirEntry(addr);
346 dir_entry.Sharers.add(shar_id);
347 }
348 }
349
350 void recordNewLocalExclusiveInDir(Entry cache_entry, Addr addr, MachineID exc_id) {
351
352 if (is_valid(cache_entry)) {
353 assert (localDirectory.isTagPresent(addr) == false);
354 cache_entry.Sharers.clear();
355 cache_entry.OwnerValid := true;
356 cache_entry.Owner := exc_id;
357 }
358 else {
359 if (localDirectory.isTagPresent(addr) == false) {
360 localDirectory.allocate(addr);
361 }
362 DirEntry dir_entry := getDirEntry(addr);
363 dir_entry.Sharers.clear();
364 dir_entry.OwnerValid := true;
365 dir_entry.Owner := exc_id;
366 }
367 }
368
369 void removeAllLocalSharersFromDir(Entry cache_entry, Addr addr) {
370 if (is_valid(cache_entry)) {
371 assert (localDirectory.isTagPresent(addr) == false);
372 cache_entry.Sharers.clear();
373 cache_entry.OwnerValid := false;
374 }
375 else {
376 DirEntry dir_entry := getDirEntry(addr);
377 dir_entry.Sharers.clear();
378 dir_entry.OwnerValid := false;
379 }
380 }
381
382 void removeSharerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
383 if (is_valid(cache_entry)) {
384 assert (localDirectory.isTagPresent(addr) == false);
385 cache_entry.Sharers.remove(sender);
386 }
387 else {
388 DirEntry dir_entry := getDirEntry(addr);
389 dir_entry.Sharers.remove(sender);
390 }
391 }
392
393 void removeOwnerFromDir(Entry cache_entry, Addr addr, MachineID sender) {
394 if (is_valid(cache_entry)) {
395 assert (localDirectory.isTagPresent(addr) == false);
396 cache_entry.OwnerValid := false;
397 }
398 else {
399 DirEntry dir_entry := getDirEntry(addr);
400 dir_entry.OwnerValid := false;
401 }
402 }
403
404 bool isLocalSharer(Entry cache_entry, Addr addr, MachineID shar_id) {
405 if (is_valid(cache_entry)) {
406 assert (localDirectory.isTagPresent(addr) == false);
407 return cache_entry.Sharers.isElement(shar_id);
408 }
409 else {
410 DirEntry dir_entry := getDirEntry(addr);
411 return dir_entry.Sharers.isElement(shar_id);
412 }
413 }
414
415 NetDest getLocalSharers(Entry cache_entry, Addr addr) {
416 if (is_valid(cache_entry)) {
417 assert (localDirectory.isTagPresent(addr) == false);
418 return cache_entry.Sharers;
419 }
420 else {
421 DirEntry dir_entry := getDirEntry(addr);
422 return dir_entry.Sharers;
423 }
424 }
425
426 MachineID getLocalOwner(Entry cache_entry, Addr addr) {
427 if (is_valid(cache_entry)) {
428 assert (localDirectory.isTagPresent(addr) == false);
429 return cache_entry.Owner;
430 }
431 else {
432 DirEntry dir_entry := getDirEntry(addr);
433 return dir_entry.Owner;
434 }
435 }
436
437 int countLocalSharers(Entry cache_entry, Addr addr) {
438 if (is_valid(cache_entry)) {
439 assert (localDirectory.isTagPresent(addr) == false);
440 return cache_entry.Sharers.count();
441 }
442 else {
443 DirEntry dir_entry := getDirEntry(addr);
444 return dir_entry.Sharers.count();
445 }
446 }
447
448 bool isLocalOwnerValid(Entry cache_entry, Addr addr) {
449 if (is_valid(cache_entry)) {
450 assert (localDirectory.isTagPresent(addr) == false);
451 return cache_entry.OwnerValid;
452 }
453 else {
454 DirEntry dir_entry := getDirEntry(addr);
455 return dir_entry.OwnerValid;
456 }
457 }
458
459 int countLocalSharersExceptRequestor(Entry cache_entry, Addr addr, MachineID requestor) {
460 if (is_valid(cache_entry)) {
461 assert (localDirectory.isTagPresent(addr) == false);
462 if (cache_entry.Sharers.isElement(requestor)) {
463 return ( cache_entry.Sharers.count() - 1 );
464 }
465 else {
466 return cache_entry.Sharers.count();
467 }
468 }
469 else {
470 DirEntry dir_entry := getDirEntry(addr);
471 if (dir_entry.Sharers.isElement(requestor)) {
472 return ( dir_entry.Sharers.count() - 1 );
473 }
474 else {
475 return dir_entry.Sharers.count();
476 }
477 }
478 }
479
480 State getState(TBE tbe, Entry cache_entry, Addr addr) {
481
482 if (is_valid(tbe)) {
483 return tbe.TBEState;
484 } else if (is_valid(cache_entry)) {
485 return cache_entry.CacheState;
486 } else if (isDirTagPresent(addr)) {
487 DirEntry dir_entry := getDirEntry(addr);
488 return dir_entry.DirState;
489 } else {
490 return State:NP;
491 }
492 }
493
494 std::string getCoherenceRequestTypeStr(CoherenceRequestType type) {
495 return CoherenceRequestType_to_string(type);
496 }
497
498 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
499 assert((localDirectory.isTagPresent(addr) && L2cache.isTagPresent(addr)) == false);
500
501 if (is_valid(tbe)) {
502 tbe.TBEState := state;
503 }
504
505 if (
506 (state == State:M) ||
507 (state == State:O) ||
508 (state == State:S) ||
509 (state == State:OLS) ||
510 (state == State:SLS) ||
511 (state == State:OLSX) ||
512 (state == State:SLS)
513 ) {
514 assert(is_valid(cache_entry));
515 }
516 else if (
517 (state == State:ILS) ||
518 (state == State:ILX) ||
519 (state == State:ILO) ||
520 (state == State:ILOX) ||
521 (state == State:ILOS) ||
522 (state == State:ILOSX)
523 ) {
524 // assert(isCacheTagPresent(addr) == false);
525 }
526
527 if (is_valid(cache_entry)) {
528 if ( ((cache_entry.CacheState != State:M) && (state == State:M)) ||
529 ((cache_entry.CacheState != State:S) && (state == State:S)) ||
530 ((cache_entry.CacheState != State:O) && (state == State:O)) ) {
531 cache_entry.CacheState := state;
532 // disable Coherence Checker for now
533 // sequencer.checkCoherence(addr);
534 }
535 else {
536 cache_entry.CacheState := state;
537 }
538 }
539 else if (localDirectory.isTagPresent(addr)) {
540 DirEntry dir_entry := getDirEntry(addr);
541 dir_entry.DirState := state;
542 }
543 }
544
545 AccessPermission getAccessPermission(Addr addr) {
546 TBE tbe := TBEs[addr];
547 if(is_valid(tbe)) {
548 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
549 return L2Cache_State_to_permission(tbe.TBEState);
550 }
551
552 Entry cache_entry := getCacheEntry(addr);
553 if(is_valid(cache_entry)) {
554 DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
555 return L2Cache_State_to_permission(cache_entry.CacheState);
556 }
557
558 DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
559 return AccessPermission:NotPresent;
560 }
561
562 void setAccessPermission(Entry cache_entry, Addr addr, State state) {
563 if (is_valid(cache_entry)) {
564 cache_entry.changePermission(L2Cache_State_to_permission(state));
565 }
566 }
567
568 void functionalRead(Addr addr, Packet *pkt) {
569 TBE tbe := TBEs[addr];
570 if(is_valid(tbe)) {
571 testAndRead(addr, tbe.DataBlk, pkt);
572 } else {
573 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
574 }
575 }
576
577 int functionalWrite(Addr addr, Packet *pkt) {
578 int num_functional_writes := 0;
579
580 TBE tbe := TBEs[addr];
581 if(is_valid(tbe)) {
582 num_functional_writes := num_functional_writes +
583 testAndWrite(addr, tbe.DataBlk, pkt);
584 return num_functional_writes;
585 }
586
587 num_functional_writes := num_functional_writes +
588 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
589 return num_functional_writes;
590 }
591
592 out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache);
593 out_port(localRequestNetwork_out, RequestMsg, L1RequestFromL2Cache);
594 out_port(responseNetwork_out, ResponseMsg, responseFromL2Cache);
595
596 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
597
598
599 // ** IN_PORTS **
600
601 // Trigger Queue
602 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=3) {
603 if (triggerQueue_in.isReady(clockEdge())) {
604 peek(triggerQueue_in, TriggerMsg) {
605 if (in_msg.Type == TriggerType:ALL_ACKS) {
606 trigger(Event:All_Acks, in_msg.addr,
607 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
608 } else {
609 error("Unexpected message");
610 }
611 }
612 }
613 }
614
615 // Response Network
616 in_port(responseNetwork_in, ResponseMsg, responseToL2Cache, rank=2) {
617 if (responseNetwork_in.isReady(clockEdge())) {
618 peek(responseNetwork_in, ResponseMsg) {
619 assert(in_msg.Destination.isElement(machineID));
620 if (in_msg.Type == CoherenceResponseType:ACK) {
621 if (in_msg.SenderMachine == MachineType:L2Cache) {
622 trigger(Event:ExtAck, in_msg.addr,
623 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
624 }
625 else {
626 trigger(Event:IntAck, in_msg.addr,
627 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
628 }
629 } else if (in_msg.Type == CoherenceResponseType:DATA) {
630 trigger(Event:Data, in_msg.addr,
631 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
632 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
633 trigger(Event:Data_Exclusive, in_msg.addr,
634 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
635 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
636 DPRINTF(RubySlicc, "Received Unblock from L1 addr: %x\n", in_msg.addr);
637 trigger(Event:Unblock, in_msg.addr,
638 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
639 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK_EXCLUSIVE) {
640 trigger(Event:Exclusive_Unblock, in_msg.addr,
641 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
642 } else if (in_msg.Type == CoherenceResponseType:WB_ACK) {
643 trigger(Event:Writeback_Ack, in_msg.addr,
644 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
645 } else if (in_msg.Type == CoherenceResponseType:WB_NACK) {
646 trigger(Event:Writeback_Nack, in_msg.addr,
647 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
648 } else if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
649 trigger(Event:DmaAck, in_msg.addr,
650 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
651 } else {
652 error("Unexpected message");
653 }
654 }
655 }
656 }
657
658
659 // Request Network
660 in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache, rank=1) {
661 if (requestNetwork_in.isReady(clockEdge())) {
662 peek(requestNetwork_in, RequestMsg) {
663 if (in_msg.Type == CoherenceRequestType:GETX || in_msg.Type == CoherenceRequestType:DMA_WRITE) {
664 if (in_msg.Requestor == machineID) {
665 trigger(Event:Own_GETX, in_msg.addr,
666 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
667 } else {
668 trigger(Event:Fwd_GETX, in_msg.addr,
669 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
670 }
671 } else if (in_msg.Type == CoherenceRequestType:GETS) {
672 trigger(Event:Fwd_GETS, in_msg.addr,
673 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
674 } else if(in_msg.Type == CoherenceRequestType:DMA_READ) {
675 trigger(Event:Fwd_DMA, in_msg.addr,
676 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
677 } else if (in_msg.Type == CoherenceRequestType:INV) {
678 trigger(Event:Inv, in_msg.addr,
679 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
680 } else {
681 error("Unexpected message");
682 }
683 }
684 }
685 }
686
687 in_port(L1requestNetwork_in, RequestMsg, L1RequestToL2Cache, rank=0) {
688 if (L1requestNetwork_in.isReady(clockEdge())) {
689 peek(L1requestNetwork_in, RequestMsg) {
690 assert(in_msg.Destination.isElement(machineID));
691 if (in_msg.Type == CoherenceRequestType:GETX) {
692 trigger(Event:L1_GETX, in_msg.addr,
693 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
694 } else if (in_msg.Type == CoherenceRequestType:GETS) {
695 trigger(Event:L1_GETS, in_msg.addr,
696 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
697 } else if (in_msg.Type == CoherenceRequestType:PUTO) {
698 trigger(Event:L1_PUTO, in_msg.addr,
699 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
700 } else if (in_msg.Type == CoherenceRequestType:PUTX) {
701 trigger(Event:L1_PUTX, in_msg.addr,
702 getCacheEntry(in_msg.addr), TBEs[in_msg.addr]);
703 } else if (in_msg.Type == CoherenceRequestType:PUTS) {
704 Entry cache_entry := getCacheEntry(in_msg.addr);
705 if (isOnlySharer(cache_entry, in_msg.addr, in_msg.Requestor)) {
706 trigger(Event:L1_PUTS_only, in_msg.addr,
707 cache_entry, TBEs[in_msg.addr]);
708 }
709 else {
710 trigger(Event:L1_PUTS, in_msg.addr,
711 cache_entry, TBEs[in_msg.addr]);
712 }
713 } else if (in_msg.Type == CoherenceRequestType:WRITEBACK_DIRTY_DATA) {
714 Entry cache_entry := getCacheEntry(in_msg.addr);
715 if (is_invalid(cache_entry) &&
716 L2cache.cacheAvail(in_msg.addr) == false) {
717 trigger(Event:L2_Replacement, L2cache.cacheProbe(in_msg.addr),
718 getCacheEntry(L2cache.cacheProbe(in_msg.addr)),
719 TBEs[L2cache.cacheProbe(in_msg.addr)]);
717 Addr victim := L2cache.cacheProbe(in_msg.addr);
718 trigger(Event:L2_Replacement,
719 victim, getCacheEntry(victim), TBEs[victim]);
720 }
721 else {
722 trigger(Event:L1_WBDIRTYDATA, in_msg.addr,
723 cache_entry, TBEs[in_msg.addr]);
724 }
725 } else if (in_msg.Type == CoherenceRequestType:WRITEBACK_CLEAN_DATA) {
726 Entry cache_entry := getCacheEntry(in_msg.addr);
727 if (is_invalid(cache_entry) &&
728 L2cache.cacheAvail(in_msg.addr) == false) {
720 }
721 else {
722 trigger(Event:L1_WBDIRTYDATA, in_msg.addr,
723 cache_entry, TBEs[in_msg.addr]);
724 }
725 } else if (in_msg.Type == CoherenceRequestType:WRITEBACK_CLEAN_DATA) {
726 Entry cache_entry := getCacheEntry(in_msg.addr);
727 if (is_invalid(cache_entry) &&
728 L2cache.cacheAvail(in_msg.addr) == false) {
729 trigger(Event:L2_Replacement, L2cache.cacheProbe(in_msg.addr),
730 getCacheEntry(L2cache.cacheProbe(in_msg.addr)),
731 TBEs[L2cache.cacheProbe(in_msg.addr)]);
729 Addr victim := L2cache.cacheProbe(in_msg.addr);
730 trigger(Event:L2_Replacement,
731 victim, getCacheEntry(victim), TBEs[victim]);
732 }
733 else {
734 trigger(Event:L1_WBCLEANDATA, in_msg.addr,
735 cache_entry, TBEs[in_msg.addr]);
736 }
737 } else {
738 error("Unexpected message");
739 }
740 }
741 }
742 }
743
744
745 // ACTIONS
746
747 action(a_issueGETS, "a", desc="issue local request globally") {
748 peek(L1requestNetwork_in, RequestMsg) {
749 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
750 out_msg.addr := address;
751 out_msg.Type := CoherenceRequestType:GETS;
752 out_msg.RequestorMachine := MachineType:L2Cache;
753 out_msg.Requestor := machineID;
754 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
755 out_msg.MessageSize := MessageSizeType:Request_Control;
756 }
757 }
758 }
759
760 action(a_issueGETX, "\a", desc="issue local request globally") {
761 peek(L1requestNetwork_in, RequestMsg) {
762 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
763 out_msg.addr := address;
764 out_msg.Type := CoherenceRequestType:GETX;
765 out_msg.RequestorMachine := MachineType:L2Cache;
766 out_msg.Requestor := machineID;
767 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
768 out_msg.MessageSize := MessageSizeType:Request_Control;
769 }
770 }
771 }
772
773 action(b_issuePUTX, "b", desc="Issue PUTX") {
774 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
775 out_msg.addr := address;
776 out_msg.Type := CoherenceRequestType:PUTX;
777 out_msg.RequestorMachine := MachineType:L2Cache;
778 out_msg.Requestor := machineID;
779 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
780 out_msg.MessageSize := MessageSizeType:Writeback_Control;
781 }
782 }
783
784 action(b_issuePUTO, "\b", desc="Issue PUTO") {
785 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
786 out_msg.addr := address;
787 out_msg.Type := CoherenceRequestType:PUTO;
788 out_msg.Requestor := machineID;
789 out_msg.RequestorMachine := MachineType:L2Cache;
790 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
791 out_msg.MessageSize := MessageSizeType:Writeback_Control;
792 }
793 }
794
795 /* PUTO, but local sharers exist */
796 action(b_issuePUTO_ls, "\bb", desc="Issue PUTO") {
797 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
798 out_msg.addr := address;
799 out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
800 out_msg.Requestor := machineID;
801 out_msg.RequestorMachine := MachineType:L2Cache;
802 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
803 out_msg.MessageSize := MessageSizeType:Writeback_Control;
804 }
805 }
806
807 action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") {
808 assert(is_valid(tbe));
809 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
810 out_msg.addr := address;
811 out_msg.Type := CoherenceResponseType:DATA;
812 out_msg.Sender := machineID;
813 out_msg.SenderMachine := MachineType:L2Cache;
814 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
815 out_msg.DataBlk := tbe.DataBlk;
816 // out_msg.Dirty := tbe.Dirty;
817 // shared data should be clean
818 out_msg.Dirty := false;
819 out_msg.MessageSize := MessageSizeType:Response_Data;
820 }
821 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
822 address, tbe.DataBlk);
823 }
824
825 action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") {
826 assert(is_valid(tbe));
827 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
828 out_msg.addr := address;
829 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
830 out_msg.Sender := machineID;
831 out_msg.SenderMachine := MachineType:L2Cache;
832 out_msg.Destination.add(tbe.L1_GetX_ID);
833 out_msg.DataBlk := tbe.DataBlk;
834 out_msg.Dirty := tbe.Dirty;
835 out_msg.Acks := tbe.Local_GETX_IntAcks;
836 out_msg.MessageSize := MessageSizeType:Response_Data;
837 }
838 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
839 address, tbe.DataBlk);
840 }
841
842 action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") {
843 assert(is_valid(tbe));
844 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
845 out_msg.addr := address;
846 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
847 out_msg.Sender := machineID;
848 out_msg.SenderMachine := MachineType:L2Cache;
849 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
850 out_msg.DataBlk := tbe.DataBlk;
851 out_msg.Dirty := tbe.Dirty;
852 out_msg.MessageSize := MessageSizeType:Response_Data;
853 }
854 }
855
856 action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") {
857 assert(is_valid(tbe));
858 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
859 out_msg.addr := address;
860 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
861 out_msg.Sender := machineID;
862 out_msg.SenderMachine := MachineType:L2Cache;
863 out_msg.Destination.add(tbe.Fwd_GetX_ID);
864 out_msg.DataBlk := tbe.DataBlk;
865 out_msg.Dirty := tbe.Dirty;
866 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
867 out_msg.MessageSize := MessageSizeType:Response_Data;
868 }
869 }
870
871 action(cd_sendDataFromTBEToFwdDma, "cd", desc="Send data from TBE to external GETX") {
872 assert(is_valid(tbe));
873 peek(requestNetwork_in, RequestMsg) {
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.add(in_msg.Requestor);
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;
886 }
887 }
888 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
889 address, tbe.DataBlk);
890 }
891
892 action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") {
893 assert(is_valid(tbe));
894 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
895 out_msg.addr := address;
896 out_msg.Type := CoherenceResponseType:DATA;
897 out_msg.Sender := machineID;
898 out_msg.SenderMachine := MachineType:L2Cache;
899 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
900 out_msg.DataBlk := tbe.DataBlk;
901 // out_msg.Dirty := tbe.Dirty;
902 // shared data should be clean
903 out_msg.Dirty := false;
904 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
905 out_msg.MessageSize := MessageSizeType:Response_Data;
906 }
907 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
908 address, tbe.DataBlk);
909 }
910
911 action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") {
912 assert(is_valid(tbe));
913 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
914 out_msg.addr := address;
915 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
916 out_msg.Sender := machineID;
917 out_msg.SenderMachine := MachineType:L2Cache;
918 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
919 out_msg.DataBlk := tbe.DataBlk;
920 out_msg.Dirty := tbe.Dirty;
921 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
922 out_msg.MessageSize := MessageSizeType:Response_Data;
923 }
924 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
925 address, tbe.DataBlk);
926 }
927
928 action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") {
929 assert(is_valid(cache_entry));
930 peek(L1requestNetwork_in, RequestMsg) {
931 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
932 out_msg.addr := address;
933 out_msg.Type := CoherenceResponseType:DATA;
934 out_msg.Sender := machineID;
935 out_msg.SenderMachine := MachineType:L2Cache;
936 out_msg.Destination.add(in_msg.Requestor);
937 out_msg.DataBlk := cache_entry.DataBlk;
938 // out_msg.Dirty := cache_entry.Dirty;
939 // shared data should be clean
940 out_msg.Dirty := false;
941 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
942 }
943 }
944 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
945 address, cache_entry.DataBlk);
946 }
947
948 action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") {
949 assert(is_valid(cache_entry));
950 peek(L1requestNetwork_in, RequestMsg) {
951 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
952 assert(is_valid(tbe));
953 out_msg.addr := address;
954 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
955 out_msg.Sender := machineID;
956 out_msg.SenderMachine := MachineType:L2Cache;
957 out_msg.Destination.add(in_msg.Requestor);
958 out_msg.DataBlk := cache_entry.DataBlk;
959 out_msg.Dirty := cache_entry.Dirty;
960 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
961 out_msg.Acks := tbe.Local_GETX_IntAcks;
962 }
963 }
964 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
965 address, cache_entry.DataBlk);
966 }
967
968 action(dd_sendDataToFwdGETX, "dd", desc="send data") {
969 assert(is_valid(cache_entry));
970 peek(requestNetwork_in, RequestMsg) {
971 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
972 out_msg.addr := address;
973 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
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 out_msg.MessageSize := MessageSizeType:Response_Data;
980 out_msg.Acks := in_msg.Acks;
981 }
982 }
983 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
984 address, cache_entry.DataBlk);
985 }
986
987
988 action(dd_sendDataToFwdGETS, "\dd", desc="send data") {
989 assert(is_valid(cache_entry));
990 peek(requestNetwork_in, RequestMsg) {
991 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
992 out_msg.addr := address;
993 out_msg.Type := CoherenceResponseType:DATA;
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 // shared data should be clean
1000 out_msg.Dirty := false;
1001 out_msg.MessageSize := MessageSizeType:Response_Data;
1002 }
1003 }
1004 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1005 address, cache_entry.DataBlk);
1006 }
1007
1008 action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") {
1009 assert(is_valid(cache_entry));
1010 peek(requestNetwork_in, RequestMsg) {
1011 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
1012 out_msg.addr := address;
1013 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
1014 out_msg.Sender := machineID;
1015 out_msg.SenderMachine := MachineType:L2Cache;
1016 out_msg.Destination.add(in_msg.Requestor);
1017 out_msg.DataBlk := cache_entry.DataBlk;
1018 out_msg.Dirty := cache_entry.Dirty;
1019 out_msg.MessageSize := MessageSizeType:Response_Data;
1020 }
1021 }
1022 }
1023
1024 action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") {
1025 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1026 assert(is_valid(tbe));
1027 out_msg.addr := address;
1028 out_msg.Type := CoherenceResponseType:ACK;
1029 out_msg.Sender := machineID;
1030 out_msg.SenderMachine := MachineType:L2Cache;
1031
1032 out_msg.Destination.add( tbe.Fwd_GetX_ID);
1033 out_msg.Acks := 0 - 1;
1034 out_msg.MessageSize := MessageSizeType:Response_Control;
1035 }
1036 }
1037
1038 action(e_sendAckToL1Requestor, "\e", desc="Send ack with the tokens we've collected thus far.") {
1039 peek(L1requestNetwork_in, RequestMsg) {
1040 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1041 out_msg.addr := address;
1042 out_msg.Type := CoherenceResponseType:ACK;
1043 out_msg.Sender := machineID;
1044 out_msg.SenderMachine := MachineType:L2Cache;
1045 out_msg.Destination.add(in_msg.Requestor);
1046 out_msg.Acks := 0 - 1;
1047 out_msg.MessageSize := MessageSizeType:Response_Control;
1048 }
1049 }
1050 }
1051
1052 action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") {
1053 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1054 assert(is_valid(tbe));
1055 out_msg.addr := address;
1056 out_msg.Type := CoherenceResponseType:ACK;
1057 out_msg.Sender := machineID;
1058 out_msg.SenderMachine := MachineType:L2Cache;
1059 out_msg.Destination.add(tbe.L1_GetX_ID);
1060 out_msg.Acks := 0 - 1;
1061 out_msg.MessageSize := MessageSizeType:Response_Control;
1062 }
1063 }
1064
1065 action(ee_sendLocalInv, "\ee", desc="Send local invalidates") {
1066 assert(is_valid(tbe));
1067 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1068 DPRINTF(RubySlicc, "Address: %#x, Local Sharers: %s, Pending Acks: %d\n",
1069 address, getLocalSharers(cache_entry, address),
1070 tbe.NumIntPendingAcks);
1071 if (isLocalOwnerValid(cache_entry, address)) {
1072 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1073 DPRINTF(RubySlicc, "%s\n", getLocalOwner(cache_entry, address));
1074 }
1075
1076 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1077 out_msg.addr := address;
1078 out_msg.Type := CoherenceRequestType:INV;
1079 out_msg.Requestor := machineID;
1080 out_msg.RequestorMachine := MachineType:L2Cache;
1081 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1082 if (isLocalOwnerValid(cache_entry, address))
1083 {
1084 out_msg.Destination.add(getLocalOwner(cache_entry, address));
1085 }
1086 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1087 }
1088 }
1089
1090 action(ee_sendLocalInvSharersOnly, "\eee", desc="Send local invalidates to sharers if they exist") {
1091
1092 // assert(countLocalSharers(address) > 0);
1093 assert(is_valid(tbe));
1094 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1095
1096 if (countLocalSharers(cache_entry, address) > 0) {
1097 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1098 out_msg.addr := address;
1099 out_msg.Type := CoherenceRequestType:INV;
1100 out_msg.Requestor := machineID;
1101 out_msg.RequestorMachine := MachineType:L2Cache;
1102 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1103 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1104 }
1105 }
1106 }
1107
1108 action(ee_addLocalIntAck, "e\ee", desc="add a local ack to wait for") {
1109 assert(is_valid(tbe));
1110 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1111 }
1112
1113 action(ee_issueLocalInvExceptL1Requestor, "\eeee", desc="Send local invalidates to sharers if they exist") {
1114 peek(L1requestNetwork_in, RequestMsg) {
1115
1116// assert(countLocalSharers(address) > 0);
1117 if (countLocalSharers(cache_entry, address) == 0) {
1118 tbe.NumIntPendingAcks := 0;
1119 }
1120 else {
1121
1122 if (isLocalSharer(cache_entry, address, in_msg.Requestor)) {
1123 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1124 }
1125 else {
1126 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1127 }
1128
1129 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1130 out_msg.addr := address;
1131 out_msg.Type := CoherenceRequestType:INV;
1132 out_msg.Requestor := in_msg.Requestor;
1133 out_msg.RequestorMachine := MachineType:L1Cache;
1134 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1135 out_msg.Destination.remove(in_msg.Requestor);
1136 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1137 }
1138 }
1139 }
1140 }
1141
1142 action(ee_issueLocalInvExceptL1RequestorInTBE, "\eeeeee", desc="Send local invalidates to sharers if they exist") {
1143 assert(is_valid(tbe));
1144 if (countLocalSharers(cache_entry, address) == 0) {
1145 tbe.NumIntPendingAcks := 0;
1146 }
1147 else {
1148 if (isLocalSharer(cache_entry, address, tbe.L1_GetX_ID)) {
1149 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1150 }
1151 else {
1152 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1153 }
1154 }
1155 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1156 out_msg.addr := address;
1157 out_msg.Type := CoherenceRequestType:INV;
1158 out_msg.Requestor := tbe.L1_GetX_ID;
1159 out_msg.RequestorMachine := MachineType:L1Cache;
1160 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1161 out_msg.Destination.remove(tbe.L1_GetX_ID);
1162 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1163 }
1164 }
1165
1166
1167 action(f_sendUnblock, "f", desc="Send unblock to global directory") {
1168 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1169 out_msg.addr := address;
1170 out_msg.Type := CoherenceResponseType:UNBLOCK;
1171 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1172 out_msg.Sender := machineID;
1173 out_msg.SenderMachine := MachineType:L2Cache;
1174 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1175 }
1176 }
1177
1178
1179 action(f_sendExclusiveUnblock, "\f", desc="Send unblock to global directory") {
1180 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1181 out_msg.addr := address;
1182 out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
1183 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1184 out_msg.Sender := machineID;
1185 out_msg.SenderMachine := MachineType:L2Cache;
1186 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1187 }
1188 }
1189
1190
1191 action(g_recordLocalSharer, "g", desc="Record new local sharer from unblock message") {
1192 peek(responseNetwork_in, ResponseMsg) {
1193 recordLocalSharerInDir(cache_entry, in_msg.addr, in_msg.Sender);
1194 }
1195 }
1196
1197 action(g_recordLocalExclusive, "\g", desc="Record new local exclusive sharer from unblock message") {
1198 peek(responseNetwork_in, ResponseMsg) {
1199 recordNewLocalExclusiveInDir(cache_entry, address, in_msg.Sender);
1200 }
1201 }
1202
1203 action(gg_clearLocalSharers, "gg", desc="Clear local sharers") {
1204 removeAllLocalSharersFromDir(cache_entry, address);
1205 }
1206
1207 action(gg_clearSharerFromL1Response, "\gg", desc="Clear sharer from L1 response queue") {
1208 peek(responseNetwork_in, ResponseMsg) {
1209 removeSharerFromDir(cache_entry, in_msg.addr, in_msg.Sender);
1210 }
1211 }
1212
1213 action(gg_clearSharerFromL1Request, "clsl1r", desc="Clear sharer from L1 request queue") {
1214 peek(L1requestNetwork_in, RequestMsg) {
1215 removeSharerFromDir(cache_entry, in_msg.addr, in_msg.Requestor);
1216 }
1217 }
1218
1219 action(gg_clearOwnerFromL1Request, "clol1r", desc="Clear owner from L1 request queue") {
1220 peek(L1requestNetwork_in, RequestMsg) {
1221 removeOwnerFromDir(cache_entry, in_msg.addr, in_msg.Requestor);
1222 }
1223 }
1224
1225 action(h_countLocalSharersExceptRequestor, "h", desc="counts number of acks needed for L1 GETX") {
1226 peek(L1requestNetwork_in, RequestMsg) {
1227 assert(is_valid(tbe));
1228 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, in_msg.Requestor);
1229 }
1230 }
1231
1232 action(h_clearIntAcks, "\h", desc="clear IntAcks") {
1233 assert(is_valid(tbe));
1234 tbe.Local_GETX_IntAcks := 0;
1235 }
1236
1237 action(hh_countLocalSharersExceptL1GETXRequestorInTBE, "hh", desc="counts number of acks needed for L1 GETX") {
1238 assert(is_valid(tbe));
1239 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, tbe.L1_GetX_ID);
1240 }
1241
1242 action(i_copyDataToTBE, "\i", desc="Copy data from response queue to TBE") {
1243 peek(responseNetwork_in, ResponseMsg) {
1244 assert(is_valid(tbe));
1245 tbe.DataBlk := in_msg.DataBlk;
1246 tbe.Dirty := in_msg.Dirty;
1247 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1248 }
1249 }
1250
1251 action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") {
1252 check_allocate(TBEs);
1253 TBEs.allocate(address);
1254 set_tbe(TBEs[address]);
1255 if(is_valid(cache_entry)) {
1256 tbe.DataBlk := cache_entry.DataBlk;
1257 tbe.Dirty := cache_entry.Dirty;
1258 }
1259 tbe.NumIntPendingAcks := 0; // default value
1260 tbe.NumExtPendingAcks := 0; // default value
1261 tbe.Fwd_GetS_IDs.clear();
1262 tbe.L1_GetS_IDs.clear();
1263 }
1264
1265
1266
1267 action(j_forwardGlobalRequestToLocalOwner, "j", desc="Forward external request to local owner") {
1268 peek(requestNetwork_in, RequestMsg) {
1269 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1270 out_msg.addr := in_msg.addr;
1271 out_msg.Type := in_msg.Type;
1272 out_msg.Requestor := machineID;
1273 out_msg.RequestorMachine := MachineType:L2Cache;
1274 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1275 out_msg.Type := in_msg.Type;
1276 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1277 out_msg.Acks := 0 - 1;
1278 }
1279 }
1280 }
1281
1282 action(jd_forwardDmaRequestToLocalOwner, "jd", desc="Forward dma request to local owner") {
1283 peek(requestNetwork_in, RequestMsg) {
1284 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1285 out_msg.addr := in_msg.addr;
1286 out_msg.Type := in_msg.Type;
1287 out_msg.Requestor := in_msg.Requestor;
1288 out_msg.RequestorMachine := in_msg.RequestorMachine;
1289 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1290 out_msg.Type := in_msg.Type;
1291 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1292 out_msg.Acks := 0 - 1;
1293 }
1294 }
1295 }
1296
1297
1298 action(k_forwardLocalGETSToLocalSharer, "k", desc="Forward local request to local sharer/owner") {
1299 peek(L1requestNetwork_in, RequestMsg) {
1300 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1301 out_msg.addr := in_msg.addr;
1302 out_msg.Type := CoherenceRequestType:GETS;
1303 out_msg.Requestor := in_msg.Requestor;
1304 out_msg.RequestorMachine := MachineType:L1Cache;
1305 // should randomize this so one node doesn't get abused more than others
1306 DirEntry dir_entry := getDirEntry(in_msg.addr);
1307 out_msg.Destination.add(dir_entry.Sharers.smallestElement(MachineType:L1Cache));
1308 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1309 }
1310 }
1311 }
1312
1313 action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") {
1314 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1315 assert(is_valid(tbe));
1316 out_msg.addr := address;
1317 out_msg.Type := CoherenceRequestType:GETX;
1318 out_msg.Requestor := tbe.L1_GetX_ID;
1319 out_msg.RequestorMachine := MachineType:L1Cache;
1320 DirEntry dir_entry := getDirEntry(address);
1321 out_msg.Destination.add(dir_entry.Owner);
1322 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1323 out_msg.Acks := 1 + tbe.Local_GETX_IntAcks;
1324 }
1325 }
1326
1327 // same as previous except that it assumes to TBE is present to get number of acks
1328 action(kk_forwardLocalGETXToLocalExclusive, "kk", desc="Forward local request to local owner") {
1329 peek(L1requestNetwork_in, RequestMsg) {
1330 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1331 out_msg.addr := in_msg.addr;
1332 out_msg.Type := CoherenceRequestType:GETX;
1333 out_msg.Requestor := in_msg.Requestor;
1334 out_msg.RequestorMachine := MachineType:L1Cache;
1335 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1336 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1337 out_msg.Acks := 1;
1338 }
1339 }
1340 }
1341
1342 action(kk_forwardLocalGETSToLocalOwner, "\kk", desc="Forward local request to local owner") {
1343 peek(L1requestNetwork_in, RequestMsg) {
1344 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1345 out_msg.addr := in_msg.addr;
1346 out_msg.Type := CoherenceRequestType:GETS;
1347 out_msg.Requestor := in_msg.Requestor;
1348 out_msg.RequestorMachine := MachineType:L1Cache;
1349 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1350 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1351 }
1352 }
1353 }
1354
1355
1356 action(l_writebackAckNeedData, "l", desc="Send writeback ack to L1 requesting data") {
1357 peek(L1requestNetwork_in, RequestMsg) {
1358 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1359 out_msg.addr := in_msg.addr;
1360 out_msg.Type := CoherenceResponseType:WB_ACK_DATA;
1361 out_msg.Sender := machineID;
1362 out_msg.SenderMachine := MachineType:L2Cache;
1363 out_msg.Destination.add(in_msg.Requestor);
1364 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1365 }
1366 }
1367 }
1368
1369 action(l_writebackAckDropData, "\l", desc="Send writeback ack to L1 indicating to drop data") {
1370 peek(L1requestNetwork_in, RequestMsg) {
1371 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1372 out_msg.addr := in_msg.addr;
1373 out_msg.Type := CoherenceResponseType:WB_ACK;
1374 out_msg.Sender := machineID;
1375 out_msg.SenderMachine := MachineType:L2Cache;
1376 out_msg.Destination.add(in_msg.Requestor);
1377 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1378 }
1379 }
1380 }
1381
1382 action(ll_writebackNack, "\ll", desc="Send writeback nack to L1") {
1383 peek(L1requestNetwork_in, RequestMsg) {
1384 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1385 out_msg.addr := in_msg.addr;
1386 out_msg.Type := CoherenceResponseType:WB_NACK;
1387 out_msg.Sender := machineID;
1388 out_msg.SenderMachine := MachineType:L2Cache;
1389 out_msg.Destination.add(in_msg.Requestor);
1390 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1391 }
1392 }
1393 }
1394
1395 action(m_popRequestQueue, "m", desc="Pop request queue.") {
1396 requestNetwork_in.dequeue(clockEdge());
1397 }
1398
1399 action(m_decrementNumberOfMessagesInt, "\m", desc="Decrement the number of messages for which we're waiting") {
1400 peek(responseNetwork_in, ResponseMsg) {
1401 assert(is_valid(tbe));
1402 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + in_msg.Acks;
1403 }
1404 }
1405
1406 action(m_decrementNumberOfMessagesExt, "\mmm", desc="Decrement the number of messages for which we're waiting") {
1407 peek(responseNetwork_in, ResponseMsg) {
1408 assert(is_valid(tbe));
1409 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1410 }
1411 }
1412
1413 action(mm_decrementNumberOfMessagesExt, "\mm", desc="Decrement the number of messages for which we're waiting") {
1414 peek(requestNetwork_in, RequestMsg) {
1415 assert(is_valid(tbe));
1416 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1417 }
1418 }
1419
1420 action(n_popResponseQueue, "n", desc="Pop response queue") {
1421 responseNetwork_in.dequeue(clockEdge());
1422 }
1423
1424 action(n_popTriggerQueue, "\n", desc="Pop trigger queue.") {
1425 triggerQueue_in.dequeue(clockEdge());
1426 }
1427
1428 action(o_popL1RequestQueue, "o", desc="Pop L1 request queue.") {
1429 L1requestNetwork_in.dequeue(clockEdge());
1430 }
1431
1432
1433 action(o_checkForIntCompletion, "\o", desc="Check if we have received all the messages required for completion") {
1434 assert(is_valid(tbe));
1435 if (tbe.NumIntPendingAcks == 0) {
1436 enqueue(triggerQueue_out, TriggerMsg) {
1437 out_msg.addr := address;
1438 out_msg.Type := TriggerType:ALL_ACKS;
1439 }
1440 }
1441 }
1442
1443 action(o_checkForExtCompletion, "\oo", desc="Check if we have received all the messages required for completion") {
1444 assert(is_valid(tbe));
1445 if (tbe.NumExtPendingAcks == 0) {
1446 enqueue(triggerQueue_out, TriggerMsg) {
1447 out_msg.addr := address;
1448 out_msg.Type := TriggerType:ALL_ACKS;
1449 }
1450 }
1451 }
1452
1453
1454 action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") {
1455 enqueue(globalRequestNetwork_out, RequestMsg, response_latency) {
1456 assert(is_valid(tbe));
1457 out_msg.addr := address;
1458 out_msg.Requestor := machineID;
1459 out_msg.RequestorMachine := MachineType:L2Cache;
1460 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1461 if (tbe.Dirty) {
1462 out_msg.Type := CoherenceRequestType:WRITEBACK_DIRTY_DATA;
1463 out_msg.DataBlk := tbe.DataBlk;
1464 out_msg.MessageSize := MessageSizeType:Writeback_Data;
1465 } else {
1466 out_msg.Type := CoherenceRequestType:WRITEBACK_CLEAN_ACK;
1467 // NOTE: in a real system this would not send data. We send
1468 // data here only so we can check it at the memory
1469 out_msg.DataBlk := tbe.DataBlk;
1470 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1471 }
1472 }
1473 }
1474
1475 action( r_setMRU, "\rrr", desc="manually set the MRU bit for cache line" ) {
1476 if(is_valid(cache_entry)) {
1477 L2cache.setMRU(address);
1478 }
1479 }
1480
1481 action( s_recordGetXL1ID, "ss", desc="record local GETX requestor") {
1482 peek(L1requestNetwork_in, RequestMsg) {
1483 assert(is_valid(tbe));
1484 tbe.L1_GetX_ID := in_msg.Requestor;
1485 }
1486 }
1487
1488 action(s_deallocateTBE, "s", desc="Deallocate external TBE") {
1489 TBEs.deallocate(address);
1490 unset_tbe();
1491 }
1492
1493 action( s_recordGetSL1ID, "\ss", desc="record local GETS requestor") {
1494 peek(L1requestNetwork_in, RequestMsg) {
1495 assert(is_valid(tbe));
1496 tbe.L1_GetS_IDs.add(in_msg.Requestor);
1497 }
1498 }
1499
1500 action(t_recordFwdXID, "t", desc="record global GETX requestor") {
1501 peek(requestNetwork_in, RequestMsg) {
1502 assert(is_valid(tbe));
1503 tbe.Fwd_GetX_ID := in_msg.Requestor;
1504 tbe.Fwd_GETX_ExtAcks := in_msg.Acks;
1505 }
1506 }
1507
1508 action(t_recordFwdSID, "\t", desc="record global GETS requestor") {
1509 peek(requestNetwork_in, RequestMsg) {
1510 assert(is_valid(tbe));
1511 tbe.Fwd_GetS_IDs.clear();
1512 tbe.Fwd_GetS_IDs.add(in_msg.Requestor);
1513 }
1514 }
1515
1516
1517 action(u_writeCleanDataToCache, "wCd", desc="Write clean data to cache") {
1518 peek(L1requestNetwork_in, RequestMsg) {
1519 assert(is_valid(cache_entry));
1520 cache_entry.DataBlk := in_msg.DataBlk;
1521 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1522 address, cache_entry.DataBlk);
1523 assert(cache_entry.Dirty == false);
1524 }
1525 }
1526
1527 action(u_writeDirtyDataToCache, "wDd", desc="Write dirty data to cache") {
1528 peek(L1requestNetwork_in, RequestMsg) {
1529 assert(is_valid(cache_entry));
1530 cache_entry.DataBlk := in_msg.DataBlk;
1531 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1532 address, cache_entry.DataBlk);
1533 cache_entry.Dirty := true;
1534 }
1535 }
1536
1537 action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") {
1538 set_cache_entry(L2cache.allocate(address, new Entry));
1539 }
1540
1541 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
1542 L2cache.deallocate(address);
1543 unset_cache_entry();
1544 }
1545
1546 action(uu_profileMiss, "\um", desc="Profile the demand miss") {
1547 ++L2cache.demand_misses;
1548 }
1549
1550 action(uu_profileHit, "\uh", desc="Profile the demand hit") {
1551 ++L2cache.demand_hits;
1552 }
1553
1554 action(y_copyCacheStateToDir, "y", desc="Copy cache state to directory state") {
1555 copyCacheStateToDir(cache_entry, address);
1556 }
1557
1558 action(y_copyDirToCacheAndRemove, "/y", desc="Copy dir state to cache and remove") {
1559 copyDirToCache(cache_entry, address);
1560 localDirectory.deallocate(address);
1561 }
1562
1563 action(zz_recycleGlobalRequestQueue, "\zglb", desc="Send the head of the mandatory queue to the back of the queue.") {
1564 peek(requestNetwork_in, RequestMsg) {
1565 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1566 }
1567 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1568 }
1569
1570 action(zz_recycleL1RequestQueue, "\zl1", desc="Send the head of the mandatory queue to the back of the queue.") {
1571 peek(L1requestNetwork_in, RequestMsg) {
1572 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1573 }
1574 L1requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1575 }
1576
1577 action(st_stallAndWaitL1RequestQueue, "st", desc="Stall and wait on the address") {
1578 stall_and_wait(L1requestNetwork_in, address);
1579 }
1580
1581 action(wa_wakeUpDependents, "wa", desc="Wake up any requests waiting for this address") {
1582 wakeUpAllBuffers(address);
1583 }
1584
1585 action(da_sendDmaAckUnblock, "da", desc="Send dma ack to global directory") {
1586 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1587 out_msg.addr := address;
1588 out_msg.Type := CoherenceResponseType:DMA_ACK;
1589 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1590 out_msg.Sender := machineID;
1591 out_msg.SenderMachine := MachineType:L2Cache;
1592 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1593 }
1594 }
1595
1596
1597
1598 //*****************************************************
1599 // TRANSITIONS
1600 //*****************************************************
1601
1602 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_PUTO, L1_PUTS, L1_PUTS_only, L1_PUTX}) {
1603 st_stallAndWaitL1RequestQueue;
1604 }
1605
1606 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_GETX, L1_GETS}) {
1607 st_stallAndWaitL1RequestQueue;
1608 }
1609
1610 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, ILXW, OW, SW, OXW, OLSXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, IGMLS, IGMO, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, L2_Replacement) {
1611 zz_recycleL1RequestQueue;
1612 }
1613
1614 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Fwd_GETX, Fwd_GETS, Fwd_DMA}) {
1615 zz_recycleGlobalRequestQueue;
1616 }
1617
1618 transition({OGMIO, IGMIO, IGMO}, Fwd_DMA) {
1619 zz_recycleGlobalRequestQueue;
1620 }
1621
1622 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Inv}) {
1623 zz_recycleGlobalRequestQueue;
1624 }
1625
1626 transition({IGM, IGS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Own_GETX}) {
1627 zz_recycleGlobalRequestQueue;
1628 }
1629
1630 // must happened because we forwarded GETX to local exclusive trying to do wb
1631 transition({I, M, O, ILS, ILOX, OLS, OLSX, SLS, S}, L1_PUTX) {
1632 ll_writebackNack;
1633 o_popL1RequestQueue;
1634 }
1635
1636 transition({M}, {L1_PUTS, L1_PUTO} ) {
1637 ll_writebackNack;
1638 o_popL1RequestQueue;
1639 }
1640
1641 transition({ILS, OLSX}, L1_PUTO){
1642 ll_writebackNack;
1643 o_popL1RequestQueue;
1644 }
1645
1646// happened if we forwarded GETS to exclusive who tried to do writeback
1647// ?? should we just Nack these instead? Could be a bugs here
1648 transition(ILO, L1_PUTX, ILOW) {
1649 l_writebackAckNeedData;
1650 o_popL1RequestQueue;
1651 }
1652
1653 // this can happen if we forwarded a L1_GETX to exclusiver after it issued a PUTX
1654 transition(ILOS, L1_PUTX, ILOSW) {
1655 l_writebackAckNeedData;
1656 o_popL1RequestQueue;
1657 }
1658
1659 transition(ILOSX, L1_PUTX, ILOSXW) {
1660 l_writebackAckNeedData;
1661 o_popL1RequestQueue;
1662 }
1663
1664 // must happened because we got Inv when L1 attempted PUTS
1665 transition(I, L1_PUTS) {
1666 ll_writebackNack;
1667 o_popL1RequestQueue;
1668 }
1669
1670 transition(I, L1_PUTO) {
1671 ll_writebackNack;
1672 o_popL1RequestQueue;
1673 }
1674
1675 // FORWARDED REQUESTS
1676
1677 transition({ILO, ILX, ILOX}, Fwd_GETS, IFGS) {
1678 i_allocateTBE;
1679 t_recordFwdSID;
1680 j_forwardGlobalRequestToLocalOwner;
1681 m_popRequestQueue;
1682 }
1683
1684 transition({ILOS, ILOSX}, Fwd_GETS, ISFGS) {
1685 i_allocateTBE;
1686 t_recordFwdSID;
1687 j_forwardGlobalRequestToLocalOwner;
1688 m_popRequestQueue;
1689 }
1690
1691 transition(ILOS, Fwd_DMA, ILOSD) {
1692 i_allocateTBE;
1693 jd_forwardDmaRequestToLocalOwner;
1694 m_popRequestQueue;
1695 }
1696
1697 transition(ILOSD, DmaAck, ILOS) {
1698 s_deallocateTBE;
1699 da_sendDmaAckUnblock;
1700 n_popResponseQueue;
1701 wa_wakeUpDependents;
1702 }
1703
1704 transition(ILOSX, Fwd_DMA, ILOSXD) {
1705 i_allocateTBE;
1706 t_recordFwdSID;
1707 jd_forwardDmaRequestToLocalOwner;
1708 m_popRequestQueue;
1709 }
1710
1711 transition(ILOSXD, DmaAck, ILOSX) {
1712 s_deallocateTBE;
1713 da_sendDmaAckUnblock;
1714 n_popResponseQueue;
1715 wa_wakeUpDependents;
1716 }
1717
1718 transition(ILO, Fwd_DMA, ILOD) {
1719 i_allocateTBE;
1720 t_recordFwdSID;
1721 jd_forwardDmaRequestToLocalOwner;
1722 m_popRequestQueue;
1723 }
1724
1725 transition(ILOD, DmaAck, ILO) {
1726 s_deallocateTBE;
1727 da_sendDmaAckUnblock;
1728 n_popResponseQueue;
1729 wa_wakeUpDependents;
1730 }
1731
1732 transition(ILX, Fwd_DMA, ILXD) {
1733 i_allocateTBE;
1734 t_recordFwdSID;
1735 jd_forwardDmaRequestToLocalOwner;
1736 m_popRequestQueue;
1737 }
1738
1739 transition(ILXD, DmaAck, ILX) {
1740 s_deallocateTBE;
1741 da_sendDmaAckUnblock;
1742 n_popResponseQueue;
1743 wa_wakeUpDependents;
1744 }
1745
1746 transition(ILOX, Fwd_DMA, ILOXD) {
1747 i_allocateTBE;
1748 t_recordFwdSID;
1749 jd_forwardDmaRequestToLocalOwner;
1750 m_popRequestQueue;
1751 }
1752
1753 transition(ILOXD, DmaAck, ILOX) {
1754 s_deallocateTBE;
1755 da_sendDmaAckUnblock;
1756 n_popResponseQueue;
1757 wa_wakeUpDependents;
1758 }
1759
1760 transition({ILOS, ILOSX, ILO, ILX, ILOX, ILXW}, Data) {
1761 i_copyDataToTBE;
1762 c_sendDataFromTBEToFwdGETS;
1763 s_deallocateTBE;
1764 n_popResponseQueue;
1765 }
1766
1767 transition(IFGS, Data, ILO) {
1768 i_copyDataToTBE;
1769 c_sendDataFromTBEToFwdGETS;
1770 s_deallocateTBE;
1771 n_popResponseQueue;
1772 wa_wakeUpDependents;
1773 }
1774
1775 transition(ISFGS, Data, ILOS) {
1776 i_copyDataToTBE;
1777 c_sendDataFromTBEToFwdGETS;
1778 s_deallocateTBE;
1779 n_popResponseQueue;
1780 wa_wakeUpDependents;
1781 }
1782
1783 transition(IFGS, Data_Exclusive, I) {
1784 i_copyDataToTBE;
1785 c_sendExclusiveDataFromTBEToFwdGETS;
1786 gg_clearLocalSharers;
1787 s_deallocateTBE;
1788 n_popResponseQueue;
1789 wa_wakeUpDependents;
1790 }
1791
1792
1793 transition({ILX, ILO, ILOX}, Fwd_GETX, IFGX) {
1794 i_allocateTBE;
1795 t_recordFwdXID;
1796 j_forwardGlobalRequestToLocalOwner;
1797 m_popRequestQueue;
1798 }
1799
1800 transition(IFGX, {Data_Exclusive, Data}, I) {
1801 i_copyDataToTBE;
1802 c_sendDataFromTBEToFwdGETX;
1803 gg_clearLocalSharers;
1804 s_deallocateTBE;
1805 n_popResponseQueue;
1806 wa_wakeUpDependents;
1807 }
1808
1809 transition({ILOSX, ILOS}, Fwd_GETX, IFGXX) {
1810 i_allocateTBE;
1811 t_recordFwdXID;
1812 j_forwardGlobalRequestToLocalOwner;
1813 ee_sendLocalInvSharersOnly;
1814 ee_addLocalIntAck;
1815 m_popRequestQueue;
1816 }
1817
1818
1819 transition(IFGXX, IntAck) {
1820 m_decrementNumberOfMessagesInt;
1821 o_checkForIntCompletion;
1822 n_popResponseQueue;
1823 }
1824
1825 transition(IFGXX, Data_Exclusive) {
1826 i_copyDataToTBE;
1827 m_decrementNumberOfMessagesInt;
1828 o_checkForIntCompletion;
1829 n_popResponseQueue;
1830 }
1831
1832 transition(IFGXX, All_Acks, I) {
1833 c_sendDataFromTBEToFwdGETX;
1834 gg_clearLocalSharers;
1835 s_deallocateTBE;
1836 n_popTriggerQueue;
1837 wa_wakeUpDependents;
1838 }
1839
1840
1841 // transition({O, OX}, Fwd_GETX, I) {
1842 transition(O, Fwd_GETX, I) {
1843 dd_sendDataToFwdGETX;
1844 y_copyCacheStateToDir;
1845 rr_deallocateL2CacheBlock;
1846 m_popRequestQueue;
1847 }
1848
1849 transition({O, OLS}, Fwd_GETS) {
1850 dd_sendDataToFwdGETS;
1851 m_popRequestQueue;
1852 }
1853
1854 transition({O, OLS}, Fwd_DMA) {
1855 dd_sendDataToFwdGETS;
1856 da_sendDmaAckUnblock;
1857 m_popRequestQueue;
1858 }
1859
1860 // transition({OLSX, OX}, Fwd_GETS, O) {
1861 transition(OLSX, Fwd_GETS, OLS) {
1862 dd_sendDataToFwdGETS;
1863 m_popRequestQueue;
1864 }
1865
1866 transition(OLSX, Fwd_DMA) {
1867 dd_sendDataToFwdGETS;
1868 da_sendDmaAckUnblock;
1869 m_popRequestQueue;
1870 }
1871
1872 transition(M, Fwd_GETX, I) {
1873 dd_sendDataToFwdGETX;
1874 rr_deallocateL2CacheBlock;
1875 m_popRequestQueue;
1876 }
1877
1878 // MAKE THIS THE SAME POLICY FOR NOW
1879
1880 // transition(M, Fwd_GETS, O) {
1881 // dd_sendDataToFwdGETS;
1882 // m_popRequestQueue;
1883 // }
1884
1885 transition(M, Fwd_GETS, I) {
1886 dd_sendExclusiveDataToFwdGETS;
1887 rr_deallocateL2CacheBlock;
1888 m_popRequestQueue;
1889 }
1890
1891 transition(M, Fwd_DMA) {
1892 dd_sendExclusiveDataToFwdGETS;
1893 da_sendDmaAckUnblock;
1894 m_popRequestQueue;
1895 }
1896
1897 transition({OLS, OLSX}, Fwd_GETX, OLSF) {
1898 i_allocateTBE;
1899 t_recordFwdXID;
1900 ee_sendLocalInv;
1901 m_popRequestQueue;
1902 }
1903
1904 transition(OLSF, IntAck) {
1905 m_decrementNumberOfMessagesInt;
1906 o_checkForIntCompletion;
1907 n_popResponseQueue;
1908 }
1909
1910 transition(OLSF, All_Acks, I) {
1911 c_sendDataFromTBEToFwdGETX;
1912 gg_clearLocalSharers;
1913 s_deallocateTBE;
1914 rr_deallocateL2CacheBlock;
1915 n_popTriggerQueue;
1916 wa_wakeUpDependents;
1917 }
1918
1919
1920
1921 // INVALIDATIONS FROM GLOBAL DIRECTORY
1922
1923 transition({IGM, IGS}, Inv) {
1924 t_recordFwdXID;
1925 e_sendAck;
1926 m_popRequestQueue;
1927 }
1928
1929 transition({I,NP}, Inv) {
1930 i_allocateTBE;
1931 t_recordFwdXID;
1932 e_sendAck;
1933 s_deallocateTBE;
1934 m_popRequestQueue;
1935 }
1936
1937 // NEED INV for S state
1938
1939 transition({ILS, ILO, ILX}, Inv, II) {
1940 i_allocateTBE;
1941 t_recordFwdXID;
1942 ee_sendLocalInv;
1943 gg_clearLocalSharers;
1944 m_popRequestQueue;
1945 }
1946
1947 transition(SLS, Inv, II) {
1948 i_allocateTBE;
1949 t_recordFwdXID;
1950 ee_sendLocalInv;
1951 rr_deallocateL2CacheBlock;
1952 m_popRequestQueue;
1953 }
1954
1955 transition(II, IntAck) {
1956 m_decrementNumberOfMessagesInt;
1957 o_checkForIntCompletion;
1958 n_popResponseQueue;
1959 }
1960
1961 transition(II, All_Acks, I) {
1962 e_sendAck;
1963 s_deallocateTBE;
1964 n_popTriggerQueue;
1965 wa_wakeUpDependents;
1966 }
1967
1968 transition(S, Inv, I) {
1969 i_allocateTBE;
1970 t_recordFwdXID;
1971 e_sendAck;
1972 s_deallocateTBE;
1973 rr_deallocateL2CacheBlock;
1974 m_popRequestQueue;
1975 }
1976
1977
1978 // LOCAL REQUESTS SATISFIED LOCALLY
1979
1980 transition(OLSX, L1_GETX, IFLOX) {
1981 i_allocateTBE;
1982 s_recordGetXL1ID;
1983 // count number of INVs needed that doesn't include requestor
1984 h_countLocalSharersExceptRequestor;
1985 // issue INVs to everyone except requestor
1986 ee_issueLocalInvExceptL1Requestor;
1987 d_sendDataToL1GETX
1988 y_copyCacheStateToDir;
1989 r_setMRU;
1990 rr_deallocateL2CacheBlock;
1991 uu_profileHit;
1992 o_popL1RequestQueue;
1993 }
1994
1995 transition(IFLOX, Exclusive_Unblock, ILX) {
1996 g_recordLocalExclusive;
1997 s_deallocateTBE;
1998 n_popResponseQueue;
1999 wa_wakeUpDependents;
2000 }
2001
2002 transition(OLSX, L1_GETS, OLSXS) {
2003 d_sendDataToL1GETS;
2004 r_setMRU;
2005 uu_profileHit;
2006 o_popL1RequestQueue;
2007 }
2008
2009 transition(OLSXS, Unblock, OLSX) {
2010 g_recordLocalSharer;
2011 n_popResponseQueue;
2012 wa_wakeUpDependents;
2013 }
2014
2015 // after this, can't get Fwd_GETX
2016 transition(IGMO, Own_GETX) {
2017 mm_decrementNumberOfMessagesExt;
2018 o_checkForExtCompletion;
2019 m_popRequestQueue;
2020
2021 }
2022
2023
2024 transition(ILX, L1_GETS, IFLOXX) {
2025 kk_forwardLocalGETSToLocalOwner;
2026 uu_profileMiss;
2027 o_popL1RequestQueue;
2028 }
2029
2030 transition(ILOSX, L1_GETS, IFLOSX) {
2031 kk_forwardLocalGETSToLocalOwner;
2032 uu_profileMiss;
2033 o_popL1RequestQueue;
2034 }
2035
2036 transition({ILOS, ILO}, L1_GETS, IFLO) {
2037 kk_forwardLocalGETSToLocalOwner;
2038 uu_profileMiss;
2039 o_popL1RequestQueue;
2040 }
2041
2042 transition(ILS, L1_GETS, IFLS) {
2043 k_forwardLocalGETSToLocalSharer;
2044 uu_profileMiss;
2045 o_popL1RequestQueue;
2046 }
2047
2048 transition({ILX, ILOX}, L1_GETX, IFLOXX) {
2049 kk_forwardLocalGETXToLocalExclusive;
2050 e_sendAckToL1Requestor;
2051 uu_profileMiss;
2052 o_popL1RequestQueue;
2053 }
2054
2055 transition(ILOX, L1_GETS, IFLOX) {
2056 kk_forwardLocalGETSToLocalOwner;
2057 uu_profileMiss;
2058 o_popL1RequestQueue;
2059 }
2060
2061 transition(IFLOX, Unblock, ILOSX) {
2062 g_recordLocalSharer;
2063 n_popResponseQueue;
2064 wa_wakeUpDependents;
2065 }
2066
2067 transition(IFLS, Unblock, ILS) {
2068 g_recordLocalSharer;
2069 n_popResponseQueue;
2070 wa_wakeUpDependents;
2071 }
2072
2073 transition(IFLOXX, Unblock, ILOSX) {
2074 g_recordLocalSharer;
2075 n_popResponseQueue;
2076 wa_wakeUpDependents;
2077 }
2078
2079 transition(IFLOSX, Unblock, ILOSX) {
2080 g_recordLocalSharer;
2081 n_popResponseQueue;
2082 wa_wakeUpDependents;
2083 }
2084
2085 transition({IFLOSX, IFLOXX}, Exclusive_Unblock, ILX) {
2086 g_recordLocalExclusive;
2087 n_popResponseQueue;
2088 wa_wakeUpDependents;
2089 }
2090
2091 transition(IFLO, Unblock, ILOS) {
2092 g_recordLocalSharer;
2093 n_popResponseQueue;
2094 wa_wakeUpDependents;
2095 }
2096
2097
2098 transition(ILOSX, L1_GETX, IFLXO) {
2099 i_allocateTBE;
2100 s_recordGetXL1ID;
2101 h_countLocalSharersExceptRequestor;
2102 ee_issueLocalInvExceptL1Requestor;
2103 k_forwardLocalGETXToLocalOwner;
2104 e_sendAckToL1RequestorFromTBE;
2105 uu_profileMiss;
2106 o_popL1RequestQueue;
2107 }
2108
2109 transition(IFLXO, Exclusive_Unblock, ILX) {
2110 g_recordLocalExclusive;
2111 s_deallocateTBE;
2112 n_popResponseQueue;
2113 wa_wakeUpDependents;
2114 }
2115
2116 // LOCAL REQUESTS THAT MUST ISSUE
2117
2118 transition(NP, {L1_PUTS, L1_PUTX, L1_PUTO}) {
2119 ll_writebackNack;
2120 o_popL1RequestQueue;
2121 }
2122
2123 transition({NP, I}, L1_GETS, IGS) {
2124 i_allocateTBE;
2125 s_recordGetSL1ID;
2126 a_issueGETS;
2127 uu_profileMiss;
2128 o_popL1RequestQueue;
2129 }
2130
2131 transition({NP, I}, L1_GETX, IGM) {
2132 i_allocateTBE;
2133 s_recordGetXL1ID;
2134 a_issueGETX;
2135 uu_profileMiss;
2136 o_popL1RequestQueue;
2137 }
2138
2139 transition(S, L1_GETX, IGM) {
2140 i_allocateTBE;
2141 s_recordGetXL1ID;
2142 a_issueGETX;
2143 y_copyCacheStateToDir;
2144 r_setMRU;
2145 rr_deallocateL2CacheBlock;
2146 uu_profileMiss;
2147 o_popL1RequestQueue;
2148 }
2149
2150 transition(ILS, L1_GETX, IGMLS) {
2151 i_allocateTBE;
2152 s_recordGetXL1ID;
2153 a_issueGETX;
2154 // count number of INVs (just sharers?) needed that doesn't include requestor
2155 h_countLocalSharersExceptRequestor;
2156 uu_profileMiss;
2157 o_popL1RequestQueue;
2158 }
2159
2160 transition(IGMLS, Inv) {
2161 t_recordFwdXID;
2162 ee_sendLocalInv;
2163 m_popRequestQueue;
2164 }
2165
2166 transition(IGMLS, IntAck) {
2167 m_decrementNumberOfMessagesInt;
2168 o_checkForIntCompletion;
2169 n_popResponseQueue;
2170 }
2171
2172 transition(IGMLS, All_Acks, IGM) {
2173 gg_clearLocalSharers;
2174 h_clearIntAcks;
2175 e_sendAck;
2176 n_popTriggerQueue;
2177 }
2178
2179 // transition(IGMLS, ExtAck, IGMO) {
2180 transition(IGMLS, ExtAck) {
2181 m_decrementNumberOfMessagesExt;
2182 o_checkForExtCompletion;
2183 n_popResponseQueue;
2184 }
2185
2186 transition(IGMLS, {Data, Data_Exclusive}, IGMO) {
2187 ee_issueLocalInvExceptL1RequestorInTBE;
2188 i_copyDataToTBE;
2189 m_decrementNumberOfMessagesExt;
2190 o_checkForExtCompletion;
2191 n_popResponseQueue;
2192 }
2193
2194
2195 transition(ILOS, L1_GETX, IGMIO) {
2196 i_allocateTBE;
2197 s_recordGetXL1ID;
2198 a_issueGETX;
2199 uu_profileMiss;
2200 o_popL1RequestQueue;
2201 }
2202
2203 // new exclusive happened while sharer attempted writeback
2204 transition(ILX, {L1_PUTS, L1_PUTS_only, L1_PUTO}) {
2205 ll_writebackNack;
2206 o_popL1RequestQueue;
2207 }
2208
2209 transition(S, L1_PUTS) {
2210 ll_writebackNack;
2211 o_popL1RequestQueue;
2212 }
2213
2214 transition(OLS, L1_GETX, OGMIO) {
2215 i_allocateTBE;
2216 s_recordGetXL1ID;
2217 a_issueGETX;
2218 h_countLocalSharersExceptRequestor;
2219 // COPY DATA FROM CACHE TO TBE (happens during i_allocateTBE)
2220 y_copyCacheStateToDir;
2221 rr_deallocateL2CacheBlock;
2222 uu_profileMiss;
2223 o_popL1RequestQueue;
2224 }
2225
2226 transition(OGMIO, Fwd_GETS) {
2227 t_recordFwdSID;
2228 c_sendDataFromTBEToFwdGETS;
2229 m_popRequestQueue;
2230 }
2231
2232 transition(ILO, L1_GETX, IGMIO) {
2233 i_allocateTBE;
2234 s_recordGetXL1ID;
2235 a_issueGETX;
2236 // the following, of course, returns 0 sharers but do anyways for consistency
2237 h_countLocalSharersExceptRequestor;
2238 uu_profileMiss;
2239 o_popL1RequestQueue;
2240 }
2241
2242 transition({ILO, ILOX}, L1_PUTS) {
2243 ll_writebackNack;
2244 o_popL1RequestQueue;
2245 }
2246
2247 transition(IGMIO, Fwd_GETX, IGMIOF) {
2248 t_recordFwdXID;
2249 j_forwardGlobalRequestToLocalOwner;
2250 ee_sendLocalInvSharersOnly;
2251 ee_addLocalIntAck;
2252 m_popRequestQueue;
2253 }
2254
2255 transition(IGMIO, Fwd_GETS, IGMIOFS) {
2256 t_recordFwdSID;
2257 j_forwardGlobalRequestToLocalOwner;
2258 m_popRequestQueue;
2259 }
2260
2261 transition(IGMIOFS, Data, IGMIO) {
2262 i_copyDataToTBE;
2263 c_sendDataFromTBEToFwdGETS;
2264 n_popResponseQueue;
2265 }
2266
2267 transition(OGMIO, Fwd_GETX, OGMIOF) {
2268 t_recordFwdXID;
2269 ee_sendLocalInvSharersOnly;
2270 m_popRequestQueue;
2271 }
2272
2273 transition(OGMIOF, IntAck) {
2274 m_decrementNumberOfMessagesInt;
2275 o_checkForIntCompletion;
2276 n_popResponseQueue;
2277 }
2278
2279 transition(OGMIOF, All_Acks, IGM) {
2280 gg_clearLocalSharers;
2281 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2282 c_sendDataFromTBEToFwdGETX;
2283 n_popTriggerQueue;
2284 }
2285
2286 transition(IGMIOF, IntAck) {
2287 m_decrementNumberOfMessagesInt;
2288 o_checkForIntCompletion;
2289 n_popResponseQueue;
2290 }
2291
2292 transition(IGMIOF, Data_Exclusive) {
2293 i_copyDataToTBE;
2294 m_decrementNumberOfMessagesInt;
2295 o_checkForIntCompletion;
2296 n_popResponseQueue;
2297 }
2298
2299 transition(IGMIOF, All_Acks, IGM) {
2300 gg_clearLocalSharers;
2301 c_sendDataFromTBEToFwdGETX;
2302 n_popTriggerQueue;
2303 }
2304
2305 transition(IGMIO, All_Acks, IGMO) {
2306 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2307 ee_issueLocalInvExceptL1RequestorInTBE;
2308 k_forwardLocalGETXToLocalOwner;
2309 e_sendAckToL1RequestorFromTBE;
2310 n_popTriggerQueue;
2311 }
2312
2313 transition(OGMIO, All_Acks, IGMO) {
2314 ee_issueLocalInvExceptL1RequestorInTBE;
2315 c_sendDataFromTBEToL1GETX;
2316 n_popTriggerQueue;
2317 }
2318
2319 transition({IGMIO, OGMIO}, Own_GETX) {
2320 mm_decrementNumberOfMessagesExt;
2321 o_checkForExtCompletion;
2322 m_popRequestQueue;
2323
2324 }
2325
2326 transition(IGM, {Data, Data_Exclusive}, IGMO) {
2327 i_copyDataToTBE;
2328 m_decrementNumberOfMessagesExt;
2329 o_checkForExtCompletion;
2330 n_popResponseQueue;
2331 }
2332
2333 transition({IGM, IGMIO, OGMIO}, ExtAck) {
2334 m_decrementNumberOfMessagesExt;
2335 o_checkForExtCompletion;
2336 n_popResponseQueue;
2337 }
2338
2339 transition(IGMO, ExtAck) {
2340 m_decrementNumberOfMessagesExt;
2341 o_checkForExtCompletion;
2342 n_popResponseQueue;
2343 }
2344
2345 transition(IGS, Data) {
2346 i_copyDataToTBE;
2347 m_decrementNumberOfMessagesExt;
2348 c_sendDataFromTBEToL1GETS;
2349 n_popResponseQueue;
2350 }
2351
2352 transition(IGS, Data_Exclusive) {
2353 i_copyDataToTBE;
2354 m_decrementNumberOfMessagesExt;
2355 c_sendExclusiveDataFromTBEToL1GETS;
2356 n_popResponseQueue;
2357 }
2358
2359 transition(IGS, Unblock, ILS) {
2360 g_recordLocalSharer;
2361 f_sendUnblock;
2362 s_deallocateTBE;
2363 n_popResponseQueue;
2364 wa_wakeUpDependents;
2365 }
2366
2367 transition(IGS, Exclusive_Unblock, ILX) {
2368 g_recordLocalExclusive;
2369 f_sendExclusiveUnblock;
2370 s_deallocateTBE;
2371 n_popResponseQueue;
2372 wa_wakeUpDependents;
2373 }
2374
2375 transition(IGMO, All_Acks) {
2376 c_sendDataFromTBEToL1GETX;
2377 n_popTriggerQueue;
2378 }
2379
2380 transition(IGMO, Exclusive_Unblock, ILX) {
2381 g_recordLocalExclusive;
2382 f_sendExclusiveUnblock;
2383 s_deallocateTBE;
2384 n_popResponseQueue;
2385 wa_wakeUpDependents;
2386 }
2387
2388
2389 transition(SLS, L1_GETX, IGMLS) {
2390 i_allocateTBE;
2391 s_recordGetXL1ID;
2392 a_issueGETX;
2393 // count number of INVs needed that doesn't include requestor
2394 h_countLocalSharersExceptRequestor;
2395 // issue INVs to everyone except requestor
2396 y_copyCacheStateToDir;
2397 rr_deallocateL2CacheBlock;
2398 uu_profileMiss;
2399 o_popL1RequestQueue;
2400
2401 }
2402
2403 transition(SLS, L1_GETS, SLSS ) {
2404 d_sendDataToL1GETS;
2405 r_setMRU;
2406 uu_profileHit;
2407 o_popL1RequestQueue;
2408 }
2409
2410 transition(SLSS, Unblock, SLS) {
2411 g_recordLocalSharer;
2412 n_popResponseQueue;
2413 wa_wakeUpDependents;
2414 }
2415
2416
2417 transition(O, L1_GETX, IGMO) {
2418 i_allocateTBE;
2419 s_recordGetXL1ID;
2420 a_issueGETX;
2421 y_copyCacheStateToDir;
2422 rr_deallocateL2CacheBlock;
2423 uu_profileMiss;
2424 o_popL1RequestQueue;
2425 }
2426
2427 transition(OLS, L1_GETS, OLSS) {
2428 d_sendDataToL1GETS;
2429 r_setMRU;
2430 uu_profileHit;
2431 o_popL1RequestQueue;
2432 }
2433
2434 transition(OLSS, Unblock, OLS) {
2435 g_recordLocalSharer;
2436 n_popResponseQueue;
2437 wa_wakeUpDependents;
2438 }
2439
2440 transition(IGMO, Fwd_GETX, IGM) {
2441 t_recordFwdXID;
2442 c_sendDataFromTBEToFwdGETX;
2443 m_popRequestQueue;
2444
2445 }
2446
2447 transition(IGMO, Fwd_GETS) {
2448 t_recordFwdSID;
2449 c_sendDataFromTBEToFwdGETS;
2450 m_popRequestQueue;
2451 }
2452
2453
2454 // LOCAL REQUESTS SATISFIED DIRECTLY BY L2
2455
2456 transition(M, L1_GETX, MM) {
2457 i_allocateTBE;
2458 // should count 0 of course
2459 h_countLocalSharersExceptRequestor;
2460 d_sendDataToL1GETX;
2461 y_copyCacheStateToDir;
2462 rr_deallocateL2CacheBlock;
2463 s_deallocateTBE;
2464 uu_profileHit;
2465 o_popL1RequestQueue;
2466 }
2467
2468 transition(MM, Exclusive_Unblock, ILX) {
2469 g_recordLocalExclusive;
2470 n_popResponseQueue;
2471 wa_wakeUpDependents;
2472 }
2473
2474 transition(M, L1_GETS, OO) {
2475 i_allocateTBE;
2476 // should count 0 of course
2477 h_countLocalSharersExceptRequestor;
2478 d_sendDataToL1GETX;
2479 r_setMRU;
2480 s_deallocateTBE;
2481 uu_profileHit;
2482 o_popL1RequestQueue;
2483 }
2484
2485 transition(S, L1_GETS, SS) {
2486 d_sendDataToL1GETS;
2487 r_setMRU;
2488 uu_profileHit;
2489 o_popL1RequestQueue;
2490 }
2491
2492 transition(SS, Unblock, SLS) {
2493 g_recordLocalSharer;
2494 n_popResponseQueue;
2495 wa_wakeUpDependents;
2496 }
2497
2498 transition(O, L1_GETS, OO) {
2499 d_sendDataToL1GETS;
2500 r_setMRU;
2501 uu_profileHit;
2502 o_popL1RequestQueue;
2503 }
2504
2505 transition(OO, Unblock, OLS) {
2506 g_recordLocalSharer;
2507 n_popResponseQueue;
2508 wa_wakeUpDependents;
2509 }
2510
2511 transition(OO, Exclusive_Unblock, ILX) {
2512 g_recordLocalExclusive
2513 y_copyCacheStateToDir;
2514 rr_deallocateL2CacheBlock;
2515 n_popResponseQueue;
2516 wa_wakeUpDependents;
2517 }
2518
2519
2520 // L1 WRITEBACKS
2521 transition(ILO, L1_PUTO, ILOW) {
2522 l_writebackAckNeedData;
2523 o_popL1RequestQueue;
2524 }
2525
2526 transition(ILOX, L1_PUTO, ILOXW) {
2527 l_writebackAckNeedData;
2528 o_popL1RequestQueue;
2529 }
2530
2531
2532 transition(ILOS, L1_PUTO, ILOSW) {
2533 l_writebackAckNeedData;
2534 o_popL1RequestQueue;
2535 }
2536
2537 transition(ILOSX, L1_PUTO, ILOSXW) {
2538 l_writebackAckNeedData;
2539 o_popL1RequestQueue;
2540 }
2541
2542
2543 // hmmm...keep data or drop. Just drop for now
2544 transition(ILOS, L1_PUTS_only, ILOW) {
2545 l_writebackAckDropData;
2546 o_popL1RequestQueue;
2547 }
2548
2549 transition(ILSW, Unblock, ILS) {
2550 gg_clearSharerFromL1Response;
2551 n_popResponseQueue;
2552 wa_wakeUpDependents;
2553 }
2554
2555 transition(ILOW, Unblock, ILO) {
2556 gg_clearSharerFromL1Response;
2557 n_popResponseQueue;
2558 wa_wakeUpDependents;
2559 }
2560
2561 transition(ILOSX, L1_PUTS_only, ILOXW) {
2562 l_writebackAckDropData;
2563 o_popL1RequestQueue;
2564 }
2565
2566 transition(ILOXW, Unblock, ILOX) {
2567 gg_clearSharerFromL1Response;
2568 n_popResponseQueue;
2569 wa_wakeUpDependents;
2570 }
2571
2572 // hmmm...keep data or drop. Just drop for now
2573 transition(ILOS, L1_PUTS, ILOSW) {
2574 l_writebackAckDropData;
2575 o_popL1RequestQueue;
2576 }
2577
2578 transition(ILOSX, L1_PUTS, ILOSXW) {
2579 l_writebackAckDropData;
2580 o_popL1RequestQueue;
2581 }
2582
2583 transition(ILOSW, Unblock, ILOS) {
2584 gg_clearSharerFromL1Response;
2585 n_popResponseQueue;
2586 wa_wakeUpDependents;
2587 }
2588
2589 transition(ILOSXW, Unblock, ILOSX) {
2590 gg_clearSharerFromL1Response;
2591 n_popResponseQueue;
2592 wa_wakeUpDependents;
2593 }
2594
2595 transition(SLS, L1_PUTS, SLSW) {
2596 l_writebackAckDropData;
2597 o_popL1RequestQueue;
2598 }
2599
2600 transition(SLS, L1_PUTS_only, SW) {
2601 l_writebackAckDropData;
2602 o_popL1RequestQueue;
2603 }
2604
2605 transition(SW, {Unblock}, S) {
2606 gg_clearSharerFromL1Response;
2607 n_popResponseQueue;
2608 wa_wakeUpDependents;
2609 }
2610
2611 transition(OLS, L1_PUTS, OLSW) {
2612 l_writebackAckDropData;
2613 o_popL1RequestQueue;
2614 }
2615
2616 transition(ILS, L1_PUTS, ILSW) {
2617 l_writebackAckNeedData;
2618 o_popL1RequestQueue;
2619 }
2620
2621 transition(ILS, L1_PUTS_only, IW) {
2622 l_writebackAckNeedData;
2623 o_popL1RequestQueue;
2624 }
2625
2626 transition(OLS, L1_PUTS_only, OW) {
2627 l_writebackAckDropData;
2628 o_popL1RequestQueue;
2629 }
2630
2631 transition(OLSX, L1_PUTS_only, OXW) {
2632 l_writebackAckDropData;
2633 o_popL1RequestQueue;
2634 }
2635
2636 transition(OLSX, L1_PUTS, OLSXW) {
2637 l_writebackAckDropData;
2638 o_popL1RequestQueue;
2639 }
2640
2641 transition(OLSXW, {Unblock}, OLSX) {
2642 gg_clearSharerFromL1Response;
2643 n_popResponseQueue;
2644 wa_wakeUpDependents;
2645 }
2646
2647 transition(OW, {Unblock}, O) {
2648 gg_clearSharerFromL1Response;
2649 n_popResponseQueue;
2650 wa_wakeUpDependents;
2651 }
2652
2653 transition(OXW, {Unblock}, M) {
2654 gg_clearSharerFromL1Response;
2655 n_popResponseQueue;
2656 wa_wakeUpDependents;
2657 }
2658
2659 transition(ILX, L1_PUTX, ILXW ) {
2660 l_writebackAckNeedData;
2661 o_popL1RequestQueue;
2662 }
2663
2664 transition(ILXW, L1_WBDIRTYDATA, M) {
2665 gg_clearLocalSharers;
2666 vv_allocateL2CacheBlock;
2667 y_copyDirToCacheAndRemove;
2668 u_writeDirtyDataToCache;
2669 o_popL1RequestQueue;
2670 wa_wakeUpDependents;
2671 }
2672
2673 // clean writeback
2674 transition(ILXW, L1_WBCLEANDATA, M) {
2675 gg_clearLocalSharers;
2676 vv_allocateL2CacheBlock;
2677 y_copyDirToCacheAndRemove;
2678 u_writeCleanDataToCache;
2679 o_popL1RequestQueue;
2680 wa_wakeUpDependents;
2681 }
2682
2683 transition(ILXW, Unblock, ILX) {
2684 // writeback canceled because L1 invalidated
2685 n_popResponseQueue;
2686 wa_wakeUpDependents;
2687 }
2688
2689 transition(ILSW, L1_WBCLEANDATA, SLS) {
2690 vv_allocateL2CacheBlock;
2691 y_copyDirToCacheAndRemove;
2692 u_writeCleanDataToCache;
2693 gg_clearSharerFromL1Request;
2694 o_popL1RequestQueue;
2695 wa_wakeUpDependents;
2696 }
2697
2698 transition(IW, L1_WBCLEANDATA, S) {
2699 vv_allocateL2CacheBlock;
2700 y_copyDirToCacheAndRemove;
2701 u_writeCleanDataToCache;
2702 gg_clearSharerFromL1Request;
2703 o_popL1RequestQueue;
2704 wa_wakeUpDependents;
2705 }
2706
2707 // Owner can have dirty data
2708 transition(ILOW, L1_WBDIRTYDATA, O) {
2709 vv_allocateL2CacheBlock;
2710 y_copyDirToCacheAndRemove;
2711 gg_clearOwnerFromL1Request;
2712 u_writeDirtyDataToCache;
2713 o_popL1RequestQueue;
2714 wa_wakeUpDependents;
2715 }
2716
2717 transition(ILOW, L1_WBCLEANDATA, O) {
2718 vv_allocateL2CacheBlock;
2719 y_copyDirToCacheAndRemove;
2720 gg_clearOwnerFromL1Request;
2721 u_writeCleanDataToCache;
2722 o_popL1RequestQueue;
2723 wa_wakeUpDependents;
2724 }
2725
2726 transition(ILOXW, L1_WBDIRTYDATA, M) {
2727 vv_allocateL2CacheBlock;
2728 y_copyDirToCacheAndRemove;
2729 gg_clearOwnerFromL1Request;
2730 u_writeDirtyDataToCache;
2731 o_popL1RequestQueue;
2732 wa_wakeUpDependents;
2733 }
2734
2735 transition(ILOXW, L1_WBCLEANDATA, M) {
2736 vv_allocateL2CacheBlock;
2737 y_copyDirToCacheAndRemove;
2738 gg_clearOwnerFromL1Request;
2739 u_writeCleanDataToCache;
2740 o_popL1RequestQueue;
2741 wa_wakeUpDependents;
2742 }
2743
2744 transition(ILOSW, L1_WBDIRTYDATA, OLS) {
2745 vv_allocateL2CacheBlock;
2746 y_copyDirToCacheAndRemove;
2747 gg_clearOwnerFromL1Request;
2748 u_writeDirtyDataToCache;
2749 o_popL1RequestQueue;
2750 wa_wakeUpDependents;
2751 }
2752
2753 transition(ILOSW, L1_WBCLEANDATA, OLS) {
2754 vv_allocateL2CacheBlock;
2755 y_copyDirToCacheAndRemove;
2756 gg_clearOwnerFromL1Request;
2757 u_writeCleanDataToCache;
2758 o_popL1RequestQueue;
2759 wa_wakeUpDependents;
2760 }
2761
2762 transition(ILOSXW, L1_WBDIRTYDATA, OLSX) {
2763 vv_allocateL2CacheBlock;
2764 y_copyDirToCacheAndRemove;
2765 gg_clearOwnerFromL1Request;
2766 u_writeDirtyDataToCache;
2767 o_popL1RequestQueue;
2768 wa_wakeUpDependents;
2769 }
2770
2771 transition(ILOSXW, L1_WBCLEANDATA, OLSX) {
2772 vv_allocateL2CacheBlock;
2773 y_copyDirToCacheAndRemove;
2774 gg_clearOwnerFromL1Request;
2775 u_writeCleanDataToCache;
2776 o_popL1RequestQueue;
2777 wa_wakeUpDependents;
2778 }
2779
2780 transition(SLSW, {Unblock}, SLS) {
2781 gg_clearSharerFromL1Response;
2782 n_popResponseQueue;
2783 wa_wakeUpDependents;
2784 }
2785
2786 transition(OLSW, {Unblock}, OLS) {
2787 gg_clearSharerFromL1Response;
2788 n_popResponseQueue;
2789 wa_wakeUpDependents;
2790 }
2791
2792
2793 // L2 WRITEBACKS
2794 transition({I, S}, L2_Replacement, I) {
2795 rr_deallocateL2CacheBlock;
2796 }
2797
2798 transition(ILS, L2_Replacement) {
2799 y_copyCacheStateToDir;
2800 rr_deallocateL2CacheBlock;
2801 }
2802
2803 transition(ILX, L2_Replacement ) {
2804 y_copyCacheStateToDir;
2805 rr_deallocateL2CacheBlock;
2806 }
2807
2808 transition({ILO, ILOS}, L2_Replacement ) {
2809 y_copyCacheStateToDir;
2810 rr_deallocateL2CacheBlock;
2811 }
2812
2813 transition(SLS, L2_Replacement, ILS) {
2814 y_copyCacheStateToDir;
2815 rr_deallocateL2CacheBlock;
2816 }
2817
2818 transition({OLS, OLSX}, L2_Replacement, OLSI) {
2819 y_copyCacheStateToDir;
2820 b_issuePUTO_ls;
2821 i_allocateTBE;
2822 rr_deallocateL2CacheBlock;
2823 }
2824
2825
2826 transition(O, L2_Replacement, OI) {
2827 b_issuePUTO;
2828 i_allocateTBE;
2829 rr_deallocateL2CacheBlock;
2830 }
2831
2832 transition(M, L2_Replacement, MI) {
2833 b_issuePUTX;
2834 i_allocateTBE;
2835 rr_deallocateL2CacheBlock;
2836 }
2837
2838 transition(OLSI, Fwd_GETX, ILSI) {
2839 t_recordFwdXID;
2840 ee_sendLocalInv;
2841 m_popRequestQueue;
2842 }
2843
2844 transition(ILSI, IntAck) {
2845 m_decrementNumberOfMessagesInt;
2846 o_checkForIntCompletion;
2847 n_popResponseQueue;
2848 }
2849
2850 transition(ILSI, All_Acks, MII) {
2851 gg_clearLocalSharers;
2852 c_sendDataFromTBEToFwdGETX;
2853 n_popTriggerQueue;
2854 }
2855
2856 transition(OLSI, Fwd_GETS) {
2857 t_recordFwdSID;
2858 c_sendDataFromTBEToFwdGETS;
2859 m_popRequestQueue;
2860 }
2861
2862 transition({MI, OI}, Fwd_GETS, OI) {
2863 t_recordFwdSID;
2864 c_sendDataFromTBEToFwdGETS;
2865 m_popRequestQueue;
2866 }
2867
2868 transition({MI, OI}, Fwd_DMA, OI) {
2869 cd_sendDataFromTBEToFwdDma;
2870 da_sendDmaAckUnblock;
2871 m_popRequestQueue;
2872 }
2873
2874 transition(OLSI, Fwd_DMA) {
2875 cd_sendDataFromTBEToFwdDma;
2876 da_sendDmaAckUnblock;
2877 m_popRequestQueue;
2878 }
2879
2880 transition({MI, OI}, Fwd_GETX, MII) {
2881 t_recordFwdXID;
2882 c_sendDataFromTBEToFwdGETX;
2883 m_popRequestQueue;
2884 }
2885
2886 transition({MI, OI}, Writeback_Ack, I) {
2887 qq_sendDataFromTBEToMemory;
2888 s_deallocateTBE;
2889 n_popResponseQueue;
2890 wa_wakeUpDependents;
2891 }
2892
2893 transition(MII, Writeback_Nack, I) {
2894 s_deallocateTBE;
2895 n_popResponseQueue;
2896 wa_wakeUpDependents;
2897 }
2898
2899 transition(OI, Writeback_Nack) {
2900 b_issuePUTO;
2901 n_popResponseQueue;
2902 }
2903
2904 transition(OLSI, Writeback_Ack, ILS) {
2905 qq_sendDataFromTBEToMemory;
2906 s_deallocateTBE;
2907 n_popResponseQueue;
2908 wa_wakeUpDependents;
2909 }
2910
2911 transition(MII, Writeback_Ack, I) {
2912 f_sendUnblock;
2913 s_deallocateTBE;
2914 n_popResponseQueue;
2915 wa_wakeUpDependents;
2916 }
2917
2918 transition(ILSI, Writeback_Ack, ILS) {
2919 f_sendUnblock;
2920 s_deallocateTBE;
2921 n_popResponseQueue;
2922 wa_wakeUpDependents;
2923 }
2924}
732 }
733 else {
734 trigger(Event:L1_WBCLEANDATA, in_msg.addr,
735 cache_entry, TBEs[in_msg.addr]);
736 }
737 } else {
738 error("Unexpected message");
739 }
740 }
741 }
742 }
743
744
745 // ACTIONS
746
747 action(a_issueGETS, "a", desc="issue local request globally") {
748 peek(L1requestNetwork_in, RequestMsg) {
749 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
750 out_msg.addr := address;
751 out_msg.Type := CoherenceRequestType:GETS;
752 out_msg.RequestorMachine := MachineType:L2Cache;
753 out_msg.Requestor := machineID;
754 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
755 out_msg.MessageSize := MessageSizeType:Request_Control;
756 }
757 }
758 }
759
760 action(a_issueGETX, "\a", desc="issue local request globally") {
761 peek(L1requestNetwork_in, RequestMsg) {
762 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
763 out_msg.addr := address;
764 out_msg.Type := CoherenceRequestType:GETX;
765 out_msg.RequestorMachine := MachineType:L2Cache;
766 out_msg.Requestor := machineID;
767 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
768 out_msg.MessageSize := MessageSizeType:Request_Control;
769 }
770 }
771 }
772
773 action(b_issuePUTX, "b", desc="Issue PUTX") {
774 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
775 out_msg.addr := address;
776 out_msg.Type := CoherenceRequestType:PUTX;
777 out_msg.RequestorMachine := MachineType:L2Cache;
778 out_msg.Requestor := machineID;
779 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
780 out_msg.MessageSize := MessageSizeType:Writeback_Control;
781 }
782 }
783
784 action(b_issuePUTO, "\b", desc="Issue PUTO") {
785 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
786 out_msg.addr := address;
787 out_msg.Type := CoherenceRequestType:PUTO;
788 out_msg.Requestor := machineID;
789 out_msg.RequestorMachine := MachineType:L2Cache;
790 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
791 out_msg.MessageSize := MessageSizeType:Writeback_Control;
792 }
793 }
794
795 /* PUTO, but local sharers exist */
796 action(b_issuePUTO_ls, "\bb", desc="Issue PUTO") {
797 enqueue(globalRequestNetwork_out, RequestMsg, request_latency) {
798 out_msg.addr := address;
799 out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
800 out_msg.Requestor := machineID;
801 out_msg.RequestorMachine := MachineType:L2Cache;
802 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
803 out_msg.MessageSize := MessageSizeType:Writeback_Control;
804 }
805 }
806
807 action(c_sendDataFromTBEToL1GETS, "c", desc="Send data from TBE to L1 requestors in TBE") {
808 assert(is_valid(tbe));
809 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
810 out_msg.addr := address;
811 out_msg.Type := CoherenceResponseType:DATA;
812 out_msg.Sender := machineID;
813 out_msg.SenderMachine := MachineType:L2Cache;
814 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
815 out_msg.DataBlk := tbe.DataBlk;
816 // out_msg.Dirty := tbe.Dirty;
817 // shared data should be clean
818 out_msg.Dirty := false;
819 out_msg.MessageSize := MessageSizeType:Response_Data;
820 }
821 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
822 address, tbe.DataBlk);
823 }
824
825 action(c_sendDataFromTBEToL1GETX, "\c", desc="Send data from TBE to L1 requestors in TBE") {
826 assert(is_valid(tbe));
827 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
828 out_msg.addr := address;
829 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
830 out_msg.Sender := machineID;
831 out_msg.SenderMachine := MachineType:L2Cache;
832 out_msg.Destination.add(tbe.L1_GetX_ID);
833 out_msg.DataBlk := tbe.DataBlk;
834 out_msg.Dirty := tbe.Dirty;
835 out_msg.Acks := tbe.Local_GETX_IntAcks;
836 out_msg.MessageSize := MessageSizeType:Response_Data;
837 }
838 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
839 address, tbe.DataBlk);
840 }
841
842 action(c_sendExclusiveDataFromTBEToL1GETS, "\cc", desc="Send data from TBE to L1 requestors in TBE") {
843 assert(is_valid(tbe));
844 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
845 out_msg.addr := address;
846 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
847 out_msg.Sender := machineID;
848 out_msg.SenderMachine := MachineType:L2Cache;
849 out_msg.Destination.addNetDest(tbe.L1_GetS_IDs);
850 out_msg.DataBlk := tbe.DataBlk;
851 out_msg.Dirty := tbe.Dirty;
852 out_msg.MessageSize := MessageSizeType:Response_Data;
853 }
854 }
855
856 action(c_sendDataFromTBEToFwdGETX, "cc", desc="Send data from TBE to external GETX") {
857 assert(is_valid(tbe));
858 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
859 out_msg.addr := address;
860 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
861 out_msg.Sender := machineID;
862 out_msg.SenderMachine := MachineType:L2Cache;
863 out_msg.Destination.add(tbe.Fwd_GetX_ID);
864 out_msg.DataBlk := tbe.DataBlk;
865 out_msg.Dirty := tbe.Dirty;
866 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
867 out_msg.MessageSize := MessageSizeType:Response_Data;
868 }
869 }
870
871 action(cd_sendDataFromTBEToFwdDma, "cd", desc="Send data from TBE to external GETX") {
872 assert(is_valid(tbe));
873 peek(requestNetwork_in, RequestMsg) {
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.add(in_msg.Requestor);
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;
886 }
887 }
888 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
889 address, tbe.DataBlk);
890 }
891
892 action(c_sendDataFromTBEToFwdGETS, "ccc", desc="Send data from TBE to external GETX") {
893 assert(is_valid(tbe));
894 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
895 out_msg.addr := address;
896 out_msg.Type := CoherenceResponseType:DATA;
897 out_msg.Sender := machineID;
898 out_msg.SenderMachine := MachineType:L2Cache;
899 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
900 out_msg.DataBlk := tbe.DataBlk;
901 // out_msg.Dirty := tbe.Dirty;
902 // shared data should be clean
903 out_msg.Dirty := false;
904 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
905 out_msg.MessageSize := MessageSizeType:Response_Data;
906 }
907 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
908 address, tbe.DataBlk);
909 }
910
911 action(c_sendExclusiveDataFromTBEToFwdGETS, "\ccc", desc="Send data from TBE to external GETX") {
912 assert(is_valid(tbe));
913 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
914 out_msg.addr := address;
915 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
916 out_msg.Sender := machineID;
917 out_msg.SenderMachine := MachineType:L2Cache;
918 out_msg.Destination.addNetDest(tbe.Fwd_GetS_IDs);
919 out_msg.DataBlk := tbe.DataBlk;
920 out_msg.Dirty := tbe.Dirty;
921 out_msg.Acks := tbe.Fwd_GETX_ExtAcks;
922 out_msg.MessageSize := MessageSizeType:Response_Data;
923 }
924 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
925 address, tbe.DataBlk);
926 }
927
928 action(d_sendDataToL1GETS, "d", desc="Send data directly to L1 requestor") {
929 assert(is_valid(cache_entry));
930 peek(L1requestNetwork_in, RequestMsg) {
931 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
932 out_msg.addr := address;
933 out_msg.Type := CoherenceResponseType:DATA;
934 out_msg.Sender := machineID;
935 out_msg.SenderMachine := MachineType:L2Cache;
936 out_msg.Destination.add(in_msg.Requestor);
937 out_msg.DataBlk := cache_entry.DataBlk;
938 // out_msg.Dirty := cache_entry.Dirty;
939 // shared data should be clean
940 out_msg.Dirty := false;
941 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
942 }
943 }
944 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
945 address, cache_entry.DataBlk);
946 }
947
948 action(d_sendDataToL1GETX, "\d", desc="Send data and a token from TBE to L1 requestor") {
949 assert(is_valid(cache_entry));
950 peek(L1requestNetwork_in, RequestMsg) {
951 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
952 assert(is_valid(tbe));
953 out_msg.addr := address;
954 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
955 out_msg.Sender := machineID;
956 out_msg.SenderMachine := MachineType:L2Cache;
957 out_msg.Destination.add(in_msg.Requestor);
958 out_msg.DataBlk := cache_entry.DataBlk;
959 out_msg.Dirty := cache_entry.Dirty;
960 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data;
961 out_msg.Acks := tbe.Local_GETX_IntAcks;
962 }
963 }
964 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
965 address, cache_entry.DataBlk);
966 }
967
968 action(dd_sendDataToFwdGETX, "dd", desc="send data") {
969 assert(is_valid(cache_entry));
970 peek(requestNetwork_in, RequestMsg) {
971 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
972 out_msg.addr := address;
973 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
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 out_msg.MessageSize := MessageSizeType:Response_Data;
980 out_msg.Acks := in_msg.Acks;
981 }
982 }
983 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
984 address, cache_entry.DataBlk);
985 }
986
987
988 action(dd_sendDataToFwdGETS, "\dd", desc="send data") {
989 assert(is_valid(cache_entry));
990 peek(requestNetwork_in, RequestMsg) {
991 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
992 out_msg.addr := address;
993 out_msg.Type := CoherenceResponseType:DATA;
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 // shared data should be clean
1000 out_msg.Dirty := false;
1001 out_msg.MessageSize := MessageSizeType:Response_Data;
1002 }
1003 }
1004 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1005 address, cache_entry.DataBlk);
1006 }
1007
1008 action(dd_sendExclusiveDataToFwdGETS, "\d\d", desc="send data") {
1009 assert(is_valid(cache_entry));
1010 peek(requestNetwork_in, RequestMsg) {
1011 enqueue(responseNetwork_out, ResponseMsg, cacheResponseLatency()) {
1012 out_msg.addr := address;
1013 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
1014 out_msg.Sender := machineID;
1015 out_msg.SenderMachine := MachineType:L2Cache;
1016 out_msg.Destination.add(in_msg.Requestor);
1017 out_msg.DataBlk := cache_entry.DataBlk;
1018 out_msg.Dirty := cache_entry.Dirty;
1019 out_msg.MessageSize := MessageSizeType:Response_Data;
1020 }
1021 }
1022 }
1023
1024 action(e_sendAck, "e", desc="Send ack with the tokens we've collected thus far.") {
1025 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1026 assert(is_valid(tbe));
1027 out_msg.addr := address;
1028 out_msg.Type := CoherenceResponseType:ACK;
1029 out_msg.Sender := machineID;
1030 out_msg.SenderMachine := MachineType:L2Cache;
1031
1032 out_msg.Destination.add( tbe.Fwd_GetX_ID);
1033 out_msg.Acks := 0 - 1;
1034 out_msg.MessageSize := MessageSizeType:Response_Control;
1035 }
1036 }
1037
1038 action(e_sendAckToL1Requestor, "\e", desc="Send ack with the tokens we've collected thus far.") {
1039 peek(L1requestNetwork_in, RequestMsg) {
1040 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1041 out_msg.addr := address;
1042 out_msg.Type := CoherenceResponseType:ACK;
1043 out_msg.Sender := machineID;
1044 out_msg.SenderMachine := MachineType:L2Cache;
1045 out_msg.Destination.add(in_msg.Requestor);
1046 out_msg.Acks := 0 - 1;
1047 out_msg.MessageSize := MessageSizeType:Response_Control;
1048 }
1049 }
1050 }
1051
1052 action(e_sendAckToL1RequestorFromTBE, "eee", desc="Send ack with the tokens we've collected thus far.") {
1053 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1054 assert(is_valid(tbe));
1055 out_msg.addr := address;
1056 out_msg.Type := CoherenceResponseType:ACK;
1057 out_msg.Sender := machineID;
1058 out_msg.SenderMachine := MachineType:L2Cache;
1059 out_msg.Destination.add(tbe.L1_GetX_ID);
1060 out_msg.Acks := 0 - 1;
1061 out_msg.MessageSize := MessageSizeType:Response_Control;
1062 }
1063 }
1064
1065 action(ee_sendLocalInv, "\ee", desc="Send local invalidates") {
1066 assert(is_valid(tbe));
1067 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1068 DPRINTF(RubySlicc, "Address: %#x, Local Sharers: %s, Pending Acks: %d\n",
1069 address, getLocalSharers(cache_entry, address),
1070 tbe.NumIntPendingAcks);
1071 if (isLocalOwnerValid(cache_entry, address)) {
1072 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1073 DPRINTF(RubySlicc, "%s\n", getLocalOwner(cache_entry, address));
1074 }
1075
1076 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1077 out_msg.addr := address;
1078 out_msg.Type := CoherenceRequestType:INV;
1079 out_msg.Requestor := machineID;
1080 out_msg.RequestorMachine := MachineType:L2Cache;
1081 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1082 if (isLocalOwnerValid(cache_entry, address))
1083 {
1084 out_msg.Destination.add(getLocalOwner(cache_entry, address));
1085 }
1086 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1087 }
1088 }
1089
1090 action(ee_sendLocalInvSharersOnly, "\eee", desc="Send local invalidates to sharers if they exist") {
1091
1092 // assert(countLocalSharers(address) > 0);
1093 assert(is_valid(tbe));
1094 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1095
1096 if (countLocalSharers(cache_entry, address) > 0) {
1097 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1098 out_msg.addr := address;
1099 out_msg.Type := CoherenceRequestType:INV;
1100 out_msg.Requestor := machineID;
1101 out_msg.RequestorMachine := MachineType:L2Cache;
1102 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1103 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1104 }
1105 }
1106 }
1107
1108 action(ee_addLocalIntAck, "e\ee", desc="add a local ack to wait for") {
1109 assert(is_valid(tbe));
1110 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + 1;
1111 }
1112
1113 action(ee_issueLocalInvExceptL1Requestor, "\eeee", desc="Send local invalidates to sharers if they exist") {
1114 peek(L1requestNetwork_in, RequestMsg) {
1115
1116// assert(countLocalSharers(address) > 0);
1117 if (countLocalSharers(cache_entry, address) == 0) {
1118 tbe.NumIntPendingAcks := 0;
1119 }
1120 else {
1121
1122 if (isLocalSharer(cache_entry, address, in_msg.Requestor)) {
1123 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1124 }
1125 else {
1126 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1127 }
1128
1129 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1130 out_msg.addr := address;
1131 out_msg.Type := CoherenceRequestType:INV;
1132 out_msg.Requestor := in_msg.Requestor;
1133 out_msg.RequestorMachine := MachineType:L1Cache;
1134 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1135 out_msg.Destination.remove(in_msg.Requestor);
1136 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1137 }
1138 }
1139 }
1140 }
1141
1142 action(ee_issueLocalInvExceptL1RequestorInTBE, "\eeeeee", desc="Send local invalidates to sharers if they exist") {
1143 assert(is_valid(tbe));
1144 if (countLocalSharers(cache_entry, address) == 0) {
1145 tbe.NumIntPendingAcks := 0;
1146 }
1147 else {
1148 if (isLocalSharer(cache_entry, address, tbe.L1_GetX_ID)) {
1149 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address) - 1;
1150 }
1151 else {
1152 tbe.NumIntPendingAcks := countLocalSharers(cache_entry, address);
1153 }
1154 }
1155 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1156 out_msg.addr := address;
1157 out_msg.Type := CoherenceRequestType:INV;
1158 out_msg.Requestor := tbe.L1_GetX_ID;
1159 out_msg.RequestorMachine := MachineType:L1Cache;
1160 out_msg.Destination.addNetDest(getLocalSharers(cache_entry, address));
1161 out_msg.Destination.remove(tbe.L1_GetX_ID);
1162 out_msg.MessageSize := MessageSizeType:Invalidate_Control;
1163 }
1164 }
1165
1166
1167 action(f_sendUnblock, "f", desc="Send unblock to global directory") {
1168 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1169 out_msg.addr := address;
1170 out_msg.Type := CoherenceResponseType:UNBLOCK;
1171 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1172 out_msg.Sender := machineID;
1173 out_msg.SenderMachine := MachineType:L2Cache;
1174 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1175 }
1176 }
1177
1178
1179 action(f_sendExclusiveUnblock, "\f", desc="Send unblock to global directory") {
1180 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1181 out_msg.addr := address;
1182 out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
1183 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1184 out_msg.Sender := machineID;
1185 out_msg.SenderMachine := MachineType:L2Cache;
1186 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1187 }
1188 }
1189
1190
1191 action(g_recordLocalSharer, "g", desc="Record new local sharer from unblock message") {
1192 peek(responseNetwork_in, ResponseMsg) {
1193 recordLocalSharerInDir(cache_entry, in_msg.addr, in_msg.Sender);
1194 }
1195 }
1196
1197 action(g_recordLocalExclusive, "\g", desc="Record new local exclusive sharer from unblock message") {
1198 peek(responseNetwork_in, ResponseMsg) {
1199 recordNewLocalExclusiveInDir(cache_entry, address, in_msg.Sender);
1200 }
1201 }
1202
1203 action(gg_clearLocalSharers, "gg", desc="Clear local sharers") {
1204 removeAllLocalSharersFromDir(cache_entry, address);
1205 }
1206
1207 action(gg_clearSharerFromL1Response, "\gg", desc="Clear sharer from L1 response queue") {
1208 peek(responseNetwork_in, ResponseMsg) {
1209 removeSharerFromDir(cache_entry, in_msg.addr, in_msg.Sender);
1210 }
1211 }
1212
1213 action(gg_clearSharerFromL1Request, "clsl1r", desc="Clear sharer from L1 request queue") {
1214 peek(L1requestNetwork_in, RequestMsg) {
1215 removeSharerFromDir(cache_entry, in_msg.addr, in_msg.Requestor);
1216 }
1217 }
1218
1219 action(gg_clearOwnerFromL1Request, "clol1r", desc="Clear owner from L1 request queue") {
1220 peek(L1requestNetwork_in, RequestMsg) {
1221 removeOwnerFromDir(cache_entry, in_msg.addr, in_msg.Requestor);
1222 }
1223 }
1224
1225 action(h_countLocalSharersExceptRequestor, "h", desc="counts number of acks needed for L1 GETX") {
1226 peek(L1requestNetwork_in, RequestMsg) {
1227 assert(is_valid(tbe));
1228 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, in_msg.Requestor);
1229 }
1230 }
1231
1232 action(h_clearIntAcks, "\h", desc="clear IntAcks") {
1233 assert(is_valid(tbe));
1234 tbe.Local_GETX_IntAcks := 0;
1235 }
1236
1237 action(hh_countLocalSharersExceptL1GETXRequestorInTBE, "hh", desc="counts number of acks needed for L1 GETX") {
1238 assert(is_valid(tbe));
1239 tbe.Local_GETX_IntAcks := countLocalSharersExceptRequestor(cache_entry, address, tbe.L1_GetX_ID);
1240 }
1241
1242 action(i_copyDataToTBE, "\i", desc="Copy data from response queue to TBE") {
1243 peek(responseNetwork_in, ResponseMsg) {
1244 assert(is_valid(tbe));
1245 tbe.DataBlk := in_msg.DataBlk;
1246 tbe.Dirty := in_msg.Dirty;
1247 APPEND_TRANSITION_COMMENT(in_msg.Sender);
1248 }
1249 }
1250
1251 action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") {
1252 check_allocate(TBEs);
1253 TBEs.allocate(address);
1254 set_tbe(TBEs[address]);
1255 if(is_valid(cache_entry)) {
1256 tbe.DataBlk := cache_entry.DataBlk;
1257 tbe.Dirty := cache_entry.Dirty;
1258 }
1259 tbe.NumIntPendingAcks := 0; // default value
1260 tbe.NumExtPendingAcks := 0; // default value
1261 tbe.Fwd_GetS_IDs.clear();
1262 tbe.L1_GetS_IDs.clear();
1263 }
1264
1265
1266
1267 action(j_forwardGlobalRequestToLocalOwner, "j", desc="Forward external request to local owner") {
1268 peek(requestNetwork_in, RequestMsg) {
1269 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1270 out_msg.addr := in_msg.addr;
1271 out_msg.Type := in_msg.Type;
1272 out_msg.Requestor := machineID;
1273 out_msg.RequestorMachine := MachineType:L2Cache;
1274 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1275 out_msg.Type := in_msg.Type;
1276 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1277 out_msg.Acks := 0 - 1;
1278 }
1279 }
1280 }
1281
1282 action(jd_forwardDmaRequestToLocalOwner, "jd", desc="Forward dma request to local owner") {
1283 peek(requestNetwork_in, RequestMsg) {
1284 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1285 out_msg.addr := in_msg.addr;
1286 out_msg.Type := in_msg.Type;
1287 out_msg.Requestor := in_msg.Requestor;
1288 out_msg.RequestorMachine := in_msg.RequestorMachine;
1289 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1290 out_msg.Type := in_msg.Type;
1291 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1292 out_msg.Acks := 0 - 1;
1293 }
1294 }
1295 }
1296
1297
1298 action(k_forwardLocalGETSToLocalSharer, "k", desc="Forward local request to local sharer/owner") {
1299 peek(L1requestNetwork_in, RequestMsg) {
1300 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1301 out_msg.addr := in_msg.addr;
1302 out_msg.Type := CoherenceRequestType:GETS;
1303 out_msg.Requestor := in_msg.Requestor;
1304 out_msg.RequestorMachine := MachineType:L1Cache;
1305 // should randomize this so one node doesn't get abused more than others
1306 DirEntry dir_entry := getDirEntry(in_msg.addr);
1307 out_msg.Destination.add(dir_entry.Sharers.smallestElement(MachineType:L1Cache));
1308 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1309 }
1310 }
1311 }
1312
1313 action(k_forwardLocalGETXToLocalOwner, "\k", desc="Forward local request to local owner") {
1314 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1315 assert(is_valid(tbe));
1316 out_msg.addr := address;
1317 out_msg.Type := CoherenceRequestType:GETX;
1318 out_msg.Requestor := tbe.L1_GetX_ID;
1319 out_msg.RequestorMachine := MachineType:L1Cache;
1320 DirEntry dir_entry := getDirEntry(address);
1321 out_msg.Destination.add(dir_entry.Owner);
1322 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1323 out_msg.Acks := 1 + tbe.Local_GETX_IntAcks;
1324 }
1325 }
1326
1327 // same as previous except that it assumes to TBE is present to get number of acks
1328 action(kk_forwardLocalGETXToLocalExclusive, "kk", desc="Forward local request to local owner") {
1329 peek(L1requestNetwork_in, RequestMsg) {
1330 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1331 out_msg.addr := in_msg.addr;
1332 out_msg.Type := CoherenceRequestType:GETX;
1333 out_msg.Requestor := in_msg.Requestor;
1334 out_msg.RequestorMachine := MachineType:L1Cache;
1335 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1336 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1337 out_msg.Acks := 1;
1338 }
1339 }
1340 }
1341
1342 action(kk_forwardLocalGETSToLocalOwner, "\kk", desc="Forward local request to local owner") {
1343 peek(L1requestNetwork_in, RequestMsg) {
1344 enqueue( localRequestNetwork_out, RequestMsg, response_latency ) {
1345 out_msg.addr := in_msg.addr;
1346 out_msg.Type := CoherenceRequestType:GETS;
1347 out_msg.Requestor := in_msg.Requestor;
1348 out_msg.RequestorMachine := MachineType:L1Cache;
1349 out_msg.Destination.add(getLocalOwner(cache_entry, in_msg.addr));
1350 out_msg.MessageSize := MessageSizeType:Forwarded_Control;
1351 }
1352 }
1353 }
1354
1355
1356 action(l_writebackAckNeedData, "l", desc="Send writeback ack to L1 requesting data") {
1357 peek(L1requestNetwork_in, RequestMsg) {
1358 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1359 out_msg.addr := in_msg.addr;
1360 out_msg.Type := CoherenceResponseType:WB_ACK_DATA;
1361 out_msg.Sender := machineID;
1362 out_msg.SenderMachine := MachineType:L2Cache;
1363 out_msg.Destination.add(in_msg.Requestor);
1364 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1365 }
1366 }
1367 }
1368
1369 action(l_writebackAckDropData, "\l", desc="Send writeback ack to L1 indicating to drop data") {
1370 peek(L1requestNetwork_in, RequestMsg) {
1371 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1372 out_msg.addr := in_msg.addr;
1373 out_msg.Type := CoherenceResponseType:WB_ACK;
1374 out_msg.Sender := machineID;
1375 out_msg.SenderMachine := MachineType:L2Cache;
1376 out_msg.Destination.add(in_msg.Requestor);
1377 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1378 }
1379 }
1380 }
1381
1382 action(ll_writebackNack, "\ll", desc="Send writeback nack to L1") {
1383 peek(L1requestNetwork_in, RequestMsg) {
1384 enqueue( responseNetwork_out, ResponseMsg, response_latency ) {
1385 out_msg.addr := in_msg.addr;
1386 out_msg.Type := CoherenceResponseType:WB_NACK;
1387 out_msg.Sender := machineID;
1388 out_msg.SenderMachine := MachineType:L2Cache;
1389 out_msg.Destination.add(in_msg.Requestor);
1390 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1391 }
1392 }
1393 }
1394
1395 action(m_popRequestQueue, "m", desc="Pop request queue.") {
1396 requestNetwork_in.dequeue(clockEdge());
1397 }
1398
1399 action(m_decrementNumberOfMessagesInt, "\m", desc="Decrement the number of messages for which we're waiting") {
1400 peek(responseNetwork_in, ResponseMsg) {
1401 assert(is_valid(tbe));
1402 tbe.NumIntPendingAcks := tbe.NumIntPendingAcks + in_msg.Acks;
1403 }
1404 }
1405
1406 action(m_decrementNumberOfMessagesExt, "\mmm", desc="Decrement the number of messages for which we're waiting") {
1407 peek(responseNetwork_in, ResponseMsg) {
1408 assert(is_valid(tbe));
1409 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1410 }
1411 }
1412
1413 action(mm_decrementNumberOfMessagesExt, "\mm", desc="Decrement the number of messages for which we're waiting") {
1414 peek(requestNetwork_in, RequestMsg) {
1415 assert(is_valid(tbe));
1416 tbe.NumExtPendingAcks := tbe.NumExtPendingAcks - in_msg.Acks;
1417 }
1418 }
1419
1420 action(n_popResponseQueue, "n", desc="Pop response queue") {
1421 responseNetwork_in.dequeue(clockEdge());
1422 }
1423
1424 action(n_popTriggerQueue, "\n", desc="Pop trigger queue.") {
1425 triggerQueue_in.dequeue(clockEdge());
1426 }
1427
1428 action(o_popL1RequestQueue, "o", desc="Pop L1 request queue.") {
1429 L1requestNetwork_in.dequeue(clockEdge());
1430 }
1431
1432
1433 action(o_checkForIntCompletion, "\o", desc="Check if we have received all the messages required for completion") {
1434 assert(is_valid(tbe));
1435 if (tbe.NumIntPendingAcks == 0) {
1436 enqueue(triggerQueue_out, TriggerMsg) {
1437 out_msg.addr := address;
1438 out_msg.Type := TriggerType:ALL_ACKS;
1439 }
1440 }
1441 }
1442
1443 action(o_checkForExtCompletion, "\oo", desc="Check if we have received all the messages required for completion") {
1444 assert(is_valid(tbe));
1445 if (tbe.NumExtPendingAcks == 0) {
1446 enqueue(triggerQueue_out, TriggerMsg) {
1447 out_msg.addr := address;
1448 out_msg.Type := TriggerType:ALL_ACKS;
1449 }
1450 }
1451 }
1452
1453
1454 action( qq_sendDataFromTBEToMemory, "qq", desc="Send data from TBE to directory") {
1455 enqueue(globalRequestNetwork_out, RequestMsg, response_latency) {
1456 assert(is_valid(tbe));
1457 out_msg.addr := address;
1458 out_msg.Requestor := machineID;
1459 out_msg.RequestorMachine := MachineType:L2Cache;
1460 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1461 if (tbe.Dirty) {
1462 out_msg.Type := CoherenceRequestType:WRITEBACK_DIRTY_DATA;
1463 out_msg.DataBlk := tbe.DataBlk;
1464 out_msg.MessageSize := MessageSizeType:Writeback_Data;
1465 } else {
1466 out_msg.Type := CoherenceRequestType:WRITEBACK_CLEAN_ACK;
1467 // NOTE: in a real system this would not send data. We send
1468 // data here only so we can check it at the memory
1469 out_msg.DataBlk := tbe.DataBlk;
1470 out_msg.MessageSize := MessageSizeType:Writeback_Control;
1471 }
1472 }
1473 }
1474
1475 action( r_setMRU, "\rrr", desc="manually set the MRU bit for cache line" ) {
1476 if(is_valid(cache_entry)) {
1477 L2cache.setMRU(address);
1478 }
1479 }
1480
1481 action( s_recordGetXL1ID, "ss", desc="record local GETX requestor") {
1482 peek(L1requestNetwork_in, RequestMsg) {
1483 assert(is_valid(tbe));
1484 tbe.L1_GetX_ID := in_msg.Requestor;
1485 }
1486 }
1487
1488 action(s_deallocateTBE, "s", desc="Deallocate external TBE") {
1489 TBEs.deallocate(address);
1490 unset_tbe();
1491 }
1492
1493 action( s_recordGetSL1ID, "\ss", desc="record local GETS requestor") {
1494 peek(L1requestNetwork_in, RequestMsg) {
1495 assert(is_valid(tbe));
1496 tbe.L1_GetS_IDs.add(in_msg.Requestor);
1497 }
1498 }
1499
1500 action(t_recordFwdXID, "t", desc="record global GETX requestor") {
1501 peek(requestNetwork_in, RequestMsg) {
1502 assert(is_valid(tbe));
1503 tbe.Fwd_GetX_ID := in_msg.Requestor;
1504 tbe.Fwd_GETX_ExtAcks := in_msg.Acks;
1505 }
1506 }
1507
1508 action(t_recordFwdSID, "\t", desc="record global GETS requestor") {
1509 peek(requestNetwork_in, RequestMsg) {
1510 assert(is_valid(tbe));
1511 tbe.Fwd_GetS_IDs.clear();
1512 tbe.Fwd_GetS_IDs.add(in_msg.Requestor);
1513 }
1514 }
1515
1516
1517 action(u_writeCleanDataToCache, "wCd", desc="Write clean data to cache") {
1518 peek(L1requestNetwork_in, RequestMsg) {
1519 assert(is_valid(cache_entry));
1520 cache_entry.DataBlk := in_msg.DataBlk;
1521 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1522 address, cache_entry.DataBlk);
1523 assert(cache_entry.Dirty == false);
1524 }
1525 }
1526
1527 action(u_writeDirtyDataToCache, "wDd", desc="Write dirty data to cache") {
1528 peek(L1requestNetwork_in, RequestMsg) {
1529 assert(is_valid(cache_entry));
1530 cache_entry.DataBlk := in_msg.DataBlk;
1531 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n",
1532 address, cache_entry.DataBlk);
1533 cache_entry.Dirty := true;
1534 }
1535 }
1536
1537 action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") {
1538 set_cache_entry(L2cache.allocate(address, new Entry));
1539 }
1540
1541 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
1542 L2cache.deallocate(address);
1543 unset_cache_entry();
1544 }
1545
1546 action(uu_profileMiss, "\um", desc="Profile the demand miss") {
1547 ++L2cache.demand_misses;
1548 }
1549
1550 action(uu_profileHit, "\uh", desc="Profile the demand hit") {
1551 ++L2cache.demand_hits;
1552 }
1553
1554 action(y_copyCacheStateToDir, "y", desc="Copy cache state to directory state") {
1555 copyCacheStateToDir(cache_entry, address);
1556 }
1557
1558 action(y_copyDirToCacheAndRemove, "/y", desc="Copy dir state to cache and remove") {
1559 copyDirToCache(cache_entry, address);
1560 localDirectory.deallocate(address);
1561 }
1562
1563 action(zz_recycleGlobalRequestQueue, "\zglb", desc="Send the head of the mandatory queue to the back of the queue.") {
1564 peek(requestNetwork_in, RequestMsg) {
1565 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1566 }
1567 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1568 }
1569
1570 action(zz_recycleL1RequestQueue, "\zl1", desc="Send the head of the mandatory queue to the back of the queue.") {
1571 peek(L1requestNetwork_in, RequestMsg) {
1572 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1573 }
1574 L1requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
1575 }
1576
1577 action(st_stallAndWaitL1RequestQueue, "st", desc="Stall and wait on the address") {
1578 stall_and_wait(L1requestNetwork_in, address);
1579 }
1580
1581 action(wa_wakeUpDependents, "wa", desc="Wake up any requests waiting for this address") {
1582 wakeUpAllBuffers(address);
1583 }
1584
1585 action(da_sendDmaAckUnblock, "da", desc="Send dma ack to global directory") {
1586 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
1587 out_msg.addr := address;
1588 out_msg.Type := CoherenceResponseType:DMA_ACK;
1589 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
1590 out_msg.Sender := machineID;
1591 out_msg.SenderMachine := MachineType:L2Cache;
1592 out_msg.MessageSize := MessageSizeType:Unblock_Control;
1593 }
1594 }
1595
1596
1597
1598 //*****************************************************
1599 // TRANSITIONS
1600 //*****************************************************
1601
1602 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_PUTO, L1_PUTS, L1_PUTS_only, L1_PUTX}) {
1603 st_stallAndWaitL1RequestQueue;
1604 }
1605
1606 transition({II, IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX, OLSXS, IGS, IGM, IGMLS, IGMO, IGMIO, OGMIO, IGMIOF, OGMIOF, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {L1_GETX, L1_GETS}) {
1607 st_stallAndWaitL1RequestQueue;
1608 }
1609
1610 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, ILXW, OW, SW, OXW, OLSXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, IGMLS, IGMO, MM, SS, OO, OI, MI, MII, OLSI, ILSI, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, L2_Replacement) {
1611 zz_recycleL1RequestQueue;
1612 }
1613
1614 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, IGS, IGM, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Fwd_GETX, Fwd_GETS, Fwd_DMA}) {
1615 zz_recycleGlobalRequestQueue;
1616 }
1617
1618 transition({OGMIO, IGMIO, IGMO}, Fwd_DMA) {
1619 zz_recycleGlobalRequestQueue;
1620 }
1621
1622 transition({IFGX, IFGS, ISFGS, IFGXX, IFLXO, ILOW, ILOXW, ILOSW, ILOSXW, SLSW, OLSW, ILSW, IW, OW, SW, OXW, OLSXW, ILXW, IFLS, IFLO, IFLOX, IFLOXX, IFLOSX,OLSXS, MM, SS, OO, SLSS, OLSS, OLSF, IGMIOFS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Inv}) {
1623 zz_recycleGlobalRequestQueue;
1624 }
1625
1626 transition({IGM, IGS, ILOSD, ILOSXD, ILOD, ILXD, ILOXD}, {Own_GETX}) {
1627 zz_recycleGlobalRequestQueue;
1628 }
1629
1630 // must happened because we forwarded GETX to local exclusive trying to do wb
1631 transition({I, M, O, ILS, ILOX, OLS, OLSX, SLS, S}, L1_PUTX) {
1632 ll_writebackNack;
1633 o_popL1RequestQueue;
1634 }
1635
1636 transition({M}, {L1_PUTS, L1_PUTO} ) {
1637 ll_writebackNack;
1638 o_popL1RequestQueue;
1639 }
1640
1641 transition({ILS, OLSX}, L1_PUTO){
1642 ll_writebackNack;
1643 o_popL1RequestQueue;
1644 }
1645
1646// happened if we forwarded GETS to exclusive who tried to do writeback
1647// ?? should we just Nack these instead? Could be a bugs here
1648 transition(ILO, L1_PUTX, ILOW) {
1649 l_writebackAckNeedData;
1650 o_popL1RequestQueue;
1651 }
1652
1653 // this can happen if we forwarded a L1_GETX to exclusiver after it issued a PUTX
1654 transition(ILOS, L1_PUTX, ILOSW) {
1655 l_writebackAckNeedData;
1656 o_popL1RequestQueue;
1657 }
1658
1659 transition(ILOSX, L1_PUTX, ILOSXW) {
1660 l_writebackAckNeedData;
1661 o_popL1RequestQueue;
1662 }
1663
1664 // must happened because we got Inv when L1 attempted PUTS
1665 transition(I, L1_PUTS) {
1666 ll_writebackNack;
1667 o_popL1RequestQueue;
1668 }
1669
1670 transition(I, L1_PUTO) {
1671 ll_writebackNack;
1672 o_popL1RequestQueue;
1673 }
1674
1675 // FORWARDED REQUESTS
1676
1677 transition({ILO, ILX, ILOX}, Fwd_GETS, IFGS) {
1678 i_allocateTBE;
1679 t_recordFwdSID;
1680 j_forwardGlobalRequestToLocalOwner;
1681 m_popRequestQueue;
1682 }
1683
1684 transition({ILOS, ILOSX}, Fwd_GETS, ISFGS) {
1685 i_allocateTBE;
1686 t_recordFwdSID;
1687 j_forwardGlobalRequestToLocalOwner;
1688 m_popRequestQueue;
1689 }
1690
1691 transition(ILOS, Fwd_DMA, ILOSD) {
1692 i_allocateTBE;
1693 jd_forwardDmaRequestToLocalOwner;
1694 m_popRequestQueue;
1695 }
1696
1697 transition(ILOSD, DmaAck, ILOS) {
1698 s_deallocateTBE;
1699 da_sendDmaAckUnblock;
1700 n_popResponseQueue;
1701 wa_wakeUpDependents;
1702 }
1703
1704 transition(ILOSX, Fwd_DMA, ILOSXD) {
1705 i_allocateTBE;
1706 t_recordFwdSID;
1707 jd_forwardDmaRequestToLocalOwner;
1708 m_popRequestQueue;
1709 }
1710
1711 transition(ILOSXD, DmaAck, ILOSX) {
1712 s_deallocateTBE;
1713 da_sendDmaAckUnblock;
1714 n_popResponseQueue;
1715 wa_wakeUpDependents;
1716 }
1717
1718 transition(ILO, Fwd_DMA, ILOD) {
1719 i_allocateTBE;
1720 t_recordFwdSID;
1721 jd_forwardDmaRequestToLocalOwner;
1722 m_popRequestQueue;
1723 }
1724
1725 transition(ILOD, DmaAck, ILO) {
1726 s_deallocateTBE;
1727 da_sendDmaAckUnblock;
1728 n_popResponseQueue;
1729 wa_wakeUpDependents;
1730 }
1731
1732 transition(ILX, Fwd_DMA, ILXD) {
1733 i_allocateTBE;
1734 t_recordFwdSID;
1735 jd_forwardDmaRequestToLocalOwner;
1736 m_popRequestQueue;
1737 }
1738
1739 transition(ILXD, DmaAck, ILX) {
1740 s_deallocateTBE;
1741 da_sendDmaAckUnblock;
1742 n_popResponseQueue;
1743 wa_wakeUpDependents;
1744 }
1745
1746 transition(ILOX, Fwd_DMA, ILOXD) {
1747 i_allocateTBE;
1748 t_recordFwdSID;
1749 jd_forwardDmaRequestToLocalOwner;
1750 m_popRequestQueue;
1751 }
1752
1753 transition(ILOXD, DmaAck, ILOX) {
1754 s_deallocateTBE;
1755 da_sendDmaAckUnblock;
1756 n_popResponseQueue;
1757 wa_wakeUpDependents;
1758 }
1759
1760 transition({ILOS, ILOSX, ILO, ILX, ILOX, ILXW}, Data) {
1761 i_copyDataToTBE;
1762 c_sendDataFromTBEToFwdGETS;
1763 s_deallocateTBE;
1764 n_popResponseQueue;
1765 }
1766
1767 transition(IFGS, Data, ILO) {
1768 i_copyDataToTBE;
1769 c_sendDataFromTBEToFwdGETS;
1770 s_deallocateTBE;
1771 n_popResponseQueue;
1772 wa_wakeUpDependents;
1773 }
1774
1775 transition(ISFGS, Data, ILOS) {
1776 i_copyDataToTBE;
1777 c_sendDataFromTBEToFwdGETS;
1778 s_deallocateTBE;
1779 n_popResponseQueue;
1780 wa_wakeUpDependents;
1781 }
1782
1783 transition(IFGS, Data_Exclusive, I) {
1784 i_copyDataToTBE;
1785 c_sendExclusiveDataFromTBEToFwdGETS;
1786 gg_clearLocalSharers;
1787 s_deallocateTBE;
1788 n_popResponseQueue;
1789 wa_wakeUpDependents;
1790 }
1791
1792
1793 transition({ILX, ILO, ILOX}, Fwd_GETX, IFGX) {
1794 i_allocateTBE;
1795 t_recordFwdXID;
1796 j_forwardGlobalRequestToLocalOwner;
1797 m_popRequestQueue;
1798 }
1799
1800 transition(IFGX, {Data_Exclusive, Data}, I) {
1801 i_copyDataToTBE;
1802 c_sendDataFromTBEToFwdGETX;
1803 gg_clearLocalSharers;
1804 s_deallocateTBE;
1805 n_popResponseQueue;
1806 wa_wakeUpDependents;
1807 }
1808
1809 transition({ILOSX, ILOS}, Fwd_GETX, IFGXX) {
1810 i_allocateTBE;
1811 t_recordFwdXID;
1812 j_forwardGlobalRequestToLocalOwner;
1813 ee_sendLocalInvSharersOnly;
1814 ee_addLocalIntAck;
1815 m_popRequestQueue;
1816 }
1817
1818
1819 transition(IFGXX, IntAck) {
1820 m_decrementNumberOfMessagesInt;
1821 o_checkForIntCompletion;
1822 n_popResponseQueue;
1823 }
1824
1825 transition(IFGXX, Data_Exclusive) {
1826 i_copyDataToTBE;
1827 m_decrementNumberOfMessagesInt;
1828 o_checkForIntCompletion;
1829 n_popResponseQueue;
1830 }
1831
1832 transition(IFGXX, All_Acks, I) {
1833 c_sendDataFromTBEToFwdGETX;
1834 gg_clearLocalSharers;
1835 s_deallocateTBE;
1836 n_popTriggerQueue;
1837 wa_wakeUpDependents;
1838 }
1839
1840
1841 // transition({O, OX}, Fwd_GETX, I) {
1842 transition(O, Fwd_GETX, I) {
1843 dd_sendDataToFwdGETX;
1844 y_copyCacheStateToDir;
1845 rr_deallocateL2CacheBlock;
1846 m_popRequestQueue;
1847 }
1848
1849 transition({O, OLS}, Fwd_GETS) {
1850 dd_sendDataToFwdGETS;
1851 m_popRequestQueue;
1852 }
1853
1854 transition({O, OLS}, Fwd_DMA) {
1855 dd_sendDataToFwdGETS;
1856 da_sendDmaAckUnblock;
1857 m_popRequestQueue;
1858 }
1859
1860 // transition({OLSX, OX}, Fwd_GETS, O) {
1861 transition(OLSX, Fwd_GETS, OLS) {
1862 dd_sendDataToFwdGETS;
1863 m_popRequestQueue;
1864 }
1865
1866 transition(OLSX, Fwd_DMA) {
1867 dd_sendDataToFwdGETS;
1868 da_sendDmaAckUnblock;
1869 m_popRequestQueue;
1870 }
1871
1872 transition(M, Fwd_GETX, I) {
1873 dd_sendDataToFwdGETX;
1874 rr_deallocateL2CacheBlock;
1875 m_popRequestQueue;
1876 }
1877
1878 // MAKE THIS THE SAME POLICY FOR NOW
1879
1880 // transition(M, Fwd_GETS, O) {
1881 // dd_sendDataToFwdGETS;
1882 // m_popRequestQueue;
1883 // }
1884
1885 transition(M, Fwd_GETS, I) {
1886 dd_sendExclusiveDataToFwdGETS;
1887 rr_deallocateL2CacheBlock;
1888 m_popRequestQueue;
1889 }
1890
1891 transition(M, Fwd_DMA) {
1892 dd_sendExclusiveDataToFwdGETS;
1893 da_sendDmaAckUnblock;
1894 m_popRequestQueue;
1895 }
1896
1897 transition({OLS, OLSX}, Fwd_GETX, OLSF) {
1898 i_allocateTBE;
1899 t_recordFwdXID;
1900 ee_sendLocalInv;
1901 m_popRequestQueue;
1902 }
1903
1904 transition(OLSF, IntAck) {
1905 m_decrementNumberOfMessagesInt;
1906 o_checkForIntCompletion;
1907 n_popResponseQueue;
1908 }
1909
1910 transition(OLSF, All_Acks, I) {
1911 c_sendDataFromTBEToFwdGETX;
1912 gg_clearLocalSharers;
1913 s_deallocateTBE;
1914 rr_deallocateL2CacheBlock;
1915 n_popTriggerQueue;
1916 wa_wakeUpDependents;
1917 }
1918
1919
1920
1921 // INVALIDATIONS FROM GLOBAL DIRECTORY
1922
1923 transition({IGM, IGS}, Inv) {
1924 t_recordFwdXID;
1925 e_sendAck;
1926 m_popRequestQueue;
1927 }
1928
1929 transition({I,NP}, Inv) {
1930 i_allocateTBE;
1931 t_recordFwdXID;
1932 e_sendAck;
1933 s_deallocateTBE;
1934 m_popRequestQueue;
1935 }
1936
1937 // NEED INV for S state
1938
1939 transition({ILS, ILO, ILX}, Inv, II) {
1940 i_allocateTBE;
1941 t_recordFwdXID;
1942 ee_sendLocalInv;
1943 gg_clearLocalSharers;
1944 m_popRequestQueue;
1945 }
1946
1947 transition(SLS, Inv, II) {
1948 i_allocateTBE;
1949 t_recordFwdXID;
1950 ee_sendLocalInv;
1951 rr_deallocateL2CacheBlock;
1952 m_popRequestQueue;
1953 }
1954
1955 transition(II, IntAck) {
1956 m_decrementNumberOfMessagesInt;
1957 o_checkForIntCompletion;
1958 n_popResponseQueue;
1959 }
1960
1961 transition(II, All_Acks, I) {
1962 e_sendAck;
1963 s_deallocateTBE;
1964 n_popTriggerQueue;
1965 wa_wakeUpDependents;
1966 }
1967
1968 transition(S, Inv, I) {
1969 i_allocateTBE;
1970 t_recordFwdXID;
1971 e_sendAck;
1972 s_deallocateTBE;
1973 rr_deallocateL2CacheBlock;
1974 m_popRequestQueue;
1975 }
1976
1977
1978 // LOCAL REQUESTS SATISFIED LOCALLY
1979
1980 transition(OLSX, L1_GETX, IFLOX) {
1981 i_allocateTBE;
1982 s_recordGetXL1ID;
1983 // count number of INVs needed that doesn't include requestor
1984 h_countLocalSharersExceptRequestor;
1985 // issue INVs to everyone except requestor
1986 ee_issueLocalInvExceptL1Requestor;
1987 d_sendDataToL1GETX
1988 y_copyCacheStateToDir;
1989 r_setMRU;
1990 rr_deallocateL2CacheBlock;
1991 uu_profileHit;
1992 o_popL1RequestQueue;
1993 }
1994
1995 transition(IFLOX, Exclusive_Unblock, ILX) {
1996 g_recordLocalExclusive;
1997 s_deallocateTBE;
1998 n_popResponseQueue;
1999 wa_wakeUpDependents;
2000 }
2001
2002 transition(OLSX, L1_GETS, OLSXS) {
2003 d_sendDataToL1GETS;
2004 r_setMRU;
2005 uu_profileHit;
2006 o_popL1RequestQueue;
2007 }
2008
2009 transition(OLSXS, Unblock, OLSX) {
2010 g_recordLocalSharer;
2011 n_popResponseQueue;
2012 wa_wakeUpDependents;
2013 }
2014
2015 // after this, can't get Fwd_GETX
2016 transition(IGMO, Own_GETX) {
2017 mm_decrementNumberOfMessagesExt;
2018 o_checkForExtCompletion;
2019 m_popRequestQueue;
2020
2021 }
2022
2023
2024 transition(ILX, L1_GETS, IFLOXX) {
2025 kk_forwardLocalGETSToLocalOwner;
2026 uu_profileMiss;
2027 o_popL1RequestQueue;
2028 }
2029
2030 transition(ILOSX, L1_GETS, IFLOSX) {
2031 kk_forwardLocalGETSToLocalOwner;
2032 uu_profileMiss;
2033 o_popL1RequestQueue;
2034 }
2035
2036 transition({ILOS, ILO}, L1_GETS, IFLO) {
2037 kk_forwardLocalGETSToLocalOwner;
2038 uu_profileMiss;
2039 o_popL1RequestQueue;
2040 }
2041
2042 transition(ILS, L1_GETS, IFLS) {
2043 k_forwardLocalGETSToLocalSharer;
2044 uu_profileMiss;
2045 o_popL1RequestQueue;
2046 }
2047
2048 transition({ILX, ILOX}, L1_GETX, IFLOXX) {
2049 kk_forwardLocalGETXToLocalExclusive;
2050 e_sendAckToL1Requestor;
2051 uu_profileMiss;
2052 o_popL1RequestQueue;
2053 }
2054
2055 transition(ILOX, L1_GETS, IFLOX) {
2056 kk_forwardLocalGETSToLocalOwner;
2057 uu_profileMiss;
2058 o_popL1RequestQueue;
2059 }
2060
2061 transition(IFLOX, Unblock, ILOSX) {
2062 g_recordLocalSharer;
2063 n_popResponseQueue;
2064 wa_wakeUpDependents;
2065 }
2066
2067 transition(IFLS, Unblock, ILS) {
2068 g_recordLocalSharer;
2069 n_popResponseQueue;
2070 wa_wakeUpDependents;
2071 }
2072
2073 transition(IFLOXX, Unblock, ILOSX) {
2074 g_recordLocalSharer;
2075 n_popResponseQueue;
2076 wa_wakeUpDependents;
2077 }
2078
2079 transition(IFLOSX, Unblock, ILOSX) {
2080 g_recordLocalSharer;
2081 n_popResponseQueue;
2082 wa_wakeUpDependents;
2083 }
2084
2085 transition({IFLOSX, IFLOXX}, Exclusive_Unblock, ILX) {
2086 g_recordLocalExclusive;
2087 n_popResponseQueue;
2088 wa_wakeUpDependents;
2089 }
2090
2091 transition(IFLO, Unblock, ILOS) {
2092 g_recordLocalSharer;
2093 n_popResponseQueue;
2094 wa_wakeUpDependents;
2095 }
2096
2097
2098 transition(ILOSX, L1_GETX, IFLXO) {
2099 i_allocateTBE;
2100 s_recordGetXL1ID;
2101 h_countLocalSharersExceptRequestor;
2102 ee_issueLocalInvExceptL1Requestor;
2103 k_forwardLocalGETXToLocalOwner;
2104 e_sendAckToL1RequestorFromTBE;
2105 uu_profileMiss;
2106 o_popL1RequestQueue;
2107 }
2108
2109 transition(IFLXO, Exclusive_Unblock, ILX) {
2110 g_recordLocalExclusive;
2111 s_deallocateTBE;
2112 n_popResponseQueue;
2113 wa_wakeUpDependents;
2114 }
2115
2116 // LOCAL REQUESTS THAT MUST ISSUE
2117
2118 transition(NP, {L1_PUTS, L1_PUTX, L1_PUTO}) {
2119 ll_writebackNack;
2120 o_popL1RequestQueue;
2121 }
2122
2123 transition({NP, I}, L1_GETS, IGS) {
2124 i_allocateTBE;
2125 s_recordGetSL1ID;
2126 a_issueGETS;
2127 uu_profileMiss;
2128 o_popL1RequestQueue;
2129 }
2130
2131 transition({NP, I}, L1_GETX, IGM) {
2132 i_allocateTBE;
2133 s_recordGetXL1ID;
2134 a_issueGETX;
2135 uu_profileMiss;
2136 o_popL1RequestQueue;
2137 }
2138
2139 transition(S, L1_GETX, IGM) {
2140 i_allocateTBE;
2141 s_recordGetXL1ID;
2142 a_issueGETX;
2143 y_copyCacheStateToDir;
2144 r_setMRU;
2145 rr_deallocateL2CacheBlock;
2146 uu_profileMiss;
2147 o_popL1RequestQueue;
2148 }
2149
2150 transition(ILS, L1_GETX, IGMLS) {
2151 i_allocateTBE;
2152 s_recordGetXL1ID;
2153 a_issueGETX;
2154 // count number of INVs (just sharers?) needed that doesn't include requestor
2155 h_countLocalSharersExceptRequestor;
2156 uu_profileMiss;
2157 o_popL1RequestQueue;
2158 }
2159
2160 transition(IGMLS, Inv) {
2161 t_recordFwdXID;
2162 ee_sendLocalInv;
2163 m_popRequestQueue;
2164 }
2165
2166 transition(IGMLS, IntAck) {
2167 m_decrementNumberOfMessagesInt;
2168 o_checkForIntCompletion;
2169 n_popResponseQueue;
2170 }
2171
2172 transition(IGMLS, All_Acks, IGM) {
2173 gg_clearLocalSharers;
2174 h_clearIntAcks;
2175 e_sendAck;
2176 n_popTriggerQueue;
2177 }
2178
2179 // transition(IGMLS, ExtAck, IGMO) {
2180 transition(IGMLS, ExtAck) {
2181 m_decrementNumberOfMessagesExt;
2182 o_checkForExtCompletion;
2183 n_popResponseQueue;
2184 }
2185
2186 transition(IGMLS, {Data, Data_Exclusive}, IGMO) {
2187 ee_issueLocalInvExceptL1RequestorInTBE;
2188 i_copyDataToTBE;
2189 m_decrementNumberOfMessagesExt;
2190 o_checkForExtCompletion;
2191 n_popResponseQueue;
2192 }
2193
2194
2195 transition(ILOS, L1_GETX, IGMIO) {
2196 i_allocateTBE;
2197 s_recordGetXL1ID;
2198 a_issueGETX;
2199 uu_profileMiss;
2200 o_popL1RequestQueue;
2201 }
2202
2203 // new exclusive happened while sharer attempted writeback
2204 transition(ILX, {L1_PUTS, L1_PUTS_only, L1_PUTO}) {
2205 ll_writebackNack;
2206 o_popL1RequestQueue;
2207 }
2208
2209 transition(S, L1_PUTS) {
2210 ll_writebackNack;
2211 o_popL1RequestQueue;
2212 }
2213
2214 transition(OLS, L1_GETX, OGMIO) {
2215 i_allocateTBE;
2216 s_recordGetXL1ID;
2217 a_issueGETX;
2218 h_countLocalSharersExceptRequestor;
2219 // COPY DATA FROM CACHE TO TBE (happens during i_allocateTBE)
2220 y_copyCacheStateToDir;
2221 rr_deallocateL2CacheBlock;
2222 uu_profileMiss;
2223 o_popL1RequestQueue;
2224 }
2225
2226 transition(OGMIO, Fwd_GETS) {
2227 t_recordFwdSID;
2228 c_sendDataFromTBEToFwdGETS;
2229 m_popRequestQueue;
2230 }
2231
2232 transition(ILO, L1_GETX, IGMIO) {
2233 i_allocateTBE;
2234 s_recordGetXL1ID;
2235 a_issueGETX;
2236 // the following, of course, returns 0 sharers but do anyways for consistency
2237 h_countLocalSharersExceptRequestor;
2238 uu_profileMiss;
2239 o_popL1RequestQueue;
2240 }
2241
2242 transition({ILO, ILOX}, L1_PUTS) {
2243 ll_writebackNack;
2244 o_popL1RequestQueue;
2245 }
2246
2247 transition(IGMIO, Fwd_GETX, IGMIOF) {
2248 t_recordFwdXID;
2249 j_forwardGlobalRequestToLocalOwner;
2250 ee_sendLocalInvSharersOnly;
2251 ee_addLocalIntAck;
2252 m_popRequestQueue;
2253 }
2254
2255 transition(IGMIO, Fwd_GETS, IGMIOFS) {
2256 t_recordFwdSID;
2257 j_forwardGlobalRequestToLocalOwner;
2258 m_popRequestQueue;
2259 }
2260
2261 transition(IGMIOFS, Data, IGMIO) {
2262 i_copyDataToTBE;
2263 c_sendDataFromTBEToFwdGETS;
2264 n_popResponseQueue;
2265 }
2266
2267 transition(OGMIO, Fwd_GETX, OGMIOF) {
2268 t_recordFwdXID;
2269 ee_sendLocalInvSharersOnly;
2270 m_popRequestQueue;
2271 }
2272
2273 transition(OGMIOF, IntAck) {
2274 m_decrementNumberOfMessagesInt;
2275 o_checkForIntCompletion;
2276 n_popResponseQueue;
2277 }
2278
2279 transition(OGMIOF, All_Acks, IGM) {
2280 gg_clearLocalSharers;
2281 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2282 c_sendDataFromTBEToFwdGETX;
2283 n_popTriggerQueue;
2284 }
2285
2286 transition(IGMIOF, IntAck) {
2287 m_decrementNumberOfMessagesInt;
2288 o_checkForIntCompletion;
2289 n_popResponseQueue;
2290 }
2291
2292 transition(IGMIOF, Data_Exclusive) {
2293 i_copyDataToTBE;
2294 m_decrementNumberOfMessagesInt;
2295 o_checkForIntCompletion;
2296 n_popResponseQueue;
2297 }
2298
2299 transition(IGMIOF, All_Acks, IGM) {
2300 gg_clearLocalSharers;
2301 c_sendDataFromTBEToFwdGETX;
2302 n_popTriggerQueue;
2303 }
2304
2305 transition(IGMIO, All_Acks, IGMO) {
2306 hh_countLocalSharersExceptL1GETXRequestorInTBE;
2307 ee_issueLocalInvExceptL1RequestorInTBE;
2308 k_forwardLocalGETXToLocalOwner;
2309 e_sendAckToL1RequestorFromTBE;
2310 n_popTriggerQueue;
2311 }
2312
2313 transition(OGMIO, All_Acks, IGMO) {
2314 ee_issueLocalInvExceptL1RequestorInTBE;
2315 c_sendDataFromTBEToL1GETX;
2316 n_popTriggerQueue;
2317 }
2318
2319 transition({IGMIO, OGMIO}, Own_GETX) {
2320 mm_decrementNumberOfMessagesExt;
2321 o_checkForExtCompletion;
2322 m_popRequestQueue;
2323
2324 }
2325
2326 transition(IGM, {Data, Data_Exclusive}, IGMO) {
2327 i_copyDataToTBE;
2328 m_decrementNumberOfMessagesExt;
2329 o_checkForExtCompletion;
2330 n_popResponseQueue;
2331 }
2332
2333 transition({IGM, IGMIO, OGMIO}, ExtAck) {
2334 m_decrementNumberOfMessagesExt;
2335 o_checkForExtCompletion;
2336 n_popResponseQueue;
2337 }
2338
2339 transition(IGMO, ExtAck) {
2340 m_decrementNumberOfMessagesExt;
2341 o_checkForExtCompletion;
2342 n_popResponseQueue;
2343 }
2344
2345 transition(IGS, Data) {
2346 i_copyDataToTBE;
2347 m_decrementNumberOfMessagesExt;
2348 c_sendDataFromTBEToL1GETS;
2349 n_popResponseQueue;
2350 }
2351
2352 transition(IGS, Data_Exclusive) {
2353 i_copyDataToTBE;
2354 m_decrementNumberOfMessagesExt;
2355 c_sendExclusiveDataFromTBEToL1GETS;
2356 n_popResponseQueue;
2357 }
2358
2359 transition(IGS, Unblock, ILS) {
2360 g_recordLocalSharer;
2361 f_sendUnblock;
2362 s_deallocateTBE;
2363 n_popResponseQueue;
2364 wa_wakeUpDependents;
2365 }
2366
2367 transition(IGS, Exclusive_Unblock, ILX) {
2368 g_recordLocalExclusive;
2369 f_sendExclusiveUnblock;
2370 s_deallocateTBE;
2371 n_popResponseQueue;
2372 wa_wakeUpDependents;
2373 }
2374
2375 transition(IGMO, All_Acks) {
2376 c_sendDataFromTBEToL1GETX;
2377 n_popTriggerQueue;
2378 }
2379
2380 transition(IGMO, Exclusive_Unblock, ILX) {
2381 g_recordLocalExclusive;
2382 f_sendExclusiveUnblock;
2383 s_deallocateTBE;
2384 n_popResponseQueue;
2385 wa_wakeUpDependents;
2386 }
2387
2388
2389 transition(SLS, L1_GETX, IGMLS) {
2390 i_allocateTBE;
2391 s_recordGetXL1ID;
2392 a_issueGETX;
2393 // count number of INVs needed that doesn't include requestor
2394 h_countLocalSharersExceptRequestor;
2395 // issue INVs to everyone except requestor
2396 y_copyCacheStateToDir;
2397 rr_deallocateL2CacheBlock;
2398 uu_profileMiss;
2399 o_popL1RequestQueue;
2400
2401 }
2402
2403 transition(SLS, L1_GETS, SLSS ) {
2404 d_sendDataToL1GETS;
2405 r_setMRU;
2406 uu_profileHit;
2407 o_popL1RequestQueue;
2408 }
2409
2410 transition(SLSS, Unblock, SLS) {
2411 g_recordLocalSharer;
2412 n_popResponseQueue;
2413 wa_wakeUpDependents;
2414 }
2415
2416
2417 transition(O, L1_GETX, IGMO) {
2418 i_allocateTBE;
2419 s_recordGetXL1ID;
2420 a_issueGETX;
2421 y_copyCacheStateToDir;
2422 rr_deallocateL2CacheBlock;
2423 uu_profileMiss;
2424 o_popL1RequestQueue;
2425 }
2426
2427 transition(OLS, L1_GETS, OLSS) {
2428 d_sendDataToL1GETS;
2429 r_setMRU;
2430 uu_profileHit;
2431 o_popL1RequestQueue;
2432 }
2433
2434 transition(OLSS, Unblock, OLS) {
2435 g_recordLocalSharer;
2436 n_popResponseQueue;
2437 wa_wakeUpDependents;
2438 }
2439
2440 transition(IGMO, Fwd_GETX, IGM) {
2441 t_recordFwdXID;
2442 c_sendDataFromTBEToFwdGETX;
2443 m_popRequestQueue;
2444
2445 }
2446
2447 transition(IGMO, Fwd_GETS) {
2448 t_recordFwdSID;
2449 c_sendDataFromTBEToFwdGETS;
2450 m_popRequestQueue;
2451 }
2452
2453
2454 // LOCAL REQUESTS SATISFIED DIRECTLY BY L2
2455
2456 transition(M, L1_GETX, MM) {
2457 i_allocateTBE;
2458 // should count 0 of course
2459 h_countLocalSharersExceptRequestor;
2460 d_sendDataToL1GETX;
2461 y_copyCacheStateToDir;
2462 rr_deallocateL2CacheBlock;
2463 s_deallocateTBE;
2464 uu_profileHit;
2465 o_popL1RequestQueue;
2466 }
2467
2468 transition(MM, Exclusive_Unblock, ILX) {
2469 g_recordLocalExclusive;
2470 n_popResponseQueue;
2471 wa_wakeUpDependents;
2472 }
2473
2474 transition(M, L1_GETS, OO) {
2475 i_allocateTBE;
2476 // should count 0 of course
2477 h_countLocalSharersExceptRequestor;
2478 d_sendDataToL1GETX;
2479 r_setMRU;
2480 s_deallocateTBE;
2481 uu_profileHit;
2482 o_popL1RequestQueue;
2483 }
2484
2485 transition(S, L1_GETS, SS) {
2486 d_sendDataToL1GETS;
2487 r_setMRU;
2488 uu_profileHit;
2489 o_popL1RequestQueue;
2490 }
2491
2492 transition(SS, Unblock, SLS) {
2493 g_recordLocalSharer;
2494 n_popResponseQueue;
2495 wa_wakeUpDependents;
2496 }
2497
2498 transition(O, L1_GETS, OO) {
2499 d_sendDataToL1GETS;
2500 r_setMRU;
2501 uu_profileHit;
2502 o_popL1RequestQueue;
2503 }
2504
2505 transition(OO, Unblock, OLS) {
2506 g_recordLocalSharer;
2507 n_popResponseQueue;
2508 wa_wakeUpDependents;
2509 }
2510
2511 transition(OO, Exclusive_Unblock, ILX) {
2512 g_recordLocalExclusive
2513 y_copyCacheStateToDir;
2514 rr_deallocateL2CacheBlock;
2515 n_popResponseQueue;
2516 wa_wakeUpDependents;
2517 }
2518
2519
2520 // L1 WRITEBACKS
2521 transition(ILO, L1_PUTO, ILOW) {
2522 l_writebackAckNeedData;
2523 o_popL1RequestQueue;
2524 }
2525
2526 transition(ILOX, L1_PUTO, ILOXW) {
2527 l_writebackAckNeedData;
2528 o_popL1RequestQueue;
2529 }
2530
2531
2532 transition(ILOS, L1_PUTO, ILOSW) {
2533 l_writebackAckNeedData;
2534 o_popL1RequestQueue;
2535 }
2536
2537 transition(ILOSX, L1_PUTO, ILOSXW) {
2538 l_writebackAckNeedData;
2539 o_popL1RequestQueue;
2540 }
2541
2542
2543 // hmmm...keep data or drop. Just drop for now
2544 transition(ILOS, L1_PUTS_only, ILOW) {
2545 l_writebackAckDropData;
2546 o_popL1RequestQueue;
2547 }
2548
2549 transition(ILSW, Unblock, ILS) {
2550 gg_clearSharerFromL1Response;
2551 n_popResponseQueue;
2552 wa_wakeUpDependents;
2553 }
2554
2555 transition(ILOW, Unblock, ILO) {
2556 gg_clearSharerFromL1Response;
2557 n_popResponseQueue;
2558 wa_wakeUpDependents;
2559 }
2560
2561 transition(ILOSX, L1_PUTS_only, ILOXW) {
2562 l_writebackAckDropData;
2563 o_popL1RequestQueue;
2564 }
2565
2566 transition(ILOXW, Unblock, ILOX) {
2567 gg_clearSharerFromL1Response;
2568 n_popResponseQueue;
2569 wa_wakeUpDependents;
2570 }
2571
2572 // hmmm...keep data or drop. Just drop for now
2573 transition(ILOS, L1_PUTS, ILOSW) {
2574 l_writebackAckDropData;
2575 o_popL1RequestQueue;
2576 }
2577
2578 transition(ILOSX, L1_PUTS, ILOSXW) {
2579 l_writebackAckDropData;
2580 o_popL1RequestQueue;
2581 }
2582
2583 transition(ILOSW, Unblock, ILOS) {
2584 gg_clearSharerFromL1Response;
2585 n_popResponseQueue;
2586 wa_wakeUpDependents;
2587 }
2588
2589 transition(ILOSXW, Unblock, ILOSX) {
2590 gg_clearSharerFromL1Response;
2591 n_popResponseQueue;
2592 wa_wakeUpDependents;
2593 }
2594
2595 transition(SLS, L1_PUTS, SLSW) {
2596 l_writebackAckDropData;
2597 o_popL1RequestQueue;
2598 }
2599
2600 transition(SLS, L1_PUTS_only, SW) {
2601 l_writebackAckDropData;
2602 o_popL1RequestQueue;
2603 }
2604
2605 transition(SW, {Unblock}, S) {
2606 gg_clearSharerFromL1Response;
2607 n_popResponseQueue;
2608 wa_wakeUpDependents;
2609 }
2610
2611 transition(OLS, L1_PUTS, OLSW) {
2612 l_writebackAckDropData;
2613 o_popL1RequestQueue;
2614 }
2615
2616 transition(ILS, L1_PUTS, ILSW) {
2617 l_writebackAckNeedData;
2618 o_popL1RequestQueue;
2619 }
2620
2621 transition(ILS, L1_PUTS_only, IW) {
2622 l_writebackAckNeedData;
2623 o_popL1RequestQueue;
2624 }
2625
2626 transition(OLS, L1_PUTS_only, OW) {
2627 l_writebackAckDropData;
2628 o_popL1RequestQueue;
2629 }
2630
2631 transition(OLSX, L1_PUTS_only, OXW) {
2632 l_writebackAckDropData;
2633 o_popL1RequestQueue;
2634 }
2635
2636 transition(OLSX, L1_PUTS, OLSXW) {
2637 l_writebackAckDropData;
2638 o_popL1RequestQueue;
2639 }
2640
2641 transition(OLSXW, {Unblock}, OLSX) {
2642 gg_clearSharerFromL1Response;
2643 n_popResponseQueue;
2644 wa_wakeUpDependents;
2645 }
2646
2647 transition(OW, {Unblock}, O) {
2648 gg_clearSharerFromL1Response;
2649 n_popResponseQueue;
2650 wa_wakeUpDependents;
2651 }
2652
2653 transition(OXW, {Unblock}, M) {
2654 gg_clearSharerFromL1Response;
2655 n_popResponseQueue;
2656 wa_wakeUpDependents;
2657 }
2658
2659 transition(ILX, L1_PUTX, ILXW ) {
2660 l_writebackAckNeedData;
2661 o_popL1RequestQueue;
2662 }
2663
2664 transition(ILXW, L1_WBDIRTYDATA, M) {
2665 gg_clearLocalSharers;
2666 vv_allocateL2CacheBlock;
2667 y_copyDirToCacheAndRemove;
2668 u_writeDirtyDataToCache;
2669 o_popL1RequestQueue;
2670 wa_wakeUpDependents;
2671 }
2672
2673 // clean writeback
2674 transition(ILXW, L1_WBCLEANDATA, M) {
2675 gg_clearLocalSharers;
2676 vv_allocateL2CacheBlock;
2677 y_copyDirToCacheAndRemove;
2678 u_writeCleanDataToCache;
2679 o_popL1RequestQueue;
2680 wa_wakeUpDependents;
2681 }
2682
2683 transition(ILXW, Unblock, ILX) {
2684 // writeback canceled because L1 invalidated
2685 n_popResponseQueue;
2686 wa_wakeUpDependents;
2687 }
2688
2689 transition(ILSW, L1_WBCLEANDATA, SLS) {
2690 vv_allocateL2CacheBlock;
2691 y_copyDirToCacheAndRemove;
2692 u_writeCleanDataToCache;
2693 gg_clearSharerFromL1Request;
2694 o_popL1RequestQueue;
2695 wa_wakeUpDependents;
2696 }
2697
2698 transition(IW, L1_WBCLEANDATA, S) {
2699 vv_allocateL2CacheBlock;
2700 y_copyDirToCacheAndRemove;
2701 u_writeCleanDataToCache;
2702 gg_clearSharerFromL1Request;
2703 o_popL1RequestQueue;
2704 wa_wakeUpDependents;
2705 }
2706
2707 // Owner can have dirty data
2708 transition(ILOW, L1_WBDIRTYDATA, O) {
2709 vv_allocateL2CacheBlock;
2710 y_copyDirToCacheAndRemove;
2711 gg_clearOwnerFromL1Request;
2712 u_writeDirtyDataToCache;
2713 o_popL1RequestQueue;
2714 wa_wakeUpDependents;
2715 }
2716
2717 transition(ILOW, L1_WBCLEANDATA, O) {
2718 vv_allocateL2CacheBlock;
2719 y_copyDirToCacheAndRemove;
2720 gg_clearOwnerFromL1Request;
2721 u_writeCleanDataToCache;
2722 o_popL1RequestQueue;
2723 wa_wakeUpDependents;
2724 }
2725
2726 transition(ILOXW, L1_WBDIRTYDATA, M) {
2727 vv_allocateL2CacheBlock;
2728 y_copyDirToCacheAndRemove;
2729 gg_clearOwnerFromL1Request;
2730 u_writeDirtyDataToCache;
2731 o_popL1RequestQueue;
2732 wa_wakeUpDependents;
2733 }
2734
2735 transition(ILOXW, L1_WBCLEANDATA, M) {
2736 vv_allocateL2CacheBlock;
2737 y_copyDirToCacheAndRemove;
2738 gg_clearOwnerFromL1Request;
2739 u_writeCleanDataToCache;
2740 o_popL1RequestQueue;
2741 wa_wakeUpDependents;
2742 }
2743
2744 transition(ILOSW, L1_WBDIRTYDATA, OLS) {
2745 vv_allocateL2CacheBlock;
2746 y_copyDirToCacheAndRemove;
2747 gg_clearOwnerFromL1Request;
2748 u_writeDirtyDataToCache;
2749 o_popL1RequestQueue;
2750 wa_wakeUpDependents;
2751 }
2752
2753 transition(ILOSW, L1_WBCLEANDATA, OLS) {
2754 vv_allocateL2CacheBlock;
2755 y_copyDirToCacheAndRemove;
2756 gg_clearOwnerFromL1Request;
2757 u_writeCleanDataToCache;
2758 o_popL1RequestQueue;
2759 wa_wakeUpDependents;
2760 }
2761
2762 transition(ILOSXW, L1_WBDIRTYDATA, OLSX) {
2763 vv_allocateL2CacheBlock;
2764 y_copyDirToCacheAndRemove;
2765 gg_clearOwnerFromL1Request;
2766 u_writeDirtyDataToCache;
2767 o_popL1RequestQueue;
2768 wa_wakeUpDependents;
2769 }
2770
2771 transition(ILOSXW, L1_WBCLEANDATA, OLSX) {
2772 vv_allocateL2CacheBlock;
2773 y_copyDirToCacheAndRemove;
2774 gg_clearOwnerFromL1Request;
2775 u_writeCleanDataToCache;
2776 o_popL1RequestQueue;
2777 wa_wakeUpDependents;
2778 }
2779
2780 transition(SLSW, {Unblock}, SLS) {
2781 gg_clearSharerFromL1Response;
2782 n_popResponseQueue;
2783 wa_wakeUpDependents;
2784 }
2785
2786 transition(OLSW, {Unblock}, OLS) {
2787 gg_clearSharerFromL1Response;
2788 n_popResponseQueue;
2789 wa_wakeUpDependents;
2790 }
2791
2792
2793 // L2 WRITEBACKS
2794 transition({I, S}, L2_Replacement, I) {
2795 rr_deallocateL2CacheBlock;
2796 }
2797
2798 transition(ILS, L2_Replacement) {
2799 y_copyCacheStateToDir;
2800 rr_deallocateL2CacheBlock;
2801 }
2802
2803 transition(ILX, L2_Replacement ) {
2804 y_copyCacheStateToDir;
2805 rr_deallocateL2CacheBlock;
2806 }
2807
2808 transition({ILO, ILOS}, L2_Replacement ) {
2809 y_copyCacheStateToDir;
2810 rr_deallocateL2CacheBlock;
2811 }
2812
2813 transition(SLS, L2_Replacement, ILS) {
2814 y_copyCacheStateToDir;
2815 rr_deallocateL2CacheBlock;
2816 }
2817
2818 transition({OLS, OLSX}, L2_Replacement, OLSI) {
2819 y_copyCacheStateToDir;
2820 b_issuePUTO_ls;
2821 i_allocateTBE;
2822 rr_deallocateL2CacheBlock;
2823 }
2824
2825
2826 transition(O, L2_Replacement, OI) {
2827 b_issuePUTO;
2828 i_allocateTBE;
2829 rr_deallocateL2CacheBlock;
2830 }
2831
2832 transition(M, L2_Replacement, MI) {
2833 b_issuePUTX;
2834 i_allocateTBE;
2835 rr_deallocateL2CacheBlock;
2836 }
2837
2838 transition(OLSI, Fwd_GETX, ILSI) {
2839 t_recordFwdXID;
2840 ee_sendLocalInv;
2841 m_popRequestQueue;
2842 }
2843
2844 transition(ILSI, IntAck) {
2845 m_decrementNumberOfMessagesInt;
2846 o_checkForIntCompletion;
2847 n_popResponseQueue;
2848 }
2849
2850 transition(ILSI, All_Acks, MII) {
2851 gg_clearLocalSharers;
2852 c_sendDataFromTBEToFwdGETX;
2853 n_popTriggerQueue;
2854 }
2855
2856 transition(OLSI, Fwd_GETS) {
2857 t_recordFwdSID;
2858 c_sendDataFromTBEToFwdGETS;
2859 m_popRequestQueue;
2860 }
2861
2862 transition({MI, OI}, Fwd_GETS, OI) {
2863 t_recordFwdSID;
2864 c_sendDataFromTBEToFwdGETS;
2865 m_popRequestQueue;
2866 }
2867
2868 transition({MI, OI}, Fwd_DMA, OI) {
2869 cd_sendDataFromTBEToFwdDma;
2870 da_sendDmaAckUnblock;
2871 m_popRequestQueue;
2872 }
2873
2874 transition(OLSI, Fwd_DMA) {
2875 cd_sendDataFromTBEToFwdDma;
2876 da_sendDmaAckUnblock;
2877 m_popRequestQueue;
2878 }
2879
2880 transition({MI, OI}, Fwd_GETX, MII) {
2881 t_recordFwdXID;
2882 c_sendDataFromTBEToFwdGETX;
2883 m_popRequestQueue;
2884 }
2885
2886 transition({MI, OI}, Writeback_Ack, I) {
2887 qq_sendDataFromTBEToMemory;
2888 s_deallocateTBE;
2889 n_popResponseQueue;
2890 wa_wakeUpDependents;
2891 }
2892
2893 transition(MII, Writeback_Nack, I) {
2894 s_deallocateTBE;
2895 n_popResponseQueue;
2896 wa_wakeUpDependents;
2897 }
2898
2899 transition(OI, Writeback_Nack) {
2900 b_issuePUTO;
2901 n_popResponseQueue;
2902 }
2903
2904 transition(OLSI, Writeback_Ack, ILS) {
2905 qq_sendDataFromTBEToMemory;
2906 s_deallocateTBE;
2907 n_popResponseQueue;
2908 wa_wakeUpDependents;
2909 }
2910
2911 transition(MII, Writeback_Ack, I) {
2912 f_sendUnblock;
2913 s_deallocateTBE;
2914 n_popResponseQueue;
2915 wa_wakeUpDependents;
2916 }
2917
2918 transition(ILSI, Writeback_Ack, ILS) {
2919 f_sendUnblock;
2920 s_deallocateTBE;
2921 n_popResponseQueue;
2922 wa_wakeUpDependents;
2923 }
2924}