1/*
2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Authors: Jason Power
34 */
35
36machine(MachineType:RegionDir, "Region Directory for AMD_Base-like protocol")
37: CacheMemory *cacheMemory; // stores only region addresses. Must set block size same as below
38  NodeID cpuRegionBufferNum;
39  NodeID gpuRegionBufferNum;
40  int blocksPerRegion := 64; // 4k regions
41  Cycles toDirLatency := 10;    // Latency to fwd requests and send invs to directory
42  bool always_migrate := "False";
43  bool sym_migrate := "False";
44  bool asym_migrate := "False";
45  bool noTCCdir := "False";
46  int TCC_select_num_bits := 1;
47
48  // To the directory
49  MessageBuffer * requestToDir, network="To", virtual_network="5", vnet_type="request";
50
51  // To the region buffers
52  MessageBuffer * notifyToRBuffer, network="To", virtual_network="7", vnet_type="request";
53  MessageBuffer * probeToRBuffer, network="To", virtual_network="8", vnet_type="request";
54
55  // From the region buffers
56  MessageBuffer * responseFromRBuffer, network="From", virtual_network="2", vnet_type="response";
57  MessageBuffer * requestFromRegBuf, network="From", virtual_network="0", vnet_type="request";
58
59  MessageBuffer * triggerQueue;
60{
61
62  // States
63  state_declaration(State, desc="Region states", default="RegionDir_State_NP") {
64    NP, AccessPermission:Invalid,       desc="Not present in region directory";
65    P,  AccessPermission:Invalid,       desc="Region is private to owner";
66    S,  AccessPermission:Invalid,       desc="Region is shared between CPU and GPU";
67
68    P_NP,  AccessPermission:Invalid,    desc="Evicting the region";
69    NP_P,  AccessPermission:Invalid,    desc="Must wait for ack from R-buf";
70    NP_S,  AccessPermission:Invalid,    desc="Must wait for ack from R-buf";
71    P_P,   AccessPermission:Invalid,    desc="Waiting for ack from R-buf";
72    S_S,   AccessPermission:Invalid,    desc="Waiting for ack from R-buf";
73    P_S,   AccessPermission:Invalid,    desc="Downgrading the region";
74    S_P,   AccessPermission:Invalid,    desc="Upgrading the region";
75    P_AS,  AccessPermission:Invalid,    desc="Sent invalidates, waiting for acks";
76    S_AP,  AccessPermission:Invalid,    desc="Sent invalidates, waiting for acks";
77    P_AP,  AccessPermission:Invalid,    desc="Sent invalidates, waiting for acks";
78
79    SP_NP_W, AccessPermission:Invalid,   desc="Last sharer writing back, waiting for ack";
80    S_W,   AccessPermission:Invalid,   desc="Sharer writing back, waiting for ack";
81
82    P_AP_W, AccessPermission:Invalid,   desc="Fwded request to dir, waiting for ack";
83    P_AS_W, AccessPermission:Invalid,   desc="Fwded request to dir, waiting for ack";
84    S_AP_W, AccessPermission:Invalid,   desc="Fwded request to dir, waiting for ack";
85  }
86
87  enumeration(Event, desc="Region directory events") {
88    SendInv,        desc="Send inv message to any machine that has a region buffer";
89    SendUpgrade,    desc="Send upgrade message to any machine that has a region buffer";
90    SendDowngrade,  desc="Send downgrade message to any machine that has a region buffer";
91
92    Evict,          desc="Evict this region";
93
94    UpgradeRequest, desc="Request from r-buf for an upgrade";
95    SharedRequest,  desc="Request from r-buf for read";
96    PrivateRequest, desc="Request from r-buf for write";
97
98    InvAckCore,     desc="Ack from region buffer to order the invalidate";
99    InvAckCoreNoShare,     desc="Ack from region buffer to order the invalidate, and it does not have the region";
100    CPUPrivateAck,  desc="Ack from region buffer to order private notification";
101
102    LastAck,      desc="Done eviciting all the blocks";
103
104    StaleCleanWbRequest, desc="stale clean writeback reqeust";
105    StaleCleanWbRequestNoShare, desc="stale clean wb req from a cache which should be removed from sharers";
106    CleanWbRequest, desc="clean writeback reqeust, multiple sharers";
107    CleanWbRequest_LastSharer, desc="clean writeback reqeust, last sharer";
108    WritebackAck,   desc="Writeback Ack from region buffer";
109    DirReadyAck,   desc="Directory is ready, waiting Ack from region buffer";
110
111    TriggerInv,   desc="trigger invalidate message";
112    TriggerDowngrade, desc="trigger downgrade message";
113  }
114
115  enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
116    DataArrayRead,    desc="Read the data array";
117    DataArrayWrite,   desc="Write the data array";
118    TagArrayRead,     desc="Read the data array";
119    TagArrayWrite,    desc="Write the data array";
120  }
121
122  structure(BoolVec, external="yes") {
123    bool at(int);
124    void resize(int);
125    void clear();
126  }
127
128  structure(Entry, desc="Region entry", interface="AbstractCacheEntry") {
129    Addr addr,        desc="Base address of this region";
130    NetDest Sharers,        desc="Set of machines that are sharing, but not owners";
131    State RegionState,      desc="Region state";
132    DataBlock DataBlk,      desc="Data for the block (always empty in region dir)";
133    MachineID Owner,        desc="Machine which owns all blocks in this region";
134    Cycles ProbeStart,        desc="Time when the first probe request was issued";
135    bool LastWriten, default="false", desc="The last time someone accessed this region, it wrote it";
136    bool LastWritenByCpu, default="false", desc="The last time the CPU accessed this region, it wrote it";
137    bool LastWritenByGpu, default="false", desc="The last time the GPU accessed this region, it wrote it";
138  }
139
140  structure(TBE, desc="...") {
141    State TBEState,         desc="Transient state";
142    MachineID Owner,        desc="Machine which owns all blocks in this region";
143    NetDest Sharers,        desc="Set of machines to send evicts";
144    int NumValidBlocks,     desc="Number of blocks valid so we don't have to count a BoolVec";
145    bool AllAcksReceived,   desc="Got all necessary acks from dir";
146    CoherenceRequestType MsgType, desc="Msg type for the evicts could be inv or dwngrd";
147    Cycles ProbeRequestTime, default="Cycles(0)", desc="Start of probe request";
148    Cycles InitialRequestTime, default="Cycles(0)", desc="To forward back on out msg";
149    Addr DemandAddress, desc="Demand address from original request";
150    uint64_t probe_id,        desc="probe id for lifetime profiling";
151  }
152
153  structure(TBETable, external="yes") {
154    TBE lookup(Addr);
155    void allocate(Addr);
156    void deallocate(Addr);
157    bool isPresent(Addr);
158  }
159
160  // Stores only region addresses
161  TBETable TBEs, template="<RegionDir_TBE>", constructor="m_number_of_TBEs";
162  int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
163
164  Tick clockEdge();
165  Tick cyclesToTicks(Cycles c);
166
167  void set_cache_entry(AbstractCacheEntry b);
168  void unset_cache_entry();
169  void set_tbe(TBE b);
170  void unset_tbe();
171  void wakeUpAllBuffers();
172  void wakeUpBuffers(Addr a);
173  Cycles curCycle();
174  MachineID mapAddressToMachine(Addr addr, MachineType mtype);
175
176  int blockBits,  default="RubySystem::getBlockSizeBits()";
177  int blockBytes, default="RubySystem::getBlockSizeBytes()";
178  int regionBits, default="log2(m_blocksPerRegion)";
179
180  // Functions
181
182  MachineID getCoreMachine(MachineID rBuf, Addr address) {
183    if (machineIDToNodeID(rBuf) == cpuRegionBufferNum) {
184      return createMachineID(MachineType:CorePair, intToID(0));
185    } else if (machineIDToNodeID(rBuf) == gpuRegionBufferNum) {
186      if (noTCCdir) {
187        return mapAddressToRange(address,MachineType:TCC,
188                                    TCC_select_low_bit, TCC_select_num_bits);
189      } else {
190        return createMachineID(MachineType:TCCdir, intToID(0));
191      }
192    } else {
193      error("Unexpected region buffer number");
194    }
195  }
196
197  bool isCpuMachine(MachineID rBuf) {
198    if (machineIDToNodeID(rBuf) == cpuRegionBufferNum) {
199      return true;
200    } else if (machineIDToNodeID(rBuf) == gpuRegionBufferNum) {
201      return false;
202    } else {
203      error("Unexpected region buffer number");
204    }
205  }
206
207  bool symMigrate(Entry cache_entry) {
208      return cache_entry.LastWriten;
209  }
210
211  bool asymMigrate(Entry cache_entry, MachineID requestor) {
212      if (isCpuMachine(requestor)) {
213          return cache_entry.LastWritenByCpu;
214      } else {
215          return cache_entry.LastWritenByGpu;
216      }
217  }
218
219  int getRegionOffset(Addr addr) {
220    if (blocksPerRegion > 1) {
221      Addr offset := bitSelect(addr, blockBits, regionBits+blockBits-1);
222      int ret := addressToInt(offset);
223      assert(ret < blocksPerRegion);
224      return ret;
225    } else {
226      return 0;
227    }
228  }
229
230  Addr getRegionBase(Addr addr) {
231    return maskLowOrderBits(addr, blockBits+regionBits);
232  }
233
234  Addr getNextBlock(Addr addr) {
235    Addr a := addr;
236    makeNextStrideAddress(a, 1);
237    return a;
238  }
239
240  bool presentOrAvail(Addr addr) {
241    DPRINTF(RubySlicc, "Present? %s, avail? %s\n", cacheMemory.isTagPresent(getRegionBase(addr)), cacheMemory.cacheAvail(getRegionBase(addr)));
242    return cacheMemory.isTagPresent(getRegionBase(addr)) || cacheMemory.cacheAvail(getRegionBase(addr));
243  }
244
245  // Returns a region entry!
246  Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
247    return static_cast(Entry, "pointer", cacheMemory.lookup(getRegionBase(addr)));
248  }
249
250  TBE getTBE(Addr addr), return_by_pointer="yes" {
251    return TBEs.lookup(getRegionBase(addr));
252  }
253
254  DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
255    return getCacheEntry(getRegionBase(addr)).DataBlk;
256  }
257
258  State getState(TBE tbe, Entry cache_entry, Addr addr) {
259    if (is_valid(tbe)) {
260      return tbe.TBEState;
261    } else if (is_valid(cache_entry)) {
262      return cache_entry.RegionState;
263    }
264    return State:NP;
265  }
266
267  void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
268    if (is_valid(tbe)) {
269        tbe.TBEState := state;
270    }
271    if (is_valid(cache_entry)) {
272        cache_entry.RegionState := state;
273    }
274  }
275
276  AccessPermission getAccessPermission(Addr addr) {
277    TBE tbe := getTBE(addr);
278    if(is_valid(tbe)) {
279      return RegionDir_State_to_permission(tbe.TBEState);
280    }
281    Entry cache_entry := getCacheEntry(addr);
282    if(is_valid(cache_entry)) {
283      return RegionDir_State_to_permission(cache_entry.RegionState);
284    }
285    return AccessPermission:NotPresent;
286  }
287
288  void setAccessPermission(Entry cache_entry, Addr addr, State state) {
289    if (is_valid(cache_entry)) {
290      cache_entry.changePermission(RegionDir_State_to_permission(state));
291    }
292  }
293
294  void functionalRead(Addr addr, Packet *pkt) {
295    functionalMemoryRead(pkt);
296  }
297
298  int functionalWrite(Addr addr, Packet *pkt) {
299    if (functionalMemoryWrite(pkt)) {
300      return 1;
301    } else {
302      return 0;
303    }
304  }
305
306  void recordRequestType(RequestType request_type, Addr addr) {
307    if (request_type == RequestType:DataArrayRead) {
308      cacheMemory.recordRequestType(CacheRequestType:DataArrayRead, addr);
309    } else if (request_type == RequestType:DataArrayWrite) {
310      cacheMemory.recordRequestType(CacheRequestType:DataArrayWrite, addr);
311    } else if (request_type == RequestType:TagArrayRead) {
312      cacheMemory.recordRequestType(CacheRequestType:TagArrayRead, addr);
313    } else if (request_type == RequestType:TagArrayWrite) {
314      cacheMemory.recordRequestType(CacheRequestType:TagArrayWrite, addr);
315    }
316  }
317
318  bool checkResourceAvailable(RequestType request_type, Addr addr) {
319    if (request_type == RequestType:DataArrayRead) {
320      return cacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
321    } else if (request_type == RequestType:DataArrayWrite) {
322      return cacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
323    } else if (request_type == RequestType:TagArrayRead) {
324      return cacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
325    } else if (request_type == RequestType:TagArrayWrite) {
326      return cacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
327    } else {
328      error("Invalid RequestType type in checkResourceAvailable");
329      return true;
330    }
331  }
332
333  out_port(triggerQueue_out, TriggerMsg, triggerQueue);
334
335  out_port(requestNetwork_out, CPURequestMsg, requestToDir);
336  out_port(notifyNetwork_out, CPURequestMsg, notifyToRBuffer);
337  out_port(probeNetwork_out, NBProbeRequestMsg, probeToRBuffer);
338
339  in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=2) {
340    if (triggerQueue_in.isReady(clockEdge())) {
341      peek(triggerQueue_in, TriggerMsg) {
342        assert(in_msg.addr == getRegionBase(in_msg.addr));
343        Entry cache_entry := getCacheEntry(in_msg.addr);
344        TBE tbe := getTBE(in_msg.addr);
345        DPRINTF(RubySlicc, "trigger msg: %s (%s)\n", in_msg, getRegionBase(in_msg.addr));
346        if (in_msg.Type == TriggerType:AcksComplete) {
347          assert(is_valid(tbe));
348          trigger(Event:LastAck, in_msg.addr, cache_entry, tbe);
349        } else if (in_msg.Type == TriggerType:InvRegion) {
350          assert(is_valid(tbe));
351          trigger(Event:TriggerInv, in_msg.addr, cache_entry, tbe);
352        } else if (in_msg.Type == TriggerType:DowngradeRegion) {
353          assert(is_valid(tbe));
354          trigger(Event:TriggerDowngrade, in_msg.addr, cache_entry, tbe);
355        } else {
356          error("Unknown trigger message");
357        }
358      }
359    }
360  }
361
362  in_port(responseNetwork_in, ResponseMsg, responseFromRBuffer, rank=1) {
363    if (responseNetwork_in.isReady(clockEdge())) {
364      peek(responseNetwork_in, ResponseMsg) {
365        TBE tbe := getTBE(in_msg.addr);
366        Entry cache_entry := getCacheEntry(in_msg.addr);
367        if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
368          assert(in_msg.addr == getRegionBase(in_msg.addr));
369          assert(is_valid(tbe));
370          if (in_msg.NotCached) {
371            trigger(Event:InvAckCoreNoShare, in_msg.addr, cache_entry, tbe);
372          } else {
373            trigger(Event:InvAckCore, in_msg.addr, cache_entry, tbe);
374          }
375        } else if (in_msg.Type == CoherenceResponseType:PrivateAck) {
376          assert(in_msg.addr == getRegionBase(in_msg.addr));
377          assert(is_valid(cache_entry));
378          //Fix Me...add back in: assert(cache_entry.Sharers.isElement(in_msg.Sender));
379          trigger(Event:CPUPrivateAck, in_msg.addr, cache_entry, tbe);
380        } else if (in_msg.Type == CoherenceResponseType:RegionWbAck) {
381            //Fix Me...add back in: assert(cache_entry.Sharers.isElement(in_msg.Sender) == false);
382          assert(in_msg.addr == getRegionBase(in_msg.addr));
383          trigger(Event:WritebackAck, in_msg.addr, cache_entry, tbe);
384        } else if (in_msg.Type == CoherenceResponseType:DirReadyAck) {
385            assert(is_valid(tbe));
386            trigger(Event:DirReadyAck, getRegionBase(in_msg.addr), cache_entry, tbe);
387        } else {
388          error("Invalid response type");
389        }
390      }
391    }
392  }
393
394  // In from cores
395  // NOTE: We get the cache / TBE entry based on the region address,
396  //       but pass the block address to the actions
397  in_port(requestNetwork_in, CPURequestMsg, requestFromRegBuf, rank=0) {
398    if (requestNetwork_in.isReady(clockEdge())) {
399      peek(requestNetwork_in, CPURequestMsg) {
400        //assert(in_msg.addr == getRegionBase(in_msg.addr));
401        Addr address := getRegionBase(in_msg.addr);
402        DPRINTF(RubySlicc, "Got %s, base %s\n", in_msg.addr, address);
403        if (presentOrAvail(address)) {
404          TBE tbe := getTBE(address);
405          Entry cache_entry := getCacheEntry(address);
406          if (in_msg.Type == CoherenceRequestType:PrivateRequest) {
407            if (is_valid(cache_entry) && (cache_entry.Owner != in_msg.Requestor ||
408                getState(tbe, cache_entry, address) == State:S)) {
409              trigger(Event:SendInv, address, cache_entry, tbe);
410            } else {
411              trigger(Event:PrivateRequest, address, cache_entry, tbe);
412            }
413          } else if (in_msg.Type == CoherenceRequestType:SharedRequest) {
414            if (is_invalid(cache_entry)) {
415              // If no one has ever requested this region give private permissions
416              trigger(Event:PrivateRequest, address, cache_entry, tbe);
417            } else {
418                if (always_migrate ||
419                    (sym_migrate && symMigrate(cache_entry)) ||
420                    (asym_migrate && asymMigrate(cache_entry, in_msg.Requestor))) {
421                    if (cache_entry.Sharers.count() == 1 &&
422                        cache_entry.Sharers.isElement(in_msg.Requestor)) {
423                        trigger(Event:UpgradeRequest, address, cache_entry, tbe);
424                    } else {
425                        trigger(Event:SendInv, address, cache_entry, tbe);
426                    }
427                } else { // don't migrate
428                    if(cache_entry.Sharers.isElement(in_msg.Requestor) ||
429                       getState(tbe, cache_entry, address) == State:S) {
430                        trigger(Event:SharedRequest, address, cache_entry, tbe);
431                    } else {
432                        trigger(Event:SendDowngrade, address, cache_entry, tbe);
433                    }
434                }
435            }
436          } else if (in_msg.Type == CoherenceRequestType:UpgradeRequest) {
437            if (is_invalid(cache_entry)) {
438              trigger(Event:PrivateRequest, address, cache_entry, tbe);
439            } else if (cache_entry.Sharers.count() == 1 && cache_entry.Sharers.isElement(in_msg.Requestor)) {
440              trigger(Event:UpgradeRequest, address, cache_entry, tbe);
441            } else {
442              trigger(Event:SendUpgrade, address, cache_entry, tbe);
443            }
444          } else if (in_msg.Type == CoherenceRequestType:CleanWbRequest) {
445            if (is_invalid(cache_entry) || cache_entry.Sharers.isElement(in_msg.Requestor) == false) {
446              trigger(Event:StaleCleanWbRequest, address, cache_entry, tbe);
447            } else {
448                DPRINTF(RubySlicc, "wb address %s(%s) owner %s sharers %s requestor %s %d %d\n", in_msg.addr, getRegionBase(in_msg.addr), cache_entry.Owner, cache_entry.Sharers, in_msg.Requestor, cache_entry.Sharers.isElement(in_msg.Requestor), cache_entry.Sharers.count());
449                if (cache_entry.Sharers.isElement(in_msg.Requestor) && cache_entry.Sharers.count() == 1) {
450                    DPRINTF(RubySlicc, "last wb\n");
451                    trigger(Event:CleanWbRequest_LastSharer, address, cache_entry, tbe);
452                } else {
453                    DPRINTF(RubySlicc, "clean wb\n");
454                    trigger(Event:CleanWbRequest, address, cache_entry, tbe);
455                }
456            }
457          } else {
458            error("unknown region dir request type");
459          }
460        } else {
461          Addr victim := cacheMemory.cacheProbe(getRegionBase(in_msg.addr));
462          TBE victim_tbe := getTBE(victim);
463          Entry victim_entry := getCacheEntry(victim);
464          DPRINTF(RubySlicc, "Evicting address %s for new region at address %s(%s)\n", victim, in_msg.addr, getRegionBase(in_msg.addr));
465          assert(is_valid(victim_entry));
466          trigger(Event:Evict, victim, victim_entry, victim_tbe);
467        }
468      }
469    }
470  }
471
472  // Actions
473
474  action(f_fwdReqToDir, "f", desc="Forward CPU request to directory") {
475    peek(requestNetwork_in, CPURequestMsg) {
476      enqueue(requestNetwork_out, CPURequestMsg, toDirLatency) {
477        out_msg.addr := in_msg.addr;  // This is the block address. "address" is the region address
478        out_msg.Type := in_msg.OriginalType;
479        out_msg.DataBlk := in_msg.DataBlk;
480        out_msg.Dirty := in_msg.Dirty;
481        out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
482        out_msg.WTRequestor := in_msg.WTRequestor;
483        out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
484        out_msg.Shared := in_msg.Shared;
485        out_msg.MessageSize := in_msg.MessageSize;
486        out_msg.Private := in_msg.Private;
487        out_msg.NoAckNeeded := true;
488        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
489        out_msg.ProbeRequestStartTime := curCycle();
490        out_msg.DemandRequest := true;
491        if (is_valid(cache_entry) && getState(tbe, cache_entry, address) != State:S) {
492            out_msg.Acks := cache_entry.Sharers.count();
493        } else {
494            out_msg.Acks := 0;
495        }
496      }
497    }
498  }
499
500  action(f_fwdReqToDirShared, "fs", desc="Forward CPU request to directory (shared)") {
501    peek(requestNetwork_in, CPURequestMsg) {
502      enqueue(requestNetwork_out, CPURequestMsg, toDirLatency) {
503        out_msg.addr := in_msg.addr;  // This is the block address. "address" is the region address
504        out_msg.Type := in_msg.OriginalType;
505        out_msg.DataBlk := in_msg.DataBlk;
506        out_msg.Dirty := in_msg.Dirty;
507        out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
508        out_msg.WTRequestor := in_msg.WTRequestor;
509        out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
510        out_msg.Shared := in_msg.Shared;
511        out_msg.MessageSize := in_msg.MessageSize;
512        out_msg.Private := in_msg.Private;
513        out_msg.NoAckNeeded := true;
514        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
515        out_msg.ProbeRequestStartTime := curCycle();
516        out_msg.DemandRequest := true;
517        out_msg.ForceShared := true;
518        if (is_valid(cache_entry) && getState(tbe, cache_entry, address) != State:S) {
519            out_msg.Acks := cache_entry.Sharers.count();
520        } else {
521            out_msg.Acks := 0;
522        }
523      }
524    }
525  }
526
527  action(f_fwdReqToDirWithAck, "fa", desc="Forward CPU request to directory with ack request") {
528    peek(requestNetwork_in, CPURequestMsg) {
529      enqueue(requestNetwork_out, CPURequestMsg, toDirLatency) {
530        out_msg.addr := in_msg.addr; // This is the block address. "address" is the region address
531        out_msg.Type := in_msg.OriginalType;
532        out_msg.DataBlk := in_msg.DataBlk;
533        out_msg.Dirty := in_msg.Dirty;
534        out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
535        out_msg.WTRequestor := in_msg.WTRequestor;
536        out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
537        out_msg.Shared := in_msg.Shared;
538        out_msg.MessageSize := in_msg.MessageSize;
539        out_msg.Private := in_msg.Private;
540        out_msg.NoAckNeeded := false;
541        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
542        out_msg.ProbeRequestStartTime := curCycle();
543        out_msg.DemandRequest := true;
544        if (is_valid(cache_entry)) {
545            out_msg.Acks := cache_entry.Sharers.count();
546            // Don't need an ack from the requestor!
547            if (cache_entry.Sharers.isElement(in_msg.Requestor)) {
548                out_msg.Acks := out_msg.Acks - 1;
549            }
550        } else {
551            out_msg.Acks := 0;
552        }
553      }
554    }
555  }
556
557  action(f_fwdReqToDirWithAckShared, "fas", desc="Forward CPU request to directory with ack request") {
558    peek(requestNetwork_in, CPURequestMsg) {
559      enqueue(requestNetwork_out, CPURequestMsg, toDirLatency) {
560        out_msg.addr := in_msg.addr; // This is the block address. "address" is the region address
561        out_msg.Type := in_msg.OriginalType;
562        out_msg.DataBlk := in_msg.DataBlk;
563        out_msg.Dirty := in_msg.Dirty;
564        out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
565        out_msg.WTRequestor := in_msg.WTRequestor;
566        out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
567        out_msg.Shared := in_msg.Shared;
568        out_msg.MessageSize := in_msg.MessageSize;
569        out_msg.Private := in_msg.Private;
570        out_msg.NoAckNeeded := false;
571        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
572        out_msg.ProbeRequestStartTime := curCycle();
573        out_msg.DemandRequest := true;
574        out_msg.ForceShared := true;
575        if (is_valid(cache_entry)) {
576            out_msg.Acks := cache_entry.Sharers.count();
577            // Don't need an ack from the requestor!
578            if (cache_entry.Sharers.isElement(in_msg.Requestor)) {
579                out_msg.Acks := out_msg.Acks - 1;
580            }
581        } else {
582            out_msg.Acks := 0;
583        }
584      }
585    }
586  }
587
588  action(a_allocateRegionEntry, "a", desc="Allocate a new entry") {
589    set_cache_entry(cacheMemory.allocate(getRegionBase(address), new Entry));
590    peek(requestNetwork_in, CPURequestMsg) {
591      APPEND_TRANSITION_COMMENT(in_msg.Requestor);
592    }
593  }
594
595  action(d_deallocateRegionEntry, "d", desc="Deallocate region entry") {
596    cacheMemory.deallocate(getRegionBase(address));
597    unset_cache_entry();
598  }
599
600  action(ra_receiveAck, "ra", desc="Mark TBE entry as received this ack") {
601    //assert(tbe.ValidBlocks.at(getRegionOffset(address)));
602    DPRINTF(RubySlicc, "received ack for %s reg: %s\n", address, getRegionBase(address));
603    tbe.NumValidBlocks := tbe.NumValidBlocks - 1;
604    assert(tbe.NumValidBlocks >= 0);
605    if (tbe.NumValidBlocks == 0) {
606      tbe.AllAcksReceived := true;
607      enqueue(triggerQueue_out, TriggerMsg, 1) {
608        out_msg.Type := TriggerType:AcksComplete;
609        out_msg.addr := address;
610      }
611    }
612    APPEND_TRANSITION_COMMENT(getRegionBase(address));
613    APPEND_TRANSITION_COMMENT(" Acks left receive ");
614    APPEND_TRANSITION_COMMENT(tbe.NumValidBlocks);
615  }
616
617  action(ca_checkAcks, "ca", desc="Check to see if we need more acks") {
618    if (tbe.NumValidBlocks == 0) {
619      tbe.AllAcksReceived := true;
620      enqueue(triggerQueue_out, TriggerMsg, 1) {
621        out_msg.Type := TriggerType:AcksComplete;
622        out_msg.addr := address;
623      }
624    }
625  }
626
627  action(ti_triggerInv, "ti", desc="") {
628      enqueue(triggerQueue_out, TriggerMsg, 1) {
629          out_msg.Type := TriggerType:InvRegion;
630          out_msg.addr := address;
631      }
632  }
633
634  action(td_triggerDowngrade, "td", desc="") {
635      enqueue(triggerQueue_out, TriggerMsg, 1) {
636        out_msg.Type := TriggerType:DowngradeRegion;
637        out_msg.addr := address;
638      }
639  }
640
641  action(t_allocateTBE, "t", desc="allocate TBE Entry") {
642    check_allocate(TBEs);
643    TBEs.allocate(getRegionBase(address));
644    set_tbe(getTBE(address));
645    if (is_valid(cache_entry)) {
646      tbe.Owner := cache_entry.Owner;
647      tbe.Sharers := cache_entry.Sharers;
648      tbe.AllAcksReceived := true; // assume no acks are required
649    }
650    tbe.ProbeRequestTime := curCycle();
651    peek(requestNetwork_in, CPURequestMsg) {
652      tbe.InitialRequestTime := in_msg.InitialRequestTime;
653      tbe.DemandAddress := in_msg.addr;
654    }
655    APPEND_TRANSITION_COMMENT(getRegionBase(address));
656    APPEND_TRANSITION_COMMENT(" Acks left ");
657    APPEND_TRANSITION_COMMENT(tbe.NumValidBlocks);
658    APPEND_TRANSITION_COMMENT(" Owner, ");
659    APPEND_TRANSITION_COMMENT(tbe.Owner);
660    APPEND_TRANSITION_COMMENT(" sharers, ");
661    APPEND_TRANSITION_COMMENT(tbe.Sharers);
662  }
663
664  action(ss_setSharers, "ss", desc="Add requestor to sharers") {
665    peek(requestNetwork_in, CPURequestMsg) {
666        cache_entry.Sharers.add(in_msg.Requestor);
667        APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
668    }
669  }
670
671  action(rs_removeSharer, "rs", desc="Remove requestor to sharers") {
672    peek(requestNetwork_in, CPURequestMsg) {
673        cache_entry.Sharers.remove(in_msg.Requestor);
674        APPEND_TRANSITION_COMMENT(" removing ");
675        APPEND_TRANSITION_COMMENT(in_msg.Requestor);
676        APPEND_TRANSITION_COMMENT(" sharers ");
677        APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
678    }
679  }
680
681  action(rsr_removeSharerResponse, "rsr", desc="Remove requestor to sharers") {
682    peek(responseNetwork_in, ResponseMsg) {
683        cache_entry.Sharers.remove(in_msg.Sender);
684        APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
685    }
686  }
687
688  action(cs_clearSharers, "cs", desc="Add requestor to sharers") {
689    cache_entry.Sharers.clear();
690  }
691
692  action(so_setOwner, "so", desc="Set the owner to the requestor") {
693    peek(requestNetwork_in, CPURequestMsg) {
694      cache_entry.Owner := in_msg.Requestor;
695      APPEND_TRANSITION_COMMENT(" Owner now: ");
696      APPEND_TRANSITION_COMMENT(cache_entry.Owner);
697    }
698  }
699
700  action(rr_removeRequestorFromTBE, "rr", desc="Remove requestor from TBE sharers") {
701    peek(requestNetwork_in, CPURequestMsg) {
702      tbe.Sharers.remove(in_msg.Requestor);
703    }
704  }
705
706  action(ur_updateDirtyStatusOnRequest, "ur", desc="Update dirty status on demand request") {
707      peek(requestNetwork_in, CPURequestMsg) {
708          if (is_valid(cache_entry)) {
709              if ((in_msg.Type == CoherenceRequestType:SharedRequest) &&
710                  (cache_entry.Sharers.isElement(in_msg.Requestor) == false)) {
711                  cache_entry.LastWriten := false;
712                  if (isCpuMachine(in_msg.Requestor)) {
713                      cache_entry.LastWritenByCpu := false;
714                  } else {
715                      cache_entry.LastWritenByGpu := false;
716                  }
717              } else if ((in_msg.Type == CoherenceRequestType:PrivateRequest) ||
718                         (in_msg.Type == CoherenceRequestType:UpgradeRequest)) {
719                  cache_entry.LastWriten := true;
720                  if (isCpuMachine(in_msg.Requestor)) {
721                      cache_entry.LastWritenByCpu := true;
722                  } else {
723                      cache_entry.LastWritenByGpu := true;
724                  }
725              }
726          }
727      }
728  }
729
730  action(ud_updateDirtyStatusWithWb, "ud", desc="Update dirty status on writeback") {
731      peek(requestNetwork_in, CPURequestMsg) {
732          if (is_valid(cache_entry) && in_msg.Dirty) {
733              cache_entry.LastWriten := true;
734              if (isCpuMachine(in_msg.Requestor)) {
735                  cache_entry.LastWritenByCpu := true;
736              } else {
737                  cache_entry.LastWritenByGpu := true;
738              }
739          }
740      }
741  }
742
743  action(sns_setNumAcksSharers, "sns", desc="Set number of acks to one per shared region buffer") {
744    assert(is_valid(tbe));
745    assert(is_valid(cache_entry));
746    tbe.NumValidBlocks := tbe.Sharers.count();
747  }
748
749  action(sno_setNumAcksOne, "sno", desc="Set number of acks to one per shared region buffer") {
750    assert(is_valid(tbe));
751    assert(is_valid(cache_entry));
752    tbe.NumValidBlocks := 1;
753  }
754
755  action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
756    TBEs.deallocate(getRegionBase(address));
757    APPEND_TRANSITION_COMMENT(" reg: ");
758    APPEND_TRANSITION_COMMENT(getRegionBase(address));
759    unset_tbe();
760  }
761
762  action(wb_sendWbNotice, "wb", desc="Send notice to cache that writeback is acknowledged") {
763    peek(requestNetwork_in, CPURequestMsg) {
764      enqueue(notifyNetwork_out, CPURequestMsg, 1) {
765        out_msg.addr := getRegionBase(address);
766        out_msg.Type := CoherenceRequestType:WbNotify;
767        out_msg.Destination.add(in_msg.Requestor);
768        out_msg.Requestor := machineID;
769        out_msg.MessageSize := MessageSizeType:Request_Control;
770        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
771      }
772    }
773  }
774
775  action(wbn_sendWbNoticeNoAck, "wbn", desc="Send notice to cache that writeback is acknowledged (no ack needed)") {
776    peek(requestNetwork_in, CPURequestMsg) {
777      enqueue(notifyNetwork_out, CPURequestMsg, 1) {
778        out_msg.addr := getRegionBase(address);
779        out_msg.Type := CoherenceRequestType:WbNotify;
780        out_msg.Destination.add(in_msg.Requestor);
781        out_msg.Requestor := machineID;
782        out_msg.MessageSize := MessageSizeType:Request_Control;
783        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
784        out_msg.NoAckNeeded := true;
785      }
786    }
787  }
788
789  action(b_sendPrivateNotice, "b", desc="Send notice to private cache that it has private access") {
790    peek(requestNetwork_in, CPURequestMsg) {
791      enqueue(notifyNetwork_out, CPURequestMsg, 1) {
792        out_msg.addr := getRegionBase(address);
793        out_msg.Type := CoherenceRequestType:PrivateNotify;
794        out_msg.Destination.add(in_msg.Requestor);
795        out_msg.Requestor := machineID;
796        out_msg.MessageSize := MessageSizeType:Request_Control;
797        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
798      }
799    }
800  }
801
802  action(bs_sendSharedNotice, "bs", desc="Send notice to private cache that it has private access") {
803    peek(requestNetwork_in, CPURequestMsg) {
804      enqueue(notifyNetwork_out, CPURequestMsg, 1) {
805        out_msg.addr := getRegionBase(address);
806        out_msg.Type := CoherenceRequestType:SharedNotify;
807        out_msg.Destination.add(in_msg.Requestor);
808        out_msg.Requestor := machineID;
809        out_msg.MessageSize := MessageSizeType:Request_Control;
810        out_msg.InitialRequestTime := in_msg.InitialRequestTime;
811      }
812    }
813  }
814
815  action(c_sendSharedNoticeToOrigReq, "c", desc="Send notice to private cache that it has shared access") {
816    assert(is_valid(tbe));
817    enqueue(notifyNetwork_out, CPURequestMsg, 1) {
818      out_msg.addr := getRegionBase(address);
819      out_msg.Type := CoherenceRequestType:SharedNotify;
820      out_msg.Destination.add(tbe.Owner);
821      out_msg.Requestor := machineID;
822      out_msg.MessageSize := MessageSizeType:Request_Control;
823      out_msg.ProbeRequestStartTime := tbe.ProbeRequestTime;
824      out_msg.InitialRequestTime := tbe.InitialRequestTime;
825      APPEND_TRANSITION_COMMENT("dest: ");
826      APPEND_TRANSITION_COMMENT(out_msg.Destination);
827    }
828  }
829
830  action(sp_sendPrivateNoticeToOrigReq, "sp", desc="Send notice to private cache that it has private access") {
831    assert(is_valid(tbe));
832    enqueue(notifyNetwork_out, CPURequestMsg, 1) {
833      out_msg.addr := getRegionBase(address);
834      out_msg.Type := CoherenceRequestType:PrivateNotify;
835      out_msg.Destination.add(tbe.Owner);
836      out_msg.Requestor := machineID;
837      out_msg.MessageSize := MessageSizeType:Request_Control;
838      out_msg.ProbeRequestStartTime := tbe.ProbeRequestTime;
839      out_msg.InitialRequestTime := tbe.InitialRequestTime;
840      APPEND_TRANSITION_COMMENT("dest: ");
841      APPEND_TRANSITION_COMMENT(out_msg.Destination);
842    }
843  }
844
845  action(i_RegionInvNotify, "i", desc="Send notice to private cache that it no longer has private access") {
846      enqueue(probeNetwork_out, NBProbeRequestMsg, 1) {
847          out_msg.addr := address;
848          out_msg.DemandAddress := tbe.DemandAddress;
849          //out_msg.Requestor := tbe.Requestor;
850          out_msg.Requestor := machineID;
851          out_msg.Type := ProbeRequestType:PrbInv;
852          //Fix me: assert(tbe.Sharers.count() > 0);
853          out_msg.DemandRequest := true;
854          out_msg.Destination := tbe.Sharers;
855          out_msg.MessageSize := MessageSizeType:Request_Control;
856          APPEND_TRANSITION_COMMENT("dest: ");
857          APPEND_TRANSITION_COMMENT(out_msg.Destination);
858      }
859  }
860
861  action(i0_RegionInvNotifyDemand0, "i0", desc="Send notice to private cache that it no longer has private access") {
862      enqueue(probeNetwork_out, NBProbeRequestMsg, 1) {
863          out_msg.addr := address;
864          // Demand address should default to 0 -> out_msg.DemandAddress := 0;
865          out_msg.Requestor := machineID;
866          out_msg.Type := ProbeRequestType:PrbInv;
867          out_msg.Destination := tbe.Sharers;
868          out_msg.MessageSize := MessageSizeType:Request_Control;
869          APPEND_TRANSITION_COMMENT("dest: ");
870          APPEND_TRANSITION_COMMENT(out_msg.Destination);
871      }
872  }
873
874  action(rd_RegionDowngrade, "rd", desc="Send notice to private cache that it only has shared access") {
875        enqueue(probeNetwork_out, NBProbeRequestMsg, 1) {
876            out_msg.addr := address;
877            out_msg.DemandAddress := tbe.DemandAddress;
878            out_msg.Requestor := machineID;
879            out_msg.Type := ProbeRequestType:PrbDowngrade;
880            out_msg.DemandRequest := true;
881            out_msg.Destination := tbe.Sharers;
882            out_msg.MessageSize := MessageSizeType:Request_Control;
883            APPEND_TRANSITION_COMMENT("dest: ");
884            APPEND_TRANSITION_COMMENT(out_msg.Destination);
885        }
886  }
887
888  action(p_popRequestQueue, "p", desc="Pop the request queue") {
889    requestNetwork_in.dequeue(clockEdge());
890  }
891
892  action(pt_popTriggerQueue, "pt", desc="Pop the trigger queue") {
893    triggerQueue_in.dequeue(clockEdge());
894  }
895
896  action(pr_popResponseQueue, "pr", desc="Pop the response queue") {
897    responseNetwork_in.dequeue(clockEdge());
898  }
899
900  action(s_stallAndWaitRequest, "s", desc="Stall and wait on the region address") {
901    Addr regAddr := getRegionBase(address);
902    stall_and_wait(requestNetwork_in, regAddr);
903  }
904
905  action(w_wakeUpRegionDependents, "w", desc="Wake up any requests waiting for this region") {
906    wakeUpBuffers(getRegionBase(address));
907  }
908
909  action(wa_wakeUpAllDependents, "wa", desc="Wake up any requests waiting for this region") {
910    wakeUpAllBuffers();
911  }
912
913  action(zz_recycleRequestQueue, "\z", desc="...") {
914    requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
915  }
916
917  action(z_stall, "z", desc="stall request queue") {
918    // fake state
919  }
920
921  action(mru_setMRU, "mru", desc="set MRU") {
922    cacheMemory.setMRU(address);
923  }
924
925 // Transistions
926
927  transition({NP_P, P_P, NP_S, S_S, S_P, P_S, P_NP, S_AP, P_AS, P_AP, SP_NP_W, S_W, P_AP_W, P_AS_W, S_AP_W}, {PrivateRequest, SharedRequest, UpgradeRequest, SendInv, SendUpgrade, SendDowngrade, CleanWbRequest, CleanWbRequest_LastSharer, StaleCleanWbRequest}) {
928    s_stallAndWaitRequest
929  }
930
931  transition({NP_P, P_P, NP_S, S_S, S_P, S_W, P_S, P_NP, S_AP, P_AS, P_AP, P_AP_W, P_AS_W, S_AP_W}, Evict) {
932    zz_recycleRequestQueue;
933  }
934
935  transition(NP, {PrivateRequest, SendUpgrade}, NP_P) {TagArrayRead, TagArrayWrite} {
936    a_allocateRegionEntry;
937    ur_updateDirtyStatusOnRequest;
938    f_fwdReqToDir;
939    b_sendPrivateNotice;
940    so_setOwner;
941    ss_setSharers;
942    t_allocateTBE;
943    p_popRequestQueue;
944  }
945
946  transition(P, {PrivateRequest, UpgradeRequest}, P_P) {TagArrayRead} {
947    mru_setMRU;
948    ur_updateDirtyStatusOnRequest;
949    f_fwdReqToDir;
950    b_sendPrivateNotice;
951    t_allocateTBE;
952    p_popRequestQueue;
953  }
954
955  transition({NP_P, P_P}, CPUPrivateAck, P) {
956    dt_deallocateTBE;
957    w_wakeUpRegionDependents;
958    pr_popResponseQueue;
959  }
960
961  transition({NP, P, S}, StaleCleanWbRequest) {TagArrayRead, TagArrayWrite} {
962      wbn_sendWbNoticeNoAck;
963      ud_updateDirtyStatusWithWb;
964      p_popRequestQueue;
965  }
966
967  transition(NP, SharedRequest, NP_S) {TagArrayRead, TagArrayWrite} {
968    a_allocateRegionEntry;
969    ur_updateDirtyStatusOnRequest;
970    f_fwdReqToDirShared;
971    bs_sendSharedNotice;
972    so_setOwner;
973    ss_setSharers;
974    t_allocateTBE;
975    p_popRequestQueue;
976  }
977
978  // Could probably do this in parallel with other shared requests
979  transition(S, SharedRequest, S_S) {TagArrayRead, TagArrayWrite} {
980    mru_setMRU;
981    ur_updateDirtyStatusOnRequest;
982    f_fwdReqToDirShared;
983    bs_sendSharedNotice;
984    ss_setSharers;
985    t_allocateTBE;
986    p_popRequestQueue;
987  }
988
989  transition({P, S}, CleanWbRequest_LastSharer, SP_NP_W) {TagArrayRead, TagArrayWrite} {
990    ud_updateDirtyStatusWithWb;
991    wb_sendWbNotice;
992    rs_removeSharer;
993    t_allocateTBE;
994    d_deallocateRegionEntry;
995    p_popRequestQueue;
996  }
997
998  transition(S, CleanWbRequest, S_W) {TagArrayRead, TagArrayWrite} {
999    ud_updateDirtyStatusWithWb;
1000    wb_sendWbNotice;
1001    rs_removeSharer;
1002    t_allocateTBE;
1003    p_popRequestQueue;
1004  }
1005
1006  transition(SP_NP_W, WritebackAck, NP) {
1007    dt_deallocateTBE;
1008    w_wakeUpRegionDependents;
1009    pr_popResponseQueue;
1010  }
1011
1012  transition(S_W, WritebackAck, S) {
1013    dt_deallocateTBE;
1014    w_wakeUpRegionDependents;
1015    pr_popResponseQueue;
1016  }
1017
1018  transition({NP_S, S_S}, CPUPrivateAck, S) {
1019    dt_deallocateTBE;
1020    w_wakeUpRegionDependents;
1021    pr_popResponseQueue;
1022  }
1023
1024  transition(S, UpgradeRequest, S_P) {TagArrayRead, TagArrayWrite} {
1025    mru_setMRU;
1026    ur_updateDirtyStatusOnRequest;
1027    f_fwdReqToDir;
1028    b_sendPrivateNotice;
1029    so_setOwner;
1030    t_allocateTBE;
1031    p_popRequestQueue;
1032  }
1033
1034  transition(S_P, CPUPrivateAck, P) {
1035    dt_deallocateTBE;
1036    w_wakeUpRegionDependents;
1037    pr_popResponseQueue;
1038  }
1039
1040  transition(P, SendInv, P_AP_W) {TagArrayRead, TagArrayWrite} {
1041    mru_setMRU;
1042    ur_updateDirtyStatusOnRequest;
1043    f_fwdReqToDirWithAck;
1044    so_setOwner;
1045    t_allocateTBE;
1046    rr_removeRequestorFromTBE;
1047    sns_setNumAcksSharers;
1048    cs_clearSharers;
1049    ss_setSharers;
1050    //i_RegionInvNotify;
1051    p_popRequestQueue;
1052  }
1053
1054  transition({P_AP_W, S_AP_W}, DirReadyAck) {
1055      ti_triggerInv;
1056      pr_popResponseQueue;
1057  }
1058
1059  transition(P_AS_W, DirReadyAck) {
1060      td_triggerDowngrade;
1061      pr_popResponseQueue;
1062  }
1063
1064  transition(P_AS_W, TriggerDowngrade, P_AS) {
1065      rd_RegionDowngrade;
1066      pt_popTriggerQueue;
1067  }
1068
1069  transition(P_AP_W, TriggerInv, P_AP) {
1070      i_RegionInvNotify;
1071      pt_popTriggerQueue;
1072  }
1073
1074  transition(S_AP_W, TriggerInv, S_AP) {
1075      i_RegionInvNotify;
1076      pt_popTriggerQueue;
1077  }
1078
1079  transition(P, SendUpgrade, P_AP_W) {TagArrayRead, TagArrayWrite} {
1080    mru_setMRU;
1081    ur_updateDirtyStatusOnRequest;
1082    f_fwdReqToDirWithAck;
1083    so_setOwner;
1084    t_allocateTBE;
1085    rr_removeRequestorFromTBE;
1086    sns_setNumAcksSharers;
1087    cs_clearSharers;
1088    ss_setSharers;
1089    p_popRequestQueue;
1090  }
1091
1092  transition(P, Evict, P_NP) {TagArrayRead, TagArrayWrite} {
1093    t_allocateTBE;
1094    sns_setNumAcksSharers;
1095    i0_RegionInvNotifyDemand0;
1096    d_deallocateRegionEntry;
1097  }
1098
1099  transition(S, SendInv, P_AP_W) {TagArrayRead, TagArrayWrite} {
1100    mru_setMRU;
1101    ur_updateDirtyStatusOnRequest;
1102    f_fwdReqToDirWithAck;
1103    so_setOwner;
1104    t_allocateTBE;
1105    rr_removeRequestorFromTBE;
1106    sns_setNumAcksSharers;
1107    cs_clearSharers;
1108    ss_setSharers;
1109    p_popRequestQueue;
1110  }
1111
1112  transition(S, Evict, P_NP) {TagArrayRead, TagArrayWrite} {
1113    t_allocateTBE;
1114    sns_setNumAcksSharers;
1115    i0_RegionInvNotifyDemand0;
1116    d_deallocateRegionEntry;
1117  }
1118
1119  transition(P_NP, LastAck, NP) {
1120    dt_deallocateTBE;
1121    wa_wakeUpAllDependents;
1122    pt_popTriggerQueue;
1123  }
1124
1125  transition(S, SendUpgrade, S_AP_W) {TagArrayRead, TagArrayWrite} {
1126    mru_setMRU;
1127    ur_updateDirtyStatusOnRequest;
1128    f_fwdReqToDirWithAck;
1129    so_setOwner;
1130    t_allocateTBE;
1131    rr_removeRequestorFromTBE;
1132    sns_setNumAcksSharers;
1133    cs_clearSharers;
1134    ss_setSharers;
1135    p_popRequestQueue;
1136  }
1137
1138  transition(S_AP, LastAck, S_P) {
1139    sp_sendPrivateNoticeToOrigReq;
1140    pt_popTriggerQueue;
1141  }
1142
1143  transition(P_AP, LastAck, P_P) {
1144    sp_sendPrivateNoticeToOrigReq;
1145    pt_popTriggerQueue;
1146  }
1147
1148  transition(P, SendDowngrade, P_AS_W) {TagArrayRead, TagArrayWrite} {
1149    mru_setMRU;
1150    ur_updateDirtyStatusOnRequest;
1151    f_fwdReqToDirWithAckShared;
1152    so_setOwner;
1153    t_allocateTBE;
1154    sns_setNumAcksSharers;
1155    ss_setSharers; //why do we set the sharers before sending the downgrade?  Are we sending a downgrade to the requestor?
1156    p_popRequestQueue;
1157  }
1158
1159  transition(P_AS, LastAck, P_S) {
1160    c_sendSharedNoticeToOrigReq;
1161    pt_popTriggerQueue;
1162  }
1163
1164  transition(P_S, CPUPrivateAck, S) {
1165    dt_deallocateTBE;
1166    w_wakeUpRegionDependents;
1167    pr_popResponseQueue;
1168  }
1169
1170  transition({P_NP, P_AS, S_AP, P_AP}, InvAckCore) {} {
1171    ra_receiveAck;
1172    pr_popResponseQueue;
1173  }
1174
1175  transition({P_NP, S_AP, P_AP}, InvAckCoreNoShare) {} {
1176    ra_receiveAck;
1177    pr_popResponseQueue;
1178  }
1179
1180  transition(P_AS, InvAckCoreNoShare) {} {
1181    ra_receiveAck;
1182    rsr_removeSharerResponse;
1183    pr_popResponseQueue;
1184  }
1185
1186}
1187
1188
1189