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            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) {
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}
2925