1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * Copyright (c) 2009 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * AMD's contributions to the MOESI hammer protocol do not constitute an 
30 * endorsement of its similarity to any AMD products.
31 *
32 * Authors: Milo Martin
33 *          Brad Beckmann
34 */
35
36machine(MachineType:Directory, "AMD Hammer-like protocol") 
37    : DirectoryMemory * directory;
38      CacheMemory * probeFilter;
39      Cycles from_memory_controller_latency := 2;
40      Cycles to_memory_controller_latency := 1;
41      bool probe_filter_enabled := "False";
42      bool full_bit_dir_enabled := "False";
43
44      MessageBuffer * forwardFromDir, network="To", virtual_network="3",
45            vnet_type="forward";
46
47      MessageBuffer * responseFromDir, network="To", virtual_network="4",
48            vnet_type="response";
49
50      // For a finite buffered network, note that the DMA response network only 
51      // works at this relatively lower numbered (lower priority) virtual network
52      // because the trigger queue decouples cache responses from DMA responses.
53      MessageBuffer * dmaResponseFromDir, network="To", virtual_network="1",
54            vnet_type="response";
55
56      MessageBuffer * unblockToDir, network="From", virtual_network="5",
57            vnet_type="unblock";
58
59      MessageBuffer * responseToDir, network="From", virtual_network="4",
60            vnet_type="response";
61
62      MessageBuffer * requestToDir, network="From", virtual_network="2",
63            vnet_type="request";
64
65      MessageBuffer * dmaRequestToDir, network="From", virtual_network="0",
66            vnet_type="request";
67
68      MessageBuffer * triggerQueue;
69      MessageBuffer * responseFromMemory;
70{
71  // STATES
72  state_declaration(State, desc="Directory states", default="Directory_State_E") {
73    // Base states
74    NX, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in O at Owner";
75    NO, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
76    S, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists pointing to the current owner";
77    O, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists";
78    E, AccessPermission:Read_Write, desc="Exclusive Owner, no probe filter entry";
79
80    O_R, AccessPermission:Read_Only, desc="Was data Owner, replacing probe filter entry";
81    S_R, AccessPermission:Read_Only, desc="Was Not Owner or Sharer, replacing probe filter entry";
82    NO_R, AccessPermission:Busy, desc="Was Not Owner or Sharer, replacing probe filter entry";
83
84    NO_B, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked";
85    NO_B_X, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
86    NO_B_S, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
87    NO_B_S_W, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
88    O_B, AccessPermission:Busy, "O^B", desc="Owner, Blocked";
89    NO_B_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
90    O_B_W, AccessPermission:Busy, desc="Owner, Blocked, waiting for Dram";
91    NO_W, AccessPermission:Busy, desc="Not Owner, waiting for Dram";
92    O_W, AccessPermission:Busy, desc="Owner, waiting for Dram";
93    NO_DW_B_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram and cache responses";
94    NO_DR_B_W, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for Dram and cache responses";
95    NO_DR_B_D, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
96    NO_DR_B, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses";
97    NO_DW_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram";
98    O_DR_B_W, AccessPermission:Busy, desc="Owner, Dma Read waiting for Dram and cache responses";
99    O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses";
100    WB, AccessPermission:Busy, desc="Blocked on a writeback";
101    WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O";
102    WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E";
103
104    NO_F,  AccessPermission:Busy, desc="Blocked on a flush";
105    NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
106  }
107
108  // Events
109  enumeration(Event, desc="Directory events") {
110    GETX,                      desc="A GETX arrives";
111    GETS,                      desc="A GETS arrives";
112    PUT,                       desc="A PUT arrives"; 
113    Unblock,                   desc="An unblock message arrives";
114    UnblockS,                   desc="An unblock message arrives";
115    UnblockM,                   desc="An unblock message arrives";
116    Writeback_Clean,           desc="The final part of a PutX (no data)";
117    Writeback_Dirty,           desc="The final part of a PutX (data)";
118    Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)";
119    Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)";
120
121    // Probe filter
122    Pf_Replacement,            desc="probe filter replacement";
123
124    // DMA requests
125    DMA_READ, desc="A DMA Read memory request";
126    DMA_WRITE, desc="A DMA Write memory request";
127
128    // Memory Controller
129    Memory_Data, desc="Fetched data from memory arrives";
130    Memory_Ack, desc="Writeback Ack from memory arrives";
131
132    // Cache responses required to handle DMA
133    Ack,             desc="Received an ack message";
134    Shared_Ack,      desc="Received an ack message, responder has a shared copy";
135    Shared_Data,     desc="Received a data message, responder has a shared copy";
136    Data,            desc="Received a data message, responder had a owner or exclusive copy, they gave it to us";
137    Exclusive_Data,  desc="Received a data message, responder had an exclusive copy, they gave it to us";
138
139    // Triggers
140    All_acks_and_shared_data,     desc="Received shared data and message acks";
141    All_acks_and_owner_data,     desc="Received shared data and message acks";
142    All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy";
143    All_Unblocks, desc="Received all unblocks for a merged gets request";
144    GETF,  desc="A GETF arrives";
145    PUTF,  desc="A PUTF arrives";
146  }
147
148  // TYPES
149
150  // DirectoryEntry
151  structure(Entry, desc="...", interface="AbstractEntry") {
152    State DirectoryState,          desc="Directory state";
153  }
154
155  // ProbeFilterEntry
156  structure(PfEntry, desc="...", interface="AbstractCacheEntry") {
157    State PfState,                 desc="Directory state";
158    MachineID Owner,               desc="Owner node";
159    Set Sharers,                   desc="sharing vector for full bit directory";
160  }
161
162  // TBE entries for DMA requests
163  structure(TBE, desc="TBE entries for outstanding DMA requests") {
164    Addr PhysicalAddress, desc="physical address";
165    State TBEState,        desc="Transient State";
166    CoherenceResponseType ResponseType, desc="The type for the subsequent response message";
167    int Acks, default="0", desc="The number of acks that the waiting response represents";
168    int SilentAcks, default="0", desc="The number of silent acks associated with this transaction";
169    DataBlock DmaDataBlk,  desc="DMA Data to be written.  Partial blocks need to merged with system memory";
170    DataBlock DataBlk,     desc="The current view of system memory";
171    int Len,               desc="...";
172    MachineID DmaRequestor, desc="DMA requestor";
173    NetDest GetSRequestors, desc="GETS merged requestors";
174    int NumPendingMsgs,    desc="Number of pending acks/messages";
175    bool CacheDirty, default="false", desc="Indicates whether a cache has responded with dirty data";
176    bool Sharers, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
177    bool Owned, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
178  }
179
180  structure(TBETable, external="yes") {
181    TBE lookup(Addr);
182    void allocate(Addr);
183    void deallocate(Addr);
184    bool isPresent(Addr);
185  }
186
187  Tick clockEdge();
188  void set_cache_entry(AbstractCacheEntry b);
189  void unset_cache_entry();
190  void set_tbe(TBE a);
191  void unset_tbe();
192  void wakeUpBuffers(Addr a);
193  Cycles curCycle();
194
195  // ** OBJECTS **
196
197  Set fwd_set;
198
199  TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
200
201  Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
202    Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
203
204    if (is_valid(dir_entry)) {
205      return dir_entry;
206    }
207
208    dir_entry :=  static_cast(Entry, "pointer",
209                              directory.allocate(addr, new Entry));
210    return dir_entry;
211  }
212
213  PfEntry getProbeFilterEntry(Addr addr), return_by_pointer="yes" {
214    if (probe_filter_enabled || full_bit_dir_enabled) {
215      PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr));
216      return pfEntry;
217    }
218    return OOD;
219  }
220
221  State getState(TBE tbe, PfEntry pf_entry, Addr addr) {
222    if (is_valid(tbe)) {
223      return tbe.TBEState;
224    } else {
225      if (probe_filter_enabled || full_bit_dir_enabled) {
226        if (is_valid(pf_entry)) {
227          assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState);
228        }
229      }
230      return getDirectoryEntry(addr).DirectoryState;
231    }
232  }
233
234  void setState(TBE tbe, PfEntry pf_entry, Addr addr, State state) {
235    if (is_valid(tbe)) {
236      tbe.TBEState := state;
237    }
238    if (probe_filter_enabled || full_bit_dir_enabled) {
239      if (is_valid(pf_entry)) {
240        pf_entry.PfState := state;
241      }
242      if (state == State:NX || state == State:NO || state == State:S || state == State:O) {
243        assert(is_valid(pf_entry));
244      }
245      if (state == State:E) {
246        assert(is_valid(pf_entry) == false);
247      }
248    }
249    if (state == State:E || state == State:NX || state == State:NO || state == State:S || 
250        state == State:O) {
251      assert(is_valid(tbe) == false);
252    }
253    getDirectoryEntry(addr).DirectoryState := state;
254  }
255
256  AccessPermission getAccessPermission(Addr addr) {
257    TBE tbe := TBEs[addr];
258    if(is_valid(tbe)) {
259      return Directory_State_to_permission(tbe.TBEState);
260    }
261
262    if(directory.isPresent(addr)) {
263      return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
264    }
265
266    return AccessPermission:NotPresent;
267  }
268
269  void setAccessPermission(PfEntry pf_entry, Addr addr, State state) {
270    getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
271  }
272
273  void functionalRead(Addr addr, Packet *pkt) {
274    TBE tbe := TBEs[addr];
275    if(is_valid(tbe)) {
276      testAndRead(addr, tbe.DataBlk, pkt);
277    } else {
278      functionalMemoryRead(pkt);
279    }
280  }
281
282  int functionalWrite(Addr addr, Packet *pkt) {
283    int num_functional_writes := 0;
284
285    TBE tbe := TBEs[addr];
286    if(is_valid(tbe)) {
287      num_functional_writes := num_functional_writes +
288        testAndWrite(addr, tbe.DataBlk, pkt);
289    }
290
291    num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt);
292    return num_functional_writes;
293  }
294
295  Event cache_request_to_event(CoherenceRequestType type) {
296    if (type == CoherenceRequestType:GETS) {
297      return Event:GETS;
298    } else if (type == CoherenceRequestType:GETX) {
299      return Event:GETX;
300    } else if (type == CoherenceRequestType:GETF) {
301      return Event:GETF;
302    } else {
303      error("Invalid CoherenceRequestType");
304    }
305  }
306
307  // ** OUT_PORTS **
308  out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
309  out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
310  out_port(responseNetwork_out, ResponseMsg, responseFromDir);
311  out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir);
312  out_port(triggerQueue_out, TriggerMsg, triggerQueue);
313  
314  // ** IN_PORTS **
315  
316  // Trigger Queue
317  in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
318    if (triggerQueue_in.isReady(clockEdge())) {
319      peek(triggerQueue_in, TriggerMsg) {
320        PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
321        TBE tbe := TBEs[in_msg.addr];
322        if (in_msg.Type == TriggerType:ALL_ACKS) {
323          trigger(Event:All_acks_and_owner_data, in_msg.addr,
324                  pf_entry, tbe);
325        } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) {
326          trigger(Event:All_acks_and_shared_data, in_msg.addr,
327                  pf_entry, tbe);
328        } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) {
329          trigger(Event:All_acks_and_data_no_sharers, in_msg.addr,
330                  pf_entry, tbe);
331        } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) {
332          trigger(Event:All_Unblocks, in_msg.addr,
333                  pf_entry, tbe);
334        } else {
335          error("Unexpected message");
336        }
337      }
338    }
339  }
340
341  in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) {
342    if (unblockNetwork_in.isReady(clockEdge())) {
343      peek(unblockNetwork_in, ResponseMsg) {
344        PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
345        TBE tbe := TBEs[in_msg.addr];
346        if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
347          trigger(Event:Unblock, in_msg.addr, pf_entry, tbe);
348        } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
349          trigger(Event:UnblockS, in_msg.addr, pf_entry, tbe);
350        } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) {
351          trigger(Event:UnblockM, in_msg.addr, pf_entry, tbe);
352        } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) {
353          trigger(Event:Writeback_Clean, in_msg.addr, pf_entry, tbe);
354        } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) {
355          trigger(Event:Writeback_Dirty, in_msg.addr, pf_entry, tbe);
356        } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) {
357          trigger(Event:Writeback_Exclusive_Clean, in_msg.addr,
358                  pf_entry, tbe);
359        } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
360          trigger(Event:Writeback_Exclusive_Dirty, in_msg.addr,
361                  pf_entry, tbe);
362        } else {
363          error("Invalid message");
364        }
365      }
366    }
367  }
368
369  // Response Network
370  in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) {
371    if (responseToDir_in.isReady(clockEdge())) {
372      peek(responseToDir_in, ResponseMsg) {
373        PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
374        TBE tbe := TBEs[in_msg.addr];
375        if (in_msg.Type == CoherenceResponseType:ACK) {
376          trigger(Event:Ack, in_msg.addr, pf_entry, tbe);
377        } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
378          trigger(Event:Shared_Ack, in_msg.addr, pf_entry, tbe);
379        } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
380          trigger(Event:Shared_Data, in_msg.addr, pf_entry, tbe);
381        } else if (in_msg.Type == CoherenceResponseType:DATA) {
382          trigger(Event:Data, in_msg.addr, pf_entry, tbe);
383        } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
384          trigger(Event:Exclusive_Data, in_msg.addr, pf_entry, tbe);
385        } else {
386          error("Unexpected message");
387        }
388      }
389    }
390  }
391
392  // off-chip memory request/response is done
393  in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=2) {
394    if (memQueue_in.isReady(clockEdge())) {
395      peek(memQueue_in, MemoryMsg) {
396        PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
397        TBE tbe := TBEs[in_msg.addr];
398        if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
399          trigger(Event:Memory_Data, in_msg.addr, pf_entry, tbe);
400        } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
401          trigger(Event:Memory_Ack, in_msg.addr, pf_entry, tbe);
402        } else {
403          DPRINTF(RubySlicc, "%d\n", in_msg.Type);
404          error("Invalid message");
405        }
406      }
407    }
408  }
409
410  in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) {
411    if (requestQueue_in.isReady(clockEdge())) {
412      peek(requestQueue_in, RequestMsg) {
413        PfEntry pf_entry := getProbeFilterEntry(in_msg.addr);
414        TBE tbe := TBEs[in_msg.addr];
415        if (in_msg.Type == CoherenceRequestType:PUT) {
416          trigger(Event:PUT, in_msg.addr, pf_entry, tbe);
417        } else if (in_msg.Type == CoherenceRequestType:PUTF) {
418          trigger(Event:PUTF, in_msg.addr, pf_entry, tbe);
419        } else {
420          if (probe_filter_enabled || full_bit_dir_enabled) {
421            if (is_valid(pf_entry)) {
422              trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
423                      pf_entry, tbe);
424            } else {
425              if (probeFilter.cacheAvail(in_msg.addr)) {
426                trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
427                        pf_entry, tbe);
428              } else {
429                trigger(Event:Pf_Replacement,
430                Addr victim := probeFilter.cacheProbe(in_msg.addr);
431                trigger(Event:Pf_Replacement,
432                        victim, getProbeFilterEntry(victim), TBEs[victim]);
433              }
434            }
435          } else {
436            trigger(cache_request_to_event(in_msg.Type), in_msg.addr,
437                    pf_entry, tbe);
438          }
439        }
440      }
441    }
442  }
443
444  in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) {
445    if (dmaRequestQueue_in.isReady(clockEdge())) {
446      peek(dmaRequestQueue_in, DMARequestMsg) {
447        PfEntry pf_entry := getProbeFilterEntry(in_msg.LineAddress);
448        TBE tbe := TBEs[in_msg.LineAddress];
449        if (in_msg.Type == DMARequestType:READ) {
450          trigger(Event:DMA_READ, in_msg.LineAddress, pf_entry, tbe);
451        } else if (in_msg.Type == DMARequestType:WRITE) {
452          trigger(Event:DMA_WRITE, in_msg.LineAddress, pf_entry, tbe);
453        } else {
454          error("Invalid message");
455        }
456      }
457    }
458  }
459
460  // Actions
461  
462  action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) {
463    if (probe_filter_enabled || full_bit_dir_enabled) {
464      assert(is_valid(cache_entry)); 
465      probeFilter.setMRU(address);
466    }
467  }
468
469  action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") {
470    if (probe_filter_enabled || full_bit_dir_enabled) {
471      assert(is_valid(cache_entry)); 
472      peek(unblockNetwork_in, ResponseMsg) {
473        assert(cache_entry.Owner != in_msg.Sender);
474        if (full_bit_dir_enabled) {
475          assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)) == false);
476        }
477      }
478    }
479  }
480
481  action(uo_updateOwnerIfPf, "uo", desc="update owner") {
482    if (probe_filter_enabled || full_bit_dir_enabled) {
483      assert(is_valid(cache_entry)); 
484      peek(unblockNetwork_in, ResponseMsg) {
485        cache_entry.Owner := in_msg.Sender;
486        if (full_bit_dir_enabled) {
487          cache_entry.Sharers.clear();
488          cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
489          APPEND_TRANSITION_COMMENT(cache_entry.Sharers);
490          DPRINTF(RubySlicc, "Sharers = %d\n", cache_entry.Sharers);
491        }
492      }
493    }
494  }
495
496  action(us_updateSharerIfFBD, "us", desc="update sharer if full-bit directory") {
497   if (full_bit_dir_enabled) {
498      assert(probeFilter.isTagPresent(address));
499      peek(unblockNetwork_in, ResponseMsg) {
500        cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender));
501      }
502    }
503  }
504
505  action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
506    peek(requestQueue_in, RequestMsg) {
507      enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
508        out_msg.addr := address;
509        out_msg.Type := CoherenceRequestType:WB_ACK;
510        out_msg.Requestor := in_msg.Requestor;
511        out_msg.Destination.add(in_msg.Requestor);
512        out_msg.MessageSize := MessageSizeType:Writeback_Control;
513      }
514    }
515  }
516
517  action(oc_sendBlockAck, "oc", desc="Send block ack to the owner") {
518    peek(requestQueue_in, RequestMsg) {
519        if (((probe_filter_enabled || full_bit_dir_enabled) && (in_msg.Requestor == cache_entry.Owner)) || machineCount(MachineType:L1Cache) == 1) {
520        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
521          out_msg.addr := address;
522          out_msg.Type := CoherenceRequestType:BLOCK_ACK;
523          out_msg.Requestor := in_msg.Requestor;
524          out_msg.Destination.add(in_msg.Requestor);
525          out_msg.MessageSize := MessageSizeType:Writeback_Control;
526        }
527      }
528    }
529  }
530
531  action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
532    peek(requestQueue_in, RequestMsg) {
533      enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
534        out_msg.addr := address;
535        out_msg.Type := CoherenceRequestType:WB_NACK;
536        out_msg.Requestor := in_msg.Requestor;
537        out_msg.Destination.add(in_msg.Requestor);
538        out_msg.MessageSize := MessageSizeType:Writeback_Control;
539      }
540    }
541  }
542
543  action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") {
544    if (probe_filter_enabled || full_bit_dir_enabled) {
545      peek(requestQueue_in, RequestMsg) {
546        set_cache_entry(probeFilter.allocate(address, new PfEntry));
547        cache_entry.Owner := in_msg.Requestor;
548        cache_entry.Sharers.setSize(machineCount(MachineType:L1Cache));
549      }
550    }
551  }
552
553  action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") {
554    if (probe_filter_enabled || full_bit_dir_enabled) {
555      probeFilter.deallocate(address);
556      unset_cache_entry();
557    }
558  }
559
560  action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") {
561    if ((probe_filter_enabled || full_bit_dir_enabled) && is_valid(cache_entry)) {
562      probeFilter.deallocate(address);
563      unset_cache_entry();
564    }
565  }
566
567  action(v_allocateTBE, "v", desc="Allocate TBE") {
568    check_allocate(TBEs);
569    peek(requestQueue_in, RequestMsg) {
570      TBEs.allocate(address);
571      set_tbe(TBEs[address]);
572      tbe.PhysicalAddress := address;
573      tbe.ResponseType := CoherenceResponseType:NULL;
574    }
575  }
576
577  action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") {
578    check_allocate(TBEs);
579    peek(dmaRequestQueue_in, DMARequestMsg) {
580      TBEs.allocate(address);
581      set_tbe(TBEs[address]);
582      tbe.DmaDataBlk := in_msg.DataBlk;
583      tbe.PhysicalAddress := in_msg.PhysicalAddress;
584      tbe.Len := in_msg.Len;
585      tbe.DmaRequestor := in_msg.Requestor;
586      tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
587      //
588      // One ack for each last-level cache
589      //
590      tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
591      //
592      // Assume initially that the caches store a clean copy and that memory
593      // will provide the data
594      //
595      tbe.CacheDirty := false;
596    }
597  }
598
599  action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") {
600    assert(is_valid(tbe));
601    if (full_bit_dir_enabled) {
602      assert(is_valid(cache_entry));
603      tbe.NumPendingMsgs := cache_entry.Sharers.count();
604    } else {
605      tbe.NumPendingMsgs := machineCount(MachineType:L1Cache);
606    }
607  }
608
609  action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") {
610    assert(is_valid(tbe));
611    tbe.NumPendingMsgs := 1;
612  }
613
614  action(w_deallocateTBE, "w", desc="Deallocate TBE") {
615    TBEs.deallocate(address);
616    unset_tbe();
617  }
618
619  action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") {
620    assert(is_valid(tbe));
621    peek(requestQueue_in, RequestMsg) {
622      if (full_bit_dir_enabled) {
623        assert(is_valid(cache_entry));
624        //
625        // If we are using the full-bit directory and no sharers exists beyond
626        // the requestor, then we must set the ack number to all, not one
627        //
628        fwd_set := cache_entry.Sharers;
629        fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
630        if (fwd_set.count() > 0) {
631          tbe.Acks := 1;
632          tbe.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
633          tbe.SilentAcks := tbe.SilentAcks - 1;
634        } else {
635          tbe.Acks := machineCount(MachineType:L1Cache);
636          tbe.SilentAcks := 0;
637        }
638      } else {
639        tbe.Acks := 1;
640      }
641    }
642  } 
643
644  action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") {
645    assert(is_valid(tbe));
646    if (probe_filter_enabled || full_bit_dir_enabled) {
647      tbe.Acks := machineCount(MachineType:L1Cache);
648      tbe.SilentAcks := 0;
649    } else {
650      tbe.Acks := 1;
651    }
652  }   
653
654  action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") {
655    peek(responseToDir_in, ResponseMsg) {
656      assert(is_valid(tbe));
657      assert(in_msg.Acks > 0);
658      DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
659      //
660      // Note that cache data responses will have an ack count of 2.  However, 
661      // directory DMA requests must wait for acks from all LLC caches, so 
662      // only decrement by 1.
663      //
664      if ((in_msg.Type == CoherenceResponseType:DATA_SHARED) ||
665          (in_msg.Type == CoherenceResponseType:DATA) ||
666          (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE)) {
667        tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
668      } else {
669        tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks;
670      }
671      DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
672    }
673  }
674
675  action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") {
676    peek(unblockNetwork_in, ResponseMsg) {
677      assert(is_valid(tbe));
678      assert(in_msg.Type == CoherenceResponseType:UNBLOCKS);
679      DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
680      tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1;
681      DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs);
682    }
683  }
684
685  action(n_popResponseQueue, "n", desc="Pop response queue") {
686    responseToDir_in.dequeue(clockEdge());
687  }
688
689  action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
690    assert(is_valid(tbe));
691    if (tbe.NumPendingMsgs == 0) {
692      enqueue(triggerQueue_out, TriggerMsg) {
693        out_msg.addr := address;
694        if (tbe.Sharers) {
695          if (tbe.Owned) {
696            out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS;
697          } else {
698            out_msg.Type := TriggerType:ALL_ACKS;
699          }
700        } else {
701          out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
702        }
703      }
704    }
705  }
706
707  action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") {
708    assert(is_valid(tbe));
709    if (tbe.NumPendingMsgs == 0) {
710      enqueue(triggerQueue_out, TriggerMsg) {
711        out_msg.addr := address;
712        out_msg.Type := TriggerType:ALL_UNBLOCKS;
713      }
714    }
715  }
716
717  action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") {
718    assert(is_valid(tbe));
719    tbe.NumPendingMsgs := tbe.GetSRequestors.count();
720  }
721
722  action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") {
723    if (probe_filter_enabled || full_bit_dir_enabled) {
724      assert(is_valid(tbe));
725      tbe.NumPendingMsgs := 0;
726    }
727  }
728
729  action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") {
730    assert(is_valid(tbe));
731    if (tbe.NumPendingMsgs == 0) {
732      assert(probe_filter_enabled || full_bit_dir_enabled);
733      enqueue(triggerQueue_out, TriggerMsg) {
734        out_msg.addr := address;
735        out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
736      }
737    }
738  }
739
740  action(d_sendData, "d", desc="Send data to requestor") {
741    peek(memQueue_in, MemoryMsg) {
742      enqueue(responseNetwork_out, ResponseMsg, 1) {
743        assert(is_valid(tbe));
744        out_msg.addr := address;
745        out_msg.Type := tbe.ResponseType;
746        out_msg.Sender := machineID;
747        out_msg.Destination.add(in_msg.OriginalRequestorMachId);
748        out_msg.DataBlk := in_msg.DataBlk;
749        DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk);
750        out_msg.Dirty := false; // By definition, the block is now clean
751        out_msg.Acks := tbe.Acks;
752        out_msg.SilentAcks := tbe.SilentAcks;
753        DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
754        assert(out_msg.Acks > 0);
755        out_msg.MessageSize := MessageSizeType:Response_Data;
756      }
757    }
758  }
759
760  action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") {
761    peek(memQueue_in, MemoryMsg) {
762      enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
763        assert(is_valid(tbe));
764        out_msg.PhysicalAddress := address;
765        out_msg.LineAddress := address;
766        out_msg.Type := DMAResponseType:DATA;
767        //
768        // we send the entire data block and rely on the dma controller to 
769        // split it up if need be
770        //
771        out_msg.DataBlk := in_msg.DataBlk;
772        out_msg.Destination.add(tbe.DmaRequestor);
773        out_msg.MessageSize := MessageSizeType:Response_Data;
774      }
775    }
776  }
777
778  action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") {
779    peek(triggerQueue_in, TriggerMsg) {
780      enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
781        assert(is_valid(tbe));
782        out_msg.PhysicalAddress := address;
783        out_msg.LineAddress := address;
784        out_msg.Type := DMAResponseType:DATA;
785        //
786        // we send the entire data block and rely on the dma controller to 
787        // split it up if need be
788        //
789        out_msg.DataBlk := tbe.DataBlk;
790        out_msg.Destination.add(tbe.DmaRequestor);
791        out_msg.MessageSize := MessageSizeType:Response_Data;
792      }
793    }
794  }
795
796  action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") {
797    enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) {
798      assert(is_valid(tbe));
799      out_msg.PhysicalAddress := address;
800      out_msg.LineAddress := address;
801      out_msg.Type := DMAResponseType:ACK;
802      out_msg.Destination.add(tbe.DmaRequestor); 
803      out_msg.MessageSize := MessageSizeType:Writeback_Control;
804    }
805  }
806
807  action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") {
808    peek(requestQueue_in, RequestMsg) {
809      assert(is_valid(tbe));
810      tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
811    }
812  }
813
814  action(r_recordDataInTBE, "rt", desc="Record Data in TBE") {
815    peek(requestQueue_in, RequestMsg) {
816      assert(is_valid(tbe));
817      if (full_bit_dir_enabled) {
818        fwd_set := cache_entry.Sharers;
819        fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
820        if (fwd_set.count() > 0) {
821          tbe.ResponseType := CoherenceResponseType:DATA;
822        } else {
823          tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
824        }
825      } else {
826        tbe.ResponseType := CoherenceResponseType:DATA;
827      }
828    }
829  }
830
831  action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") {
832    peek(requestQueue_in, RequestMsg) {
833      assert(is_valid(tbe));
834      tbe.GetSRequestors.add(in_msg.Requestor);
835    }
836  }
837
838  action(r_setSharerBit, "r", desc="We saw other sharers") {
839    assert(is_valid(tbe));
840    tbe.Sharers := true;
841  }
842
843  action(so_setOwnerBit, "so", desc="We saw other sharers") {
844    assert(is_valid(tbe));
845    tbe.Sharers := true;
846    tbe.Owned := true;
847  }
848
849  action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
850    peek(requestQueue_in, RequestMsg) {
851      queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
852    }
853  }
854
855  action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") {
856    peek(dmaRequestQueue_in, DMARequestMsg) {
857      queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency);
858    }
859  }
860
861  action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") {
862    assert(is_valid(tbe));
863    if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) {
864      if (full_bit_dir_enabled) {
865        assert(is_valid(cache_entry));
866        peek(requestQueue_in, RequestMsg) {
867          fwd_set := cache_entry.Sharers;
868          fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
869          if (fwd_set.count() > 0) {
870            enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
871              out_msg.addr := address;
872              out_msg.Type := in_msg.Type;
873              out_msg.Requestor := in_msg.Requestor;
874              out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
875              out_msg.MessageSize := MessageSizeType:Multicast_Control;
876              out_msg.InitialRequestTime := in_msg.InitialRequestTime;
877              out_msg.ForwardRequestTime := curCycle();
878              assert(tbe.SilentAcks > 0);
879              out_msg.SilentAcks := tbe.SilentAcks;
880            }
881          }
882        }
883      } else {
884        peek(requestQueue_in, RequestMsg) {
885          enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
886            out_msg.addr := address;
887            out_msg.Type := in_msg.Type;
888            out_msg.Requestor := in_msg.Requestor;
889            out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
890            out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
891            out_msg.MessageSize := MessageSizeType:Broadcast_Control;
892            out_msg.InitialRequestTime := in_msg.InitialRequestTime;
893            out_msg.ForwardRequestTime := curCycle();
894          }
895        }
896      }
897    }
898  }
899
900  action(ia_invalidateAllRequest, "ia", desc="invalidate all copies") {
901    if (machineCount(MachineType:L1Cache) > 1) {
902      if (full_bit_dir_enabled) {
903        assert(cache_entry.Sharers.count() > 0);
904        peek(requestQueue_in, RequestMsg) {
905          enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
906            out_msg.addr := address;
907            out_msg.Type := CoherenceRequestType:INV;
908            out_msg.Requestor := machineID;
909            out_msg.Destination.setNetDest(MachineType:L1Cache, cache_entry.Sharers);
910            out_msg.MessageSize := MessageSizeType:Multicast_Control;
911          }
912        }
913      } else {
914        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
915          out_msg.addr := address;
916          out_msg.Type := CoherenceRequestType:INV;
917          out_msg.Requestor := machineID;
918          out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
919          out_msg.MessageSize := MessageSizeType:Broadcast_Control;
920        }
921      }
922    }
923  }
924
925  action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") {
926    if (machineCount(MachineType:L1Cache) > 1) {
927      enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
928        assert(is_valid(cache_entry)); 
929        out_msg.addr := address;
930        out_msg.Type := CoherenceRequestType:INV;
931        out_msg.Requestor := machineID;
932        out_msg.Destination.add(cache_entry.Owner);
933        out_msg.MessageSize := MessageSizeType:Request_Control;
934        out_msg.DirectedProbe := true;
935      }
936    }
937  }
938
939  action(fb_forwardRequestBcast, "fb", desc="Forward requests to all nodes") {
940    if (machineCount(MachineType:L1Cache) > 1) {
941      peek(requestQueue_in, RequestMsg) {
942        if (full_bit_dir_enabled) {
943          fwd_set := cache_entry.Sharers;
944          fwd_set.remove(machineIDToNodeID(in_msg.Requestor));
945          if (fwd_set.count() > 0) {
946            enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
947                  out_msg.addr := address;
948                  out_msg.Type := in_msg.Type;
949                  out_msg.Requestor := in_msg.Requestor;
950                  out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set);
951                  out_msg.MessageSize := MessageSizeType:Multicast_Control;
952                  out_msg.InitialRequestTime := in_msg.InitialRequestTime;
953                  out_msg.ForwardRequestTime := curCycle();
954                  out_msg.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count();
955                  out_msg.SilentAcks := out_msg.SilentAcks - 1;
956              }
957          }
958        } else {
959            enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
960                out_msg.addr := address;
961                out_msg.Type := in_msg.Type;
962                out_msg.Requestor := in_msg.Requestor;
963                out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
964                out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
965                out_msg.MessageSize := MessageSizeType:Broadcast_Control;
966                out_msg.InitialRequestTime := in_msg.InitialRequestTime;
967                out_msg.ForwardRequestTime := curCycle();
968            }
969        }
970      }
971    } else {
972      peek(requestQueue_in, RequestMsg) {
973          enqueue(responseNetwork_out, ResponseMsg, 1) {
974            out_msg.addr := address;
975            out_msg.Type := CoherenceResponseType:ACK;
976            out_msg.Sender := machineID;
977            out_msg.Destination.add(in_msg.Requestor);
978            out_msg.Dirty := false; // By definition, the block is now clean
979            out_msg.Acks := 0;
980            out_msg.SilentAcks := 0;
981            DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
982            out_msg.MessageSize := MessageSizeType:Response_Control;
983          }
984      }
985    }
986  }
987
988  action(fr_forwardMergeReadRequestsToOwner, "frr", desc="Forward coalesced read request to owner") {
989    assert(machineCount(MachineType:L1Cache) > 1);
990    //
991    // Fixme! The unblock network should not stall on the forward network.  Add a trigger queue to
992    // decouple the two.
993    //
994    peek(unblockNetwork_in, ResponseMsg) {
995      enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
996        assert(is_valid(tbe));
997        out_msg.addr := address;
998        out_msg.Type := CoherenceRequestType:MERGED_GETS;
999        out_msg.MergedRequestors := tbe.GetSRequestors;
1000        if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
1001          out_msg.Destination.add(in_msg.CurOwner);
1002        } else {
1003          out_msg.Destination.add(in_msg.Sender);
1004        }
1005        out_msg.MessageSize := MessageSizeType:Request_Control;
1006        out_msg.InitialRequestTime := zero_time();
1007        out_msg.ForwardRequestTime := curCycle();
1008      }      
1009    }
1010  }
1011
1012  action(fc_forwardRequestConditionalOwner, "fc", desc="Forward request to one or more nodes") {
1013    assert(machineCount(MachineType:L1Cache) > 1);
1014    if (probe_filter_enabled || full_bit_dir_enabled) {
1015      peek(requestQueue_in, RequestMsg) {
1016        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1017          assert(is_valid(cache_entry)); 
1018          out_msg.addr := address;
1019          out_msg.Type := in_msg.Type;
1020          out_msg.Requestor := in_msg.Requestor;
1021          out_msg.Destination.add(cache_entry.Owner);
1022          out_msg.MessageSize := MessageSizeType:Request_Control;
1023          out_msg.DirectedProbe := true;
1024          out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1025          out_msg.ForwardRequestTime := curCycle();
1026        }
1027      }      
1028    } else {
1029      peek(requestQueue_in, RequestMsg) {
1030        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1031          out_msg.addr := address;
1032          out_msg.Type := in_msg.Type;
1033          out_msg.Requestor := in_msg.Requestor;
1034          out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1035          out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1036          out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1037          out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1038          out_msg.ForwardRequestTime := curCycle();
1039        }
1040      }
1041    }
1042  }
1043
1044  action(nofc_forwardRequestConditionalOwner, "nofc", desc="Forward request to one or more nodes if the requestor is not the owner") {
1045   if (machineCount(MachineType:L1Cache) > 1) {
1046
1047     if (probe_filter_enabled || full_bit_dir_enabled) {
1048       peek(requestQueue_in, RequestMsg) {
1049        if (in_msg.Requestor != cache_entry.Owner) {
1050          enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1051            assert(is_valid(cache_entry));
1052            out_msg.addr := address;
1053            out_msg.Type := in_msg.Type;
1054            out_msg.Requestor := in_msg.Requestor;
1055            out_msg.Destination.add(cache_entry.Owner);
1056            out_msg.MessageSize := MessageSizeType:Request_Control;
1057            out_msg.DirectedProbe := true;
1058            out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1059            out_msg.ForwardRequestTime := curCycle();
1060          }
1061        }
1062       }
1063     } else {
1064      peek(requestQueue_in, RequestMsg) {
1065        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1066          out_msg.addr := address;
1067          out_msg.Type := in_msg.Type;
1068          out_msg.Requestor := in_msg.Requestor;
1069          out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
1070          out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
1071          out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1072          out_msg.InitialRequestTime := in_msg.InitialRequestTime;
1073          out_msg.ForwardRequestTime := curCycle();
1074        }
1075      }
1076     }
1077   }
1078  }
1079
1080  action(f_forwardWriteFromDma, "fw", desc="Forward requests") {
1081    assert(is_valid(tbe));
1082    if (tbe.NumPendingMsgs > 0) {
1083      peek(dmaRequestQueue_in, DMARequestMsg) {
1084        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1085          out_msg.addr := address;
1086          out_msg.Type := CoherenceRequestType:GETX;
1087          //
1088          // Send to all L1 caches, since the requestor is the memory controller
1089          // itself
1090          //
1091          out_msg.Requestor := machineID;
1092          out_msg.Destination.broadcast(MachineType:L1Cache); 
1093          out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1094        }
1095      }
1096    }
1097  }
1098
1099  action(f_forwardReadFromDma, "fr", desc="Forward requests") {
1100    assert(is_valid(tbe));
1101    if (tbe.NumPendingMsgs > 0) {
1102      peek(dmaRequestQueue_in, DMARequestMsg) {
1103        enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) {
1104          out_msg.addr := address;
1105          out_msg.Type := CoherenceRequestType:GETS;
1106          //
1107          // Send to all L1 caches, since the requestor is the memory controller
1108          // itself
1109          //
1110          out_msg.Requestor := machineID;
1111          out_msg.Destination.broadcast(MachineType:L1Cache); 
1112          out_msg.MessageSize := MessageSizeType:Broadcast_Control;
1113        }
1114      }
1115    }
1116  }
1117
1118  action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
1119    requestQueue_in.dequeue(clockEdge());
1120  }
1121
1122  action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
1123    peek(unblockNetwork_in, ResponseMsg) {
1124        APPEND_TRANSITION_COMMENT(in_msg.Sender);
1125    } 
1126    unblockNetwork_in.dequeue(clockEdge());
1127  }
1128
1129  action(k_wakeUpDependents, "k", desc="wake-up dependents") {
1130    wakeUpBuffers(address);
1131  }
1132
1133  action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
1134    memQueue_in.dequeue(clockEdge());
1135  }
1136
1137  action(g_popTriggerQueue, "g", desc="Pop trigger queue") {
1138    triggerQueue_in.dequeue(clockEdge());
1139  }
1140
1141  action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") {
1142    dmaRequestQueue_in.dequeue(clockEdge());
1143  }
1144
1145  action(zd_stallAndWaitDMARequest, "zd", desc="Stall and wait the dma request queue") {
1146    peek(dmaRequestQueue_in, DMARequestMsg) {
1147        APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1148    } 
1149    stall_and_wait(dmaRequestQueue_in, address);
1150  }
1151
1152  action(r_recordMemoryData, "rd", desc="record data from memory to TBE") {
1153    peek(memQueue_in, MemoryMsg) {
1154      assert(is_valid(tbe));
1155      if (tbe.CacheDirty == false) {
1156        tbe.DataBlk := in_msg.DataBlk;
1157      }
1158    }
1159  }
1160
1161  action(r_recordCacheData, "rc", desc="record data from cache response to TBE") {
1162    peek(responseToDir_in, ResponseMsg) {
1163      assert(is_valid(tbe));
1164      tbe.CacheDirty := true;
1165      tbe.DataBlk := in_msg.DataBlk;
1166    }
1167  }
1168
1169  action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") {
1170    assert(is_valid(tbe));
1171    assert(tbe.CacheDirty);
1172  }
1173
1174  action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") {
1175    if (probe_filter_enabled || full_bit_dir_enabled) {
1176      peek(requestQueue_in, RequestMsg) {
1177        assert(is_valid(cache_entry)); 
1178        assert(cache_entry.Owner != in_msg.Requestor);
1179      }
1180    }
1181  }
1182
1183  action(ans_assertNotSharer, "ans", desc="Assert that request is not a current sharer") {
1184    if (full_bit_dir_enabled) {
1185      peek(requestQueue_in, RequestMsg) {
1186        assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Requestor)) == false);
1187      }
1188    }
1189  }
1190
1191  action(rs_removeSharer, "s", desc="remove current sharer") {
1192    if (full_bit_dir_enabled) {
1193      peek(unblockNetwork_in, ResponseMsg) {
1194        assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)));
1195        cache_entry.Sharers.remove(machineIDToNodeID(in_msg.Sender));
1196      }
1197    }
1198  }
1199
1200  action(cs_clearSharers, "cs", desc="clear current sharers") {
1201    if (full_bit_dir_enabled) {
1202      peek(requestQueue_in, RequestMsg) {
1203        cache_entry.Sharers.clear();
1204        cache_entry.Sharers.add(machineIDToNodeID(in_msg.Requestor));
1205      }
1206    }
1207  }
1208
1209  action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
1210    peek(unblockNetwork_in, ResponseMsg) {
1211      queueMemoryWrite(in_msg.Sender, address, to_memory_controller_latency,
1212                       in_msg.DataBlk);
1213    }
1214  }
1215
1216  action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") {
1217    assert(is_valid(tbe));
1218    queueMemoryWritePartial(tbe.DmaRequestor, tbe.PhysicalAddress,
1219                            to_memory_controller_latency, tbe.DmaDataBlk,
1220                            tbe.Len);
1221  }
1222
1223  action(ly_queueMemoryWriteFromTBE, "ly", desc="Write data to memory from TBE") {
1224    queueMemoryWrite(machineID, address, to_memory_controller_latency,
1225                     tbe.DataBlk);
1226  }
1227
1228  action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
1229    peek(unblockNetwork_in, ResponseMsg) {
1230      assert(in_msg.Dirty == false);
1231      assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
1232      DPRINTF(RubySlicc, "%s\n", in_msg.DataBlk);
1233    }
1234  }
1235
1236  action(z_stallAndWaitRequest, "z", desc="Recycle the request queue") {
1237    peek(requestQueue_in, RequestMsg) {
1238        APPEND_TRANSITION_COMMENT(in_msg.Requestor);
1239    } 
1240    stall_and_wait(requestQueue_in, address);
1241  }
1242
1243  // TRANSITIONS
1244
1245  // Transitions out of E state
1246  transition(E, GETX, NO_B_W) {
1247    pfa_probeFilterAllocate;
1248    v_allocateTBE;
1249    rx_recordExclusiveInTBE;
1250    saa_setAcksToAllIfPF;
1251    qf_queueMemoryFetchRequest;
1252    fn_forwardRequestIfNecessary;
1253    i_popIncomingRequestQueue;
1254  }
1255
1256  transition(E, GETF, NO_F_W) {
1257    pfa_probeFilterAllocate;
1258    v_allocateTBE;
1259    rx_recordExclusiveInTBE;
1260    saa_setAcksToAllIfPF;
1261    qf_queueMemoryFetchRequest;
1262    fn_forwardRequestIfNecessary;
1263    i_popIncomingRequestQueue;
1264  }
1265
1266  transition(E, GETS, NO_B_W) {
1267    pfa_probeFilterAllocate;
1268    v_allocateTBE;
1269    rx_recordExclusiveInTBE;
1270    saa_setAcksToAllIfPF;
1271    qf_queueMemoryFetchRequest;
1272    fn_forwardRequestIfNecessary;
1273    i_popIncomingRequestQueue;
1274  }
1275
1276  transition(E, DMA_READ, NO_DR_B_W) {
1277    vd_allocateDmaRequestInTBE;
1278    qd_queueMemoryRequestFromDmaRead;
1279    spa_setPendingAcksToZeroIfPF;
1280    f_forwardReadFromDma;
1281    p_popDmaRequestQueue;
1282  }
1283
1284  transition(E, DMA_WRITE, NO_DW_B_W) {
1285    vd_allocateDmaRequestInTBE;
1286    spa_setPendingAcksToZeroIfPF;
1287    sc_signalCompletionIfPF;
1288    f_forwardWriteFromDma;
1289    p_popDmaRequestQueue;
1290  }
1291
1292  // Transitions out of O state
1293  transition(O, GETX, NO_B_W) {
1294    r_setMRU;
1295    v_allocateTBE;
1296    r_recordDataInTBE;
1297    sa_setAcksToOne;
1298    qf_queueMemoryFetchRequest;
1299    fb_forwardRequestBcast;
1300    cs_clearSharers;
1301    i_popIncomingRequestQueue;
1302  }
1303
1304  transition(O, GETF, NO_F_W) {
1305    r_setMRU;
1306    v_allocateTBE;
1307    r_recordDataInTBE;
1308    sa_setAcksToOne;
1309    qf_queueMemoryFetchRequest;
1310    fb_forwardRequestBcast;
1311    cs_clearSharers;
1312    i_popIncomingRequestQueue;
1313  }
1314
1315  // This transition is dumb, if a shared copy exists on-chip, then that should
1316  // provide data, not slow off-chip dram.  The problem is that the current
1317  // caches don't provide data in S state
1318  transition(O, GETS, O_B_W) {
1319    r_setMRU;
1320    v_allocateTBE;
1321    r_recordDataInTBE;
1322    saa_setAcksToAllIfPF;
1323    qf_queueMemoryFetchRequest;
1324    fn_forwardRequestIfNecessary;
1325    i_popIncomingRequestQueue;
1326  }
1327
1328  transition(O, DMA_READ, O_DR_B_W) {
1329    vd_allocateDmaRequestInTBE;
1330    spa_setPendingAcksToZeroIfPF;
1331    qd_queueMemoryRequestFromDmaRead;
1332    f_forwardReadFromDma;
1333    p_popDmaRequestQueue;
1334  }
1335
1336  transition(O, Pf_Replacement, O_R) {
1337    v_allocateTBE;
1338    pa_setPendingMsgsToAll;
1339    ia_invalidateAllRequest;
1340    pfd_probeFilterDeallocate;
1341  }
1342
1343  transition(S, Pf_Replacement, S_R) {
1344    v_allocateTBE;
1345    pa_setPendingMsgsToAll;
1346    ia_invalidateAllRequest;
1347    pfd_probeFilterDeallocate;
1348  }
1349
1350  transition(NO, Pf_Replacement, NO_R) {
1351    v_allocateTBE;
1352    po_setPendingMsgsToOne;
1353    io_invalidateOwnerRequest;
1354    pfd_probeFilterDeallocate;
1355  }
1356
1357  transition(NX, Pf_Replacement, NO_R) {
1358    v_allocateTBE;
1359    pa_setPendingMsgsToAll;
1360    ia_invalidateAllRequest;
1361    pfd_probeFilterDeallocate;
1362  }
1363
1364  transition({O, S, NO, NX}, DMA_WRITE, NO_DW_B_W) {
1365    vd_allocateDmaRequestInTBE;
1366    f_forwardWriteFromDma;
1367    p_popDmaRequestQueue;
1368  }
1369
1370  // Transitions out of NO state
1371  transition(NX, GETX, NO_B) {
1372    r_setMRU;
1373    fb_forwardRequestBcast;
1374    cs_clearSharers;
1375    i_popIncomingRequestQueue;
1376  }
1377
1378  transition(NX, GETF, NO_F) {
1379    r_setMRU;
1380    fb_forwardRequestBcast;
1381    cs_clearSharers;
1382    i_popIncomingRequestQueue;
1383  }
1384
1385  // Transitions out of NO state
1386  transition(NO, GETX, NO_B) {
1387    r_setMRU;
1388    ano_assertNotOwner;
1389    fc_forwardRequestConditionalOwner;
1390    cs_clearSharers;
1391    i_popIncomingRequestQueue;
1392  }
1393
1394  transition(NO, GETF, NO_F) {
1395    r_setMRU;
1396    //ano_assertNotOwner;
1397    nofc_forwardRequestConditionalOwner; //forward request if the requester is not the owner
1398    cs_clearSharers;
1399    oc_sendBlockAck; // send ack if the owner
1400    i_popIncomingRequestQueue;
1401  }
1402
1403  transition(S, GETX, NO_B) {
1404    r_setMRU;
1405    fb_forwardRequestBcast;
1406    cs_clearSharers;
1407    i_popIncomingRequestQueue;
1408  }
1409
1410  transition(S, GETF, NO_F) {
1411    r_setMRU;
1412    fb_forwardRequestBcast;
1413    cs_clearSharers;
1414    i_popIncomingRequestQueue;
1415  }
1416
1417  transition(S, GETS, NO_B) {
1418    r_setMRU;
1419    ano_assertNotOwner;
1420    fb_forwardRequestBcast;
1421    i_popIncomingRequestQueue;
1422  }
1423
1424  transition(NO, GETS, NO_B) {
1425    r_setMRU;
1426    ano_assertNotOwner;
1427    ans_assertNotSharer;
1428    fc_forwardRequestConditionalOwner;
1429    i_popIncomingRequestQueue;
1430  }
1431
1432  transition(NX, GETS, NO_B) {
1433    r_setMRU;
1434    ano_assertNotOwner;
1435    fc_forwardRequestConditionalOwner;
1436    i_popIncomingRequestQueue;
1437  }
1438
1439  transition({NO, NX, S}, PUT, WB) {
1440    //
1441    // note that the PUT requestor may not be the current owner if an invalidate
1442    // raced with PUT
1443    //    
1444    a_sendWriteBackAck;
1445    i_popIncomingRequestQueue;
1446  }
1447
1448  transition({NO, NX, S}, DMA_READ, NO_DR_B_D) {
1449    vd_allocateDmaRequestInTBE;
1450    f_forwardReadFromDma;
1451    p_popDmaRequestQueue;
1452  }
1453
1454  // Nack PUT requests when races cause us to believe we own the data
1455  transition({O, E}, PUT) {
1456    b_sendWriteBackNack;
1457    i_popIncomingRequestQueue;
1458  }
1459
1460  // Blocked transient states
1461  transition({NO_B_X, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, 
1462              NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1463              NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W}, 
1464             {GETS, GETX, GETF, PUT, Pf_Replacement}) {
1465    z_stallAndWaitRequest;
1466  }
1467
1468  transition(NO_F, {GETS, GETX, GETF, PUT, Pf_Replacement}){
1469    z_stallAndWaitRequest;
1470  }
1471
1472  transition(NO_B, {GETX, GETF}, NO_B_X) {
1473    z_stallAndWaitRequest;
1474  }
1475
1476  transition(NO_B, {PUT, Pf_Replacement}) {
1477    z_stallAndWaitRequest;
1478  }
1479
1480  transition(NO_B_S, {GETX, GETF, PUT, Pf_Replacement}) {
1481    z_stallAndWaitRequest;
1482  }
1483
1484  transition({NO_B_X, NO_B, NO_B_S, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, 
1485              NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1486              NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W}, 
1487             {DMA_READ, DMA_WRITE}) {
1488    zd_stallAndWaitDMARequest;
1489  }
1490
1491  // merge GETS into one response
1492  transition(NO_B, GETS, NO_B_S) {
1493    v_allocateTBE;
1494    rs_recordGetSRequestor;
1495    i_popIncomingRequestQueue;
1496  }
1497
1498  transition(NO_B_S, GETS) {
1499    rs_recordGetSRequestor;
1500    i_popIncomingRequestQueue;
1501  }
1502
1503  // unblock responses
1504  transition({NO_B, NO_B_X}, UnblockS, NX) {
1505    us_updateSharerIfFBD;
1506    k_wakeUpDependents;
1507    j_popIncomingUnblockQueue;
1508  }
1509
1510  transition({NO_B, NO_B_X}, UnblockM, NO) {
1511    uo_updateOwnerIfPf;
1512    us_updateSharerIfFBD;
1513    k_wakeUpDependents;
1514    j_popIncomingUnblockQueue;
1515  }
1516
1517  transition(NO_B_S, UnblockS, NO_B_S_W) {
1518    us_updateSharerIfFBD;
1519    fr_forwardMergeReadRequestsToOwner;
1520    sp_setPendingMsgsToMergedSharers;
1521    j_popIncomingUnblockQueue;
1522  }
1523
1524  transition(NO_B_S, UnblockM, NO_B_S_W) {
1525    uo_updateOwnerIfPf;
1526    fr_forwardMergeReadRequestsToOwner;
1527    sp_setPendingMsgsToMergedSharers;
1528    j_popIncomingUnblockQueue;
1529  }
1530
1531  transition(NO_B_S_W, UnblockS) {
1532    us_updateSharerIfFBD;
1533    mu_decrementNumberOfUnblocks;
1534    os_checkForMergedGetSCompletion;
1535    j_popIncomingUnblockQueue;
1536  }
1537
1538  transition(NO_B_S_W, All_Unblocks, NX) {
1539    w_deallocateTBE;
1540    k_wakeUpDependents;
1541    g_popTriggerQueue;
1542  }
1543
1544  transition(O_B, UnblockS, O) {
1545    us_updateSharerIfFBD;
1546    k_wakeUpDependents;
1547    j_popIncomingUnblockQueue;
1548  }
1549
1550  transition(O_B, UnblockM, NO) {
1551    us_updateSharerIfFBD;
1552    uo_updateOwnerIfPf;
1553    k_wakeUpDependents;
1554    j_popIncomingUnblockQueue;
1555  }
1556
1557  transition(NO_B_W, Memory_Data, NO_B) {
1558    d_sendData;
1559    w_deallocateTBE;
1560    l_popMemQueue;
1561  }
1562
1563  transition(NO_F_W, Memory_Data, NO_F) {
1564    d_sendData;
1565    w_deallocateTBE;
1566    l_popMemQueue;
1567  }
1568
1569  transition(NO_DR_B_W, Memory_Data, NO_DR_B) {
1570    r_recordMemoryData;
1571    o_checkForCompletion;
1572    l_popMemQueue;
1573  }
1574
1575  transition(O_DR_B_W, Memory_Data, O_DR_B) {
1576    r_recordMemoryData;
1577    dr_sendDmaData;
1578    o_checkForCompletion;
1579    l_popMemQueue;
1580  }
1581
1582  transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) {
1583    m_decrementNumberOfMessages;
1584    o_checkForCompletion;
1585    n_popResponseQueue;
1586  }
1587
1588  transition({O_R, S_R, NO_R}, Ack) {
1589    m_decrementNumberOfMessages;
1590    o_checkForCompletion;
1591    n_popResponseQueue;
1592  }
1593
1594  transition(S_R, Data) {
1595    m_decrementNumberOfMessages;
1596    o_checkForCompletion;
1597    n_popResponseQueue;
1598  }
1599
1600  transition(NO_R, {Data, Exclusive_Data}) {
1601    r_recordCacheData;
1602    m_decrementNumberOfMessages;
1603    o_checkForCompletion;
1604    n_popResponseQueue;
1605  }
1606
1607  transition({O_R, S_R}, All_acks_and_data_no_sharers, E) {
1608    w_deallocateTBE;
1609    k_wakeUpDependents;
1610    g_popTriggerQueue;
1611  }
1612
1613  transition(NO_R, All_acks_and_data_no_sharers, WB_E_W) {
1614    ly_queueMemoryWriteFromTBE;
1615    w_deallocateTBE;
1616    k_wakeUpDependents;
1617    g_popTriggerQueue;
1618  }
1619
1620  transition({NO_DR_B_W, O_DR_B_W}, Ack) {
1621    m_decrementNumberOfMessages;
1622    n_popResponseQueue;
1623  }
1624
1625  transition(NO_DR_B_W, Shared_Ack) {
1626    m_decrementNumberOfMessages;
1627    r_setSharerBit;
1628    n_popResponseQueue;
1629  }
1630
1631  transition(O_DR_B, Shared_Ack) {
1632    m_decrementNumberOfMessages;
1633    r_setSharerBit;
1634    o_checkForCompletion;
1635    n_popResponseQueue;
1636  }
1637
1638  transition(O_DR_B_W, Shared_Ack) {
1639    m_decrementNumberOfMessages;
1640    r_setSharerBit;
1641    n_popResponseQueue;
1642  }
1643
1644  transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) {
1645    m_decrementNumberOfMessages;
1646    r_setSharerBit;
1647    o_checkForCompletion;
1648    n_popResponseQueue;
1649  }
1650
1651  transition(NO_DR_B_W, Shared_Data) {
1652    r_recordCacheData;
1653    m_decrementNumberOfMessages;
1654    so_setOwnerBit;
1655    o_checkForCompletion;
1656    n_popResponseQueue;
1657  }
1658
1659  transition({NO_DR_B, NO_DR_B_D}, Shared_Data) {
1660    r_recordCacheData;
1661    m_decrementNumberOfMessages;
1662    so_setOwnerBit;
1663    o_checkForCompletion;
1664    n_popResponseQueue;
1665  }
1666
1667  transition(NO_DR_B_W, {Exclusive_Data, Data}) {
1668    r_recordCacheData;
1669    m_decrementNumberOfMessages;
1670    n_popResponseQueue;
1671  }
1672
1673  transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, {Exclusive_Data, Data}) {
1674    r_recordCacheData;
1675    m_decrementNumberOfMessages;
1676    o_checkForCompletion;
1677    n_popResponseQueue;
1678  }
1679
1680  transition(NO_DR_B, All_acks_and_owner_data, WB_O_W) {
1681    //
1682    // Note that the DMA consistency model allows us to send the DMA device
1683    // a response as soon as we receive valid data and prior to receiving
1684    // all acks.  However, to simplify the protocol we wait for all acks.
1685    //
1686    dt_sendDmaDataFromTbe;
1687    ly_queueMemoryWriteFromTBE;
1688    w_deallocateTBE;
1689    k_wakeUpDependents;
1690    g_popTriggerQueue;
1691  }
1692
1693  transition(NO_DR_B, All_acks_and_shared_data, S) {
1694    //
1695    // Note that the DMA consistency model allows us to send the DMA device
1696    // a response as soon as we receive valid data and prior to receiving
1697    // all acks.  However, to simplify the protocol we wait for all acks.
1698    //
1699    dt_sendDmaDataFromTbe;
1700    w_deallocateTBE;
1701    k_wakeUpDependents;
1702    g_popTriggerQueue;
1703  }
1704
1705  transition(NO_DR_B_D, All_acks_and_owner_data, WB_O_W) {
1706    //
1707    // Note that the DMA consistency model allows us to send the DMA device
1708    // a response as soon as we receive valid data and prior to receiving
1709    // all acks.  However, to simplify the protocol we wait for all acks.
1710    //
1711    dt_sendDmaDataFromTbe;
1712    ly_queueMemoryWriteFromTBE;
1713    w_deallocateTBE;
1714    k_wakeUpDependents;
1715    g_popTriggerQueue;
1716  }
1717
1718  transition(NO_DR_B_D, All_acks_and_shared_data, S) {
1719    //
1720    // Note that the DMA consistency model allows us to send the DMA device
1721    // a response as soon as we receive valid data and prior to receiving
1722    // all acks.  However, to simplify the protocol we wait for all acks.
1723    //
1724    dt_sendDmaDataFromTbe;
1725    w_deallocateTBE;
1726    k_wakeUpDependents;
1727    g_popTriggerQueue;
1728  }
1729
1730  transition(O_DR_B, All_acks_and_owner_data, WB_O_W) {
1731    ly_queueMemoryWriteFromTBE;
1732    w_deallocateTBE;
1733    k_wakeUpDependents;
1734    g_popTriggerQueue;
1735  }
1736
1737  transition(O_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1738    ly_queueMemoryWriteFromTBE;
1739    w_deallocateTBE;
1740    pfd_probeFilterDeallocate;
1741    k_wakeUpDependents;
1742    g_popTriggerQueue;
1743  }
1744
1745  transition(NO_DR_B, All_acks_and_data_no_sharers, WB_E_W) {
1746    //
1747    // Note that the DMA consistency model allows us to send the DMA device
1748    // a response as soon as we receive valid data and prior to receiving
1749    // all acks.  However, to simplify the protocol we wait for all acks.
1750    //
1751    dt_sendDmaDataFromTbe;
1752    ly_queueMemoryWriteFromTBE;
1753    w_deallocateTBE;
1754    ppfd_possibleProbeFilterDeallocate;
1755    k_wakeUpDependents;
1756    g_popTriggerQueue;
1757  }
1758
1759  transition(NO_DR_B_D, All_acks_and_data_no_sharers, WB_E_W) {
1760    a_assertCacheData;
1761    //
1762    // Note that the DMA consistency model allows us to send the DMA device
1763    // a response as soon as we receive valid data and prior to receiving
1764    // all acks.  However, to simplify the protocol we wait for all acks.
1765    //
1766    dt_sendDmaDataFromTbe;
1767    ly_queueMemoryWriteFromTBE;
1768    w_deallocateTBE;
1769    ppfd_possibleProbeFilterDeallocate;
1770    k_wakeUpDependents;
1771    g_popTriggerQueue;
1772  }
1773
1774  transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) {
1775    ld_queueMemoryDmaWrite;
1776    g_popTriggerQueue;
1777  }
1778
1779  transition(NO_DW_W, Memory_Ack, E) {
1780    da_sendDmaAck;
1781    w_deallocateTBE;
1782    ppfd_possibleProbeFilterDeallocate;
1783    k_wakeUpDependents;
1784    l_popMemQueue;
1785  }
1786
1787  transition(O_B_W, Memory_Data, O_B) {
1788    d_sendData;
1789    w_deallocateTBE;
1790    l_popMemQueue;
1791  }
1792
1793  transition(NO_B_W, UnblockM, NO_W) {
1794    uo_updateOwnerIfPf;
1795    j_popIncomingUnblockQueue;
1796  }
1797
1798  transition(NO_B_W, UnblockS, NO_W) {
1799    us_updateSharerIfFBD;
1800    j_popIncomingUnblockQueue;
1801  }
1802
1803  transition(O_B_W, UnblockS, O_W) {
1804    us_updateSharerIfFBD;
1805    j_popIncomingUnblockQueue;
1806  }
1807
1808  transition(NO_W, Memory_Data, NO) {
1809    w_deallocateTBE;
1810    k_wakeUpDependents;
1811    l_popMemQueue;
1812  }
1813
1814  transition(O_W, Memory_Data, O) {
1815    w_deallocateTBE;
1816    k_wakeUpDependents;
1817    l_popMemQueue;
1818  }
1819
1820  // WB State Transistions
1821  transition(WB, Writeback_Dirty, WB_O_W) {
1822    rs_removeSharer;
1823    l_queueMemoryWBRequest;
1824    j_popIncomingUnblockQueue;
1825  }
1826
1827  transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
1828    rs_removeSharer;
1829    l_queueMemoryWBRequest;
1830    pfd_probeFilterDeallocate;
1831    j_popIncomingUnblockQueue;
1832  }
1833
1834  transition(WB_E_W, Memory_Ack, E) {
1835    k_wakeUpDependents;
1836    l_popMemQueue;
1837  }
1838
1839  transition(WB_O_W, Memory_Ack, O) {
1840    k_wakeUpDependents;
1841    l_popMemQueue;
1842  }
1843
1844  transition(WB, Writeback_Clean, O) {
1845    ll_checkIncomingWriteback;
1846    rs_removeSharer;
1847    k_wakeUpDependents;
1848    j_popIncomingUnblockQueue;
1849  }
1850
1851  transition(WB, Writeback_Exclusive_Clean, E) {
1852    ll_checkIncomingWriteback;
1853    rs_removeSharer;
1854    pfd_probeFilterDeallocate;
1855    k_wakeUpDependents;
1856    j_popIncomingUnblockQueue;
1857  }
1858
1859  transition(WB, Unblock, NX) {
1860    auno_assertUnblockerNotOwner;
1861    k_wakeUpDependents;
1862    j_popIncomingUnblockQueue;
1863  }
1864
1865  transition(NO_F, PUTF, WB) {
1866    a_sendWriteBackAck;
1867    i_popIncomingRequestQueue;
1868  }
1869
1870  //possible race between GETF and UnblockM -- not sure needed any more?
1871  transition(NO_F, UnblockM) {
1872    us_updateSharerIfFBD;
1873    uo_updateOwnerIfPf;
1874    j_popIncomingUnblockQueue;
1875  }
1876}
1877