1/*
2 * Copyright (c) 2010-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: Lisa Hsu
34 */
35
36machine(MachineType:L3Cache, "L3")
37 : CacheMemory * L3cache;
38   WireBuffer * reqToDir;
39   WireBuffer * respToDir;
40   WireBuffer * l3UnblockToDir;
41   WireBuffer * reqToL3;
42   WireBuffer * probeToL3;
43   WireBuffer * respToL3;
44   Cycles l3_request_latency := 1;
45   Cycles l3_response_latency := 35;
46
47  // To the general response network
48  MessageBuffer * responseFromL3, network="To", virtual_network="2", ordered="false", vnet_type="response";
49
50  // From the general response network
51  MessageBuffer * responseToL3, network="From", virtual_network="2", ordered="false", vnet_type="response";
52
53{
54  // EVENTS
55  enumeration(Event, desc="L3 Events") {
56    // Requests coming from the Cores
57    RdBlk,                  desc="CPU RdBlk event";
58    RdBlkM,                 desc="CPU RdBlkM event";
59    RdBlkS,                 desc="CPU RdBlkS event";
60    CtoD,                   desc="Change to Dirty request";
61    WrVicBlk,               desc="L2 Victim (dirty)";
62    WrVicBlkShared,               desc="L2 Victim (dirty)";
63    ClVicBlk,               desc="L2 Victim (clean)";
64    ClVicBlkShared,               desc="L2 Victim (clean)";
65
66    CPUData,                      desc="WB data from CPU";
67    CPUDataShared,                desc="WB data from CPU, NBReqShared 1";
68    StaleWB,                desc="WB stale; no data";
69
70    L3_Repl,             desc="L3 Replacement";
71
72    // Probes
73    PrbInvData,         desc="Invalidating probe, return dirty data";
74    PrbInv,             desc="Invalidating probe, no need to return data";
75    PrbShrData,         desc="Downgrading probe, return data";
76
77    // Coming from Memory Controller
78    WBAck,                     desc="ack from memory";
79
80    CancelWB,                   desc="Cancel WB from L2";
81  }
82
83  // STATES
84  // Base States:
85  state_declaration(State, desc="L3 State", default="L3Cache_State_I") {
86    M, AccessPermission:Read_Write, desc="Modified";  // No other cache has copy, memory stale
87    O, AccessPermission:Read_Only, desc="Owned";     // Correct most recent copy, others may exist in S
88    E, AccessPermission:Read_Write, desc="Exclusive"; // Correct, most recent, and only copy (and == Memory)
89    S, AccessPermission:Read_Only, desc="Shared";    // Correct, most recent. If no one in O, then == Memory
90    I, AccessPermission:Invalid, desc="Invalid";
91
92    I_M, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data";
93    I_O, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data";
94    I_E, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data";
95    I_S, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data";
96    S_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to M";
97    S_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O";
98    S_E, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to E";
99    S_S, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to S";
100    E_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O";
101    E_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O";
102    E_E, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O";
103    E_S, AccessPermission:Busy, desc="Shared, received WrVicBlk, sent Ack, waiting for Data";
104    O_M, AccessPermission:Busy, desc="...";
105    O_O, AccessPermission:Busy, desc="...";
106    O_E, AccessPermission:Busy, desc="...";
107    O_S, AccessPermission:Busy, desc="...";
108    M_M, AccessPermission:Busy, desc="...";
109    M_O, AccessPermission:Busy, desc="...";
110    M_E, AccessPermission:Busy, desc="...";
111    M_S, AccessPermission:Busy, desc="...";
112    D_I, AccessPermission:Invalid,  desc="drop WB data on the floor when receive";
113    MOD_I, AccessPermission:Busy, desc="drop WB data on the floor, waiting for WBAck from Mem";
114    MO_I, AccessPermission:Busy, desc="M or O, received L3_Repl, waiting for WBAck from Mem";
115    I_I, AccessPermission:Busy, desc="I_MO received L3_Repl";
116    I_CD, AccessPermission:Busy, desc="I_I received WBAck, now just waiting for CPUData";
117    I_C, AccessPermission:Invalid, desc="sent cancel, just waiting to receive mem wb ack so nothing gets confused";
118  }
119
120  enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
121    DataArrayRead,    desc="Read the data array";
122    DataArrayWrite,   desc="Write the data array";
123    TagArrayRead,     desc="Read the data array";
124    TagArrayWrite,    desc="Write the data array";
125  }
126
127  // STRUCTURES
128
129  structure(Entry, desc="...", interface="AbstractCacheEntry") {
130    State CacheState,           desc="cache state";
131    bool Dirty,                 desc="Is the data dirty (diff from memory?)";
132    DataBlock DataBlk,          desc="Data for the block";
133  }
134
135  structure(TBE, desc="...") {
136    State TBEState,     desc="Transient state";
137    DataBlock DataBlk,  desc="data for the block";
138    bool Dirty,         desc="Is the data dirty?";
139    bool Shared,        desc="Victim hit by shared probe";
140    MachineID From,     desc="Waiting for writeback from...";
141  }
142
143  structure(TBETable, external="yes") {
144    TBE lookup(Addr);
145    void allocate(Addr);
146    void deallocate(Addr);
147    bool isPresent(Addr);
148  }
149
150  TBETable TBEs, template="<L3Cache_TBE>", constructor="m_number_of_TBEs";
151
152  void set_cache_entry(AbstractCacheEntry b);
153  void unset_cache_entry();
154  void set_tbe(TBE b);
155  void unset_tbe();
156  void wakeUpAllBuffers();
157  void wakeUpBuffers(Addr a);
158  MachineID mapAddressToMachine(Addr addr, MachineType mtype);
159
160  // FUNCTION DEFINITIONS
161  Tick clockEdge();
162  Tick cyclesToTicks(Cycles c);
163
164  Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
165    return static_cast(Entry, "pointer", L3cache.lookup(addr));
166  }
167
168  DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
169    return getCacheEntry(addr).DataBlk;
170  }
171
172  bool presentOrAvail(Addr addr) {
173    return L3cache.isTagPresent(addr) || L3cache.cacheAvail(addr);
174  }
175
176  State getState(TBE tbe, Entry cache_entry, Addr addr) {
177    if (is_valid(tbe)) {
178      return tbe.TBEState;
179    } else if (is_valid(cache_entry)) {
180      return cache_entry.CacheState;
181    }
182    return State:I;
183  }
184
185  void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
186    if (is_valid(tbe)) {
187        tbe.TBEState := state;
188    }
189
190    if (is_valid(cache_entry)) {
191        cache_entry.CacheState := state;
192    }
193  }
194
195  void functionalRead(Addr addr, Packet *pkt) {
196    TBE tbe := TBEs.lookup(addr);
197    if(is_valid(tbe)) {
198      testAndRead(addr, tbe.DataBlk, pkt);
199    } else {
200      functionalMemoryRead(pkt);
201    }
202  }
203
204  int functionalWrite(Addr addr, Packet *pkt) {
205    int num_functional_writes := 0;
206
207    TBE tbe := TBEs.lookup(addr);
208    if(is_valid(tbe)) {
209      num_functional_writes := num_functional_writes +
210            testAndWrite(addr, tbe.DataBlk, pkt);
211    }
212
213    num_functional_writes := num_functional_writes +
214        functionalMemoryWrite(pkt);
215    return num_functional_writes;
216  }
217
218  AccessPermission getAccessPermission(Addr addr) {
219    TBE tbe := TBEs.lookup(addr);
220    if(is_valid(tbe)) {
221      return L3Cache_State_to_permission(tbe.TBEState);
222    }
223
224    Entry cache_entry := getCacheEntry(addr);
225    if(is_valid(cache_entry)) {
226      return L3Cache_State_to_permission(cache_entry.CacheState);
227    }
228
229    return AccessPermission:NotPresent;
230  }
231
232  void setAccessPermission(Entry cache_entry, Addr addr, State state) {
233    if (is_valid(cache_entry)) {
234      cache_entry.changePermission(L3Cache_State_to_permission(state));
235    }
236  }
237
238  void recordRequestType(RequestType request_type, Addr addr) {
239
240  }
241
242  bool checkResourceAvailable(RequestType request_type, Addr addr) {
243    return true;
244  }
245
246
247  // OUT PORTS
248  out_port(requestNetwork_out, CPURequestMsg, reqToDir);
249  out_port(L3Resp_out, ResponseMsg, respToDir);
250  out_port(responseNetwork_out, ResponseMsg, responseFromL3);
251  out_port(unblockNetwork_out, UnblockMsg, l3UnblockToDir);
252
253  // IN PORTS
254  in_port(NBResponse_in, ResponseMsg, respToL3) {
255    if (NBResponse_in.isReady(clockEdge())) {
256      peek(NBResponse_in, ResponseMsg) {
257        Entry cache_entry := getCacheEntry(in_msg.addr);
258        TBE tbe := TBEs.lookup(in_msg.addr);
259        if (in_msg.Type == CoherenceResponseType:NBSysWBAck) {
260          trigger(Event:WBAck, in_msg.addr, cache_entry, tbe);
261        } else {
262          DPRINTF(RubySlicc, "%s\n", in_msg);
263          error("Error on NBResponse Type");
264        }
265      }
266    }
267  }
268
269  // Response Network
270  in_port(responseNetwork_in, ResponseMsg, responseToL3) {
271    if (responseNetwork_in.isReady(clockEdge())) {
272      peek(responseNetwork_in, ResponseMsg) {
273        Entry cache_entry := getCacheEntry(in_msg.addr);
274        TBE tbe := TBEs.lookup(in_msg.addr);
275        if (in_msg.Type == CoherenceResponseType:CPUData) {
276          if (in_msg.NbReqShared) {
277            trigger(Event:CPUDataShared, in_msg.addr, cache_entry, tbe);
278          } else {
279            trigger(Event:CPUData, in_msg.addr, cache_entry, tbe);
280          }
281        } else if (in_msg.Type == CoherenceResponseType:StaleNotif) {
282            trigger(Event:StaleWB, in_msg.addr, cache_entry, tbe);
283        } else {
284          DPRINTF(RubySlicc, "%s\n", in_msg);
285          error("Error on NBResponse Type");
286        }
287      }
288    }
289  }
290
291  // probe network
292  in_port(probeNetwork_in, NBProbeRequestMsg, probeToL3) {
293    if (probeNetwork_in.isReady(clockEdge())) {
294      peek(probeNetwork_in, NBProbeRequestMsg) {
295        Entry cache_entry := getCacheEntry(in_msg.addr);
296        TBE tbe := TBEs.lookup(in_msg.addr);
297        if (in_msg.Type == ProbeRequestType:PrbInv) {
298          if (in_msg.ReturnData) {
299            trigger(Event:PrbInvData, in_msg.addr, cache_entry, tbe);
300          } else {
301            trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe);
302          }
303        } else if (in_msg.Type == ProbeRequestType:PrbDowngrade) {
304          if (in_msg.ReturnData) {
305            trigger(Event:PrbShrData, in_msg.addr, cache_entry, tbe);
306          } else {
307            error("Don't think I should get any of these");
308          }
309        }
310      }
311    }
312  }
313
314  // Request Network
315  in_port(requestNetwork_in, CPURequestMsg, reqToL3) {
316    if (requestNetwork_in.isReady(clockEdge())) {
317      peek(requestNetwork_in, CPURequestMsg) {
318        assert(in_msg.Destination.isElement(machineID));
319        Entry cache_entry := getCacheEntry(in_msg.addr);
320        TBE tbe := TBEs.lookup(in_msg.addr);
321        if (in_msg.Type == CoherenceRequestType:RdBlk) {
322          trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe);
323        } else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
324          trigger(Event:RdBlkS, in_msg.addr, cache_entry, tbe);
325        } else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
326          trigger(Event:RdBlkM, in_msg.addr, cache_entry, tbe);
327        } else if (in_msg.Type == CoherenceRequestType:VicClean) {
328          if (presentOrAvail(in_msg.addr)) {
329            if (in_msg.Shared) {
330              trigger(Event:ClVicBlkShared, in_msg.addr, cache_entry, tbe);
331            } else {
332              trigger(Event:ClVicBlk, in_msg.addr, cache_entry, tbe);
333            }
334          } else {
335            Addr victim :=  L3cache.cacheProbe(in_msg.addr);
336            trigger(Event:L3_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
337          }
338        } else if (in_msg.Type == CoherenceRequestType:VicDirty) {
339          if (presentOrAvail(in_msg.addr)) {
340            if (in_msg.Shared) {
341              trigger(Event:WrVicBlkShared, in_msg.addr, cache_entry, tbe);
342            } else {
343              trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe);
344            }
345          } else {
346            Addr victim := L3cache.cacheProbe(in_msg.addr);
347            trigger(Event:L3_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim));
348          }
349        } else if (in_msg.Type == CoherenceRequestType:WrCancel) {
350          if (is_valid(tbe) && tbe.From == in_msg.Requestor) {
351            trigger(Event:CancelWB, in_msg.addr, cache_entry, tbe);
352          } else {
353            requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
354          }
355        }
356      }
357    }
358  }
359
360  // BEGIN ACTIONS
361
362  action(i_invL3, "i", desc="invalidate L3 cache block") {
363    if (is_valid(cache_entry)) {
364        L3cache.deallocate(address);
365    }
366    unset_cache_entry();
367  }
368
369  action(rm_sendResponseM, "rm", desc="send Modified response") {
370    peek(requestNetwork_in, CPURequestMsg) {
371      enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) {
372        out_msg.addr := address;
373        out_msg.Type := CoherenceResponseType:NBSysResp;
374        out_msg.Sender := machineID;
375        out_msg.Destination.add(in_msg.Requestor);
376        out_msg.DataBlk := cache_entry.DataBlk;
377        out_msg.MessageSize := MessageSizeType:Response_Data;
378        out_msg.Dirty := cache_entry.Dirty;
379        out_msg.State := CoherenceState:Modified;
380        DPRINTF(RubySlicc, "%s\n", out_msg);
381      }
382    }
383  }
384
385  action(rs_sendResponseS, "rs", desc="send Shared response") {
386    peek(requestNetwork_in, CPURequestMsg) {
387      enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) {
388        out_msg.addr := address;
389        out_msg.Type := CoherenceResponseType:NBSysResp;
390        out_msg.Sender := machineID;
391        out_msg.Destination.add(in_msg.Requestor);
392        out_msg.DataBlk := cache_entry.DataBlk;
393        out_msg.MessageSize := MessageSizeType:Response_Data;
394        out_msg.Dirty := cache_entry.Dirty;
395        out_msg.State := CoherenceState:Shared;
396        DPRINTF(RubySlicc, "%s\n", out_msg);
397      }
398    }
399  }
400
401
402  action(r_requestToMem, "r", desc="Miss in L3, pass on") {
403    peek(requestNetwork_in, CPURequestMsg) {
404      enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) {
405        out_msg.addr := address;
406        out_msg.Type := in_msg.Type;
407        out_msg.Requestor := in_msg.Requestor;
408        out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
409        out_msg.Shared := false; // unneeded for this request
410        out_msg.MessageSize := in_msg.MessageSize;
411        DPRINTF(RubySlicc, "%s\n", out_msg);
412      }
413    }
414  }
415
416  action(t_allocateTBE, "t", desc="allocate TBE Entry") {
417    TBEs.allocate(address);
418    set_tbe(TBEs.lookup(address));
419    if (is_valid(cache_entry)) {
420      tbe.DataBlk := cache_entry.DataBlk; // Data only for WBs
421      tbe.Dirty := cache_entry.Dirty;
422    }
423    tbe.From := machineID;
424  }
425
426  action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
427    TBEs.deallocate(address);
428    unset_tbe();
429  }
430
431  action(vd_vicDirty, "vd", desc="Victimize dirty L3 data") {
432    enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) {
433      out_msg.addr := address;
434      out_msg.Type := CoherenceRequestType:VicDirty;
435      out_msg.Requestor := machineID;
436      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
437      out_msg.MessageSize := MessageSizeType:Request_Control;
438    }
439  }
440
441  action(w_sendResponseWBAck, "w", desc="send WB Ack") {
442    peek(requestNetwork_in, CPURequestMsg) {
443      enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) {
444        out_msg.addr := address;
445        out_msg.Type := CoherenceResponseType:NBSysWBAck;
446        out_msg.Destination.add(in_msg.Requestor);
447        out_msg.Sender := machineID;
448        out_msg.MessageSize := MessageSizeType:Writeback_Control;
449      }
450    }
451  }
452
453  action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") {
454    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
455      out_msg.addr := address;
456      out_msg.Type := CoherenceResponseType:CPUPrbResp;  // L3 and CPUs respond in same way to probes
457      out_msg.Sender := machineID;
458      // will this always be ok? probably not for multisocket
459      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
460      out_msg.Dirty := false;
461      out_msg.Hit := false;
462      out_msg.Ntsl := true;
463      out_msg.State := CoherenceState:NA;
464      out_msg.MessageSize := MessageSizeType:Response_Control;
465    }
466  }
467
468  action(ph_sendProbeResponseHit, "ph", desc="send probe ack, no data") {
469    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
470      out_msg.addr := address;
471      out_msg.Type := CoherenceResponseType:CPUPrbResp;  // L3 and CPUs respond in same way to probes
472      out_msg.Sender := machineID;
473      // will this always be ok? probably not for multisocket
474      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
475      out_msg.Dirty := false;
476      out_msg.Hit := true;
477      out_msg.Ntsl := false;
478      out_msg.State := CoherenceState:NA;
479      out_msg.MessageSize := MessageSizeType:Response_Control;
480    }
481  }
482
483  action(pm_sendProbeResponseMiss, "pm", desc="send probe ack, no data") {
484    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
485      out_msg.addr := address;
486      out_msg.Type := CoherenceResponseType:CPUPrbResp;  // L3 and CPUs respond in same way to probes
487      out_msg.Sender := machineID;
488      // will this always be ok? probably not for multisocket
489      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
490      out_msg.Dirty := false;
491      out_msg.Hit := false;
492      out_msg.Ntsl := false;
493      out_msg.State := CoherenceState:NA;
494      out_msg.MessageSize := MessageSizeType:Response_Control;
495    }
496  }
497
498  action(pd_sendProbeResponseData, "pd", desc="send probe ack, with data") {
499    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
500      out_msg.addr := address;
501      out_msg.Type := CoherenceResponseType:CPUPrbResp;  // L3 and CPUs respond in same way to probes
502      out_msg.Sender := machineID;
503      // will this always be ok? probably not for multisocket
504      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
505      out_msg.DataBlk := cache_entry.DataBlk;
506      assert(cache_entry.Dirty);
507      out_msg.Dirty := true;
508      out_msg.Hit := true;
509      out_msg.State := CoherenceState:NA;
510      out_msg.MessageSize := MessageSizeType:Response_Data;
511    }
512  }
513
514  action(pdt_sendProbeResponseDataFromTBE, "pdt", desc="send probe ack with data") {
515    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
516      out_msg.addr := address;
517      out_msg.Type := CoherenceResponseType:CPUPrbResp;
518      out_msg.Sender := machineID;
519      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
520      out_msg.DataBlk := tbe.DataBlk;
521      assert(tbe.Dirty);
522      out_msg.Dirty := true;
523      out_msg.Hit := true;
524      out_msg.MessageSize := MessageSizeType:Response_Data;
525      out_msg.State := CoherenceState:NA;
526      DPRINTF(RubySlicc, "%s\n", out_msg);
527    }
528  }
529
530  action(mc_cancelMemWriteback, "mc", desc="send writeback cancel to memory") {
531    enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) {
532      out_msg.addr := address;
533      out_msg.Type := CoherenceRequestType:WrCancel;
534      out_msg.Requestor := machineID;
535      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
536      out_msg.MessageSize := MessageSizeType:Request_Control;
537    }
538  }
539
540  action(a_allocateBlock, "a", desc="allocate L3 block") {
541    if (is_invalid(cache_entry)) {
542      set_cache_entry(L3cache.allocate(address, new Entry));
543    }
544  }
545
546  action(d_writeData, "d", desc="write data to L3") {
547    peek(responseNetwork_in, ResponseMsg) {
548      if (in_msg.Dirty) {
549        cache_entry.Dirty := in_msg.Dirty;
550      }
551      cache_entry.DataBlk := in_msg.DataBlk;
552      DPRINTF(RubySlicc, "Writing to L3: %s\n", in_msg);
553    }
554  }
555
556  action(rd_copyDataFromRequest, "rd", desc="write data to L3") {
557    peek(requestNetwork_in, CPURequestMsg) {
558      cache_entry.DataBlk := in_msg.DataBlk;
559      cache_entry.Dirty := true;
560    }
561  }
562
563  action(f_setFrom, "f", desc="set who WB is expected to come from") {
564    peek(requestNetwork_in, CPURequestMsg) {
565      tbe.From := in_msg.Requestor;
566    }
567  }
568
569  action(rf_resetFrom, "rf", desc="reset From") {
570    tbe.From := machineID;
571  }
572
573  action(wb_data, "wb", desc="write back data") {
574    enqueue(L3Resp_out, ResponseMsg, l3_request_latency) {
575      out_msg.addr := address;
576      out_msg.Type := CoherenceResponseType:CPUData;
577      out_msg.Sender := machineID;
578      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
579      out_msg.DataBlk := tbe.DataBlk;
580      out_msg.Dirty := tbe.Dirty;
581      if (tbe.Shared) {
582        out_msg.NbReqShared := true;
583      } else {
584        out_msg.NbReqShared := false;
585      }
586      out_msg.State := CoherenceState:Shared; // faux info
587      out_msg.MessageSize := MessageSizeType:Writeback_Data;
588      DPRINTF(RubySlicc, "%s\n", out_msg);
589    }
590  }
591
592  action(wt_writeDataToTBE, "wt", desc="write WB data to TBE") {
593    peek(responseNetwork_in, ResponseMsg) {
594      tbe.DataBlk := in_msg.DataBlk;
595      tbe.Dirty := in_msg.Dirty;
596    }
597  }
598
599  action(uu_sendUnblock, "uu", desc="state changed, unblock") {
600    enqueue(unblockNetwork_out, UnblockMsg, l3_request_latency) {
601      out_msg.addr := address;
602      out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
603      out_msg.MessageSize := MessageSizeType:Unblock_Control;
604      DPRINTF(RubySlicc, "%s\n", out_msg);
605    }
606  }
607
608  action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") {
609    L3cache.setMRU(address);
610  }
611
612  action(p_popRequestQueue, "p", desc="pop request queue") {
613    requestNetwork_in.dequeue(clockEdge());
614  }
615
616  action(pr_popResponseQueue, "pr", desc="pop response queue") {
617    responseNetwork_in.dequeue(clockEdge());
618  }
619
620  action(pn_popNBResponseQueue, "pn", desc="pop NB response queue") {
621    NBResponse_in.dequeue(clockEdge());
622  }
623
624  action(pp_popProbeQueue, "pp", desc="pop probe queue") {
625    probeNetwork_in.dequeue(clockEdge());
626  }
627
628  action(zz_recycleRequestQueue, "\z", desc="recycle request queue") {
629    requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
630  }
631
632
633  // END ACTIONS
634
635  // BEGIN TRANSITIONS
636
637  // transitions from base
638
639  transition({I, I_C}, {RdBlk, RdBlkS, RdBlkM, CtoD}) {TagArrayRead} {
640    r_requestToMem;
641    p_popRequestQueue;
642  }
643
644  transition(O, RdBlk ) {TagArrayRead, DataArrayRead} {
645    rs_sendResponseS;
646    ut_updateTag;
647    p_popRequestQueue;
648  }
649  transition(M, RdBlk, O) {TagArrayRead, DataArrayRead, TagArrayWrite} {
650    rs_sendResponseS;
651    ut_updateTag;
652    p_popRequestQueue;
653  }
654
655  transition(S, RdBlk) {TagArrayRead, DataArrayRead} {
656    rs_sendResponseS;
657    ut_updateTag;
658    p_popRequestQueue;
659  }
660  transition(E, RdBlk, S) {TagArrayRead, DataArrayRead, TagArrayWrite} {
661    rs_sendResponseS;
662    ut_updateTag;
663    p_popRequestQueue;
664  }
665
666  transition({M, O}, RdBlkS, O) {TagArrayRead, DataArrayRead, TagArrayWrite} {
667    rs_sendResponseS;
668    ut_updateTag;
669    p_popRequestQueue;
670  }
671
672  transition({E, S}, RdBlkS, S) {TagArrayRead, DataArrayRead, TagArrayWrite} {
673    rs_sendResponseS;
674    ut_updateTag;
675    p_popRequestQueue;
676  }
677
678  transition(M, RdBlkM, I) {TagArrayRead, TagArrayWrite, DataArrayRead} {
679    rm_sendResponseM;
680    i_invL3;
681    p_popRequestQueue;
682  }
683
684  transition({O, S}, {RdBlkM, CtoD}) {TagArrayRead} {
685    r_requestToMem;  // can't handle this, just forward
686    p_popRequestQueue;
687  }
688
689  transition(E, RdBlkM, I) {TagArrayRead, TagArrayWrite, DataArrayRead} {
690    rm_sendResponseM;
691    i_invL3;
692    p_popRequestQueue;
693  }
694
695  transition({I}, WrVicBlk, I_M) {TagArrayRead, TagArrayWrite} {
696    a_allocateBlock;
697    t_allocateTBE;
698    f_setFrom;
699//    rd_copyDataFromRequest;
700    w_sendResponseWBAck;
701    p_popRequestQueue;
702  }
703
704  transition(I_C, {WrVicBlk, WrVicBlkShared, ClVicBlk, ClVicBlkShared}) {} {
705    zz_recycleRequestQueue;
706  }
707
708  transition({I}, WrVicBlkShared, I_O) {TagArrayRead, TagArrayWrite} {
709    a_allocateBlock;
710    t_allocateTBE;
711    f_setFrom;
712//    rd_copyDataFromRequest;
713    w_sendResponseWBAck;
714    p_popRequestQueue;
715  }
716
717  transition(S, WrVicBlkShared, S_O) {TagArrayRead, TagArrayWrite} {
718//    rd_copyDataFromRequest;
719    t_allocateTBE;
720    f_setFrom;
721    w_sendResponseWBAck;
722    p_popRequestQueue;
723  }
724
725  transition(S, WrVicBlk, S_M) {TagArrayRead, TagArrayWrite} { // should be technically not possible, but assume the data comes back with shared bit flipped
726//    rd_copyDataFromRequest;
727    t_allocateTBE;
728    f_setFrom;
729    w_sendResponseWBAck;
730    p_popRequestQueue;
731  }
732
733  transition(E, WrVicBlk, E_M) {TagArrayRead, TagArrayWrite}  {
734    t_allocateTBE;
735    f_setFrom;
736    w_sendResponseWBAck;
737    p_popRequestQueue;
738  }
739
740  transition(E, WrVicBlkShared, E_O) {TagArrayRead, TagArrayWrite} {
741    t_allocateTBE;
742    f_setFrom;
743    w_sendResponseWBAck;
744    p_popRequestQueue;
745  }
746
747  transition(O, WrVicBlk, O_M) {TagArrayRead, TagArrayWrite} {
748    t_allocateTBE;
749    f_setFrom;
750    w_sendResponseWBAck;
751    p_popRequestQueue;
752  }
753
754  transition(O, WrVicBlkShared, O_O) {TagArrayRead, TagArrayWrite} {
755    t_allocateTBE;
756    f_setFrom;
757    w_sendResponseWBAck;
758    p_popRequestQueue;
759  }
760
761  transition(M, WrVicBlk, M_M) {TagArrayRead, TagArrayWrite} {
762    t_allocateTBE;
763    f_setFrom;
764    w_sendResponseWBAck;
765    p_popRequestQueue;
766  }
767
768  transition(M, WrVicBlkShared, M_O) {TagArrayRead, TagArrayWrite} {
769    t_allocateTBE;
770    f_setFrom;
771    w_sendResponseWBAck;
772    p_popRequestQueue;
773  }
774
775  transition({I}, ClVicBlk, I_E) {TagArrayRead, TagArrayWrite} {
776    t_allocateTBE;
777    f_setFrom;
778    a_allocateBlock;
779    w_sendResponseWBAck;
780    p_popRequestQueue;
781  }
782
783  transition({I}, ClVicBlkShared, I_S) {TagArrayRead, TagArrayWrite} {
784    t_allocateTBE;
785    f_setFrom;
786    a_allocateBlock;
787    w_sendResponseWBAck;
788    p_popRequestQueue;
789  }
790
791  transition(S, ClVicBlk, S_E) {TagArrayRead, TagArrayWrite} { // technically impossible, assume data comes back with shared bit flipped
792    t_allocateTBE;
793    f_setFrom;
794    w_sendResponseWBAck;
795    p_popRequestQueue;
796  }
797
798  transition(S, ClVicBlkShared, S_S) {TagArrayRead, TagArrayWrite} {
799    t_allocateTBE;
800    f_setFrom;
801    w_sendResponseWBAck;
802    p_popRequestQueue;
803  }
804
805  transition(E, ClVicBlk, E_E) {TagArrayRead, TagArrayWrite} {
806    t_allocateTBE;
807    f_setFrom;
808    w_sendResponseWBAck;
809    p_popRequestQueue;
810  }
811
812  transition(E, ClVicBlkShared, E_S) {TagArrayRead, TagArrayWrite} {
813    t_allocateTBE;
814    f_setFrom;
815    w_sendResponseWBAck;
816    p_popRequestQueue;
817  }
818
819  transition(O, ClVicBlk, O_E) {TagArrayRead, TagArrayWrite} { // technically impossible, but assume data comes back with shared bit flipped
820    t_allocateTBE;
821    f_setFrom;
822    w_sendResponseWBAck;
823    p_popRequestQueue;
824  }
825
826  transition(O, ClVicBlkShared, O_S) {TagArrayRead, TagArrayWrite} {
827    t_allocateTBE;
828    f_setFrom;
829    w_sendResponseWBAck;
830    p_popRequestQueue;
831  }
832
833  transition(M, ClVicBlk, M_E) {TagArrayRead, TagArrayWrite}  {
834    t_allocateTBE;
835    f_setFrom;
836    w_sendResponseWBAck;
837    p_popRequestQueue;
838  }
839
840  transition(M, ClVicBlkShared, M_S) {TagArrayRead, TagArrayWrite} {
841    t_allocateTBE;
842    f_setFrom;
843    w_sendResponseWBAck;
844    p_popRequestQueue;
845  }
846
847  transition({MO_I}, {RdBlk, RdBlkS, RdBlkM, CtoD}) {} {
848    r_requestToMem;
849    p_popRequestQueue;
850  }
851
852  transition(MO_I, {WrVicBlkShared, WrVicBlk, ClVicBlk, ClVicBlkShared}, MOD_I) {TagArrayWrite} {
853    f_setFrom;
854    w_sendResponseWBAck;
855    p_popRequestQueue;
856  }
857
858  transition(I_M, CPUData, M) {DataArrayWrite, TagArrayWrite} {
859    uu_sendUnblock;
860    dt_deallocateTBE;
861    d_writeData;
862    pr_popResponseQueue;
863  }
864
865  transition(I_M, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} {
866    uu_sendUnblock;
867    dt_deallocateTBE;
868    d_writeData;
869    pr_popResponseQueue;
870  }
871
872  transition(I_O, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} {
873    uu_sendUnblock;
874    dt_deallocateTBE;
875    d_writeData;
876    pr_popResponseQueue;
877  }
878
879  transition(I_E, CPUData, E) {DataArrayWrite, TagArrayWrite} {
880    uu_sendUnblock;
881    dt_deallocateTBE;
882    d_writeData;
883    pr_popResponseQueue;
884  }
885
886  transition(I_E, CPUDataShared, S) {DataArrayWrite, TagArrayWrite} {
887    uu_sendUnblock;
888    dt_deallocateTBE;
889    d_writeData;
890    pr_popResponseQueue;
891  }
892
893  transition(I_S, {CPUData, CPUDataShared}, S) {DataArrayWrite, TagArrayWrite} {
894    uu_sendUnblock;
895    dt_deallocateTBE;
896    d_writeData;
897    pr_popResponseQueue;
898  }
899
900  transition(S_M, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} {
901    uu_sendUnblock;
902    dt_deallocateTBE;
903    d_writeData;
904    ut_updateTag;  // update tag on writeback hits.
905    pr_popResponseQueue;
906  }
907
908  transition(S_O, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} {
909    uu_sendUnblock;
910    dt_deallocateTBE;
911    d_writeData;
912    ut_updateTag;  // update tag on writeback hits.
913    pr_popResponseQueue;
914  }
915
916  transition(S_E, CPUDataShared, S) {DataArrayWrite, TagArrayWrite} {
917    uu_sendUnblock;
918    dt_deallocateTBE;
919    d_writeData;
920    ut_updateTag;  // update tag on writeback hits.
921    pr_popResponseQueue;
922  }
923
924  transition(S_S, {CPUData, CPUDataShared}, S) {DataArrayWrite, TagArrayWrite} {
925    uu_sendUnblock;
926    dt_deallocateTBE;
927    d_writeData;
928    ut_updateTag;  // update tag on writeback hits.
929    pr_popResponseQueue;
930  }
931
932  transition(O_E, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} {
933    uu_sendUnblock;
934    dt_deallocateTBE;
935    d_writeData;
936    ut_updateTag;  // update tag on writeback hits.
937    pr_popResponseQueue;
938  }
939
940  transition(O_S, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} {
941    uu_sendUnblock;
942    dt_deallocateTBE;
943    d_writeData;
944    ut_updateTag;  // update tag on writeback hits.
945    pr_popResponseQueue;
946  }
947
948  transition({D_I}, {CPUData, CPUDataShared}, I) {TagArrayWrite} {
949    uu_sendUnblock;
950    dt_deallocateTBE;
951    pr_popResponseQueue;
952  }
953
954  transition(MOD_I, {CPUData, CPUDataShared}, MO_I) {TagArrayWrite} {
955    uu_sendUnblock;
956    rf_resetFrom;
957    pr_popResponseQueue;
958  }
959
960  transition(I_I, {CPUData, CPUDataShared}, MO_I) {TagArrayWrite, DataArrayRead} {
961    uu_sendUnblock;
962    wt_writeDataToTBE;
963    rf_resetFrom;
964    pr_popResponseQueue;
965  }
966
967  transition(I_CD, {CPUData, CPUDataShared}, I) {DataArrayRead, TagArrayWrite} {
968    uu_sendUnblock;
969    wt_writeDataToTBE;
970    wb_data;
971    dt_deallocateTBE;
972    pr_popResponseQueue;
973  }
974
975  transition({M, O}, L3_Repl, MO_I) {TagArrayRead, TagArrayWrite} {
976    t_allocateTBE;
977    vd_vicDirty;
978    i_invL3;
979  }
980
981  transition({E, S,}, L3_Repl, I) {TagArrayRead, TagArrayWrite} {
982    i_invL3;
983  }
984
985  transition({I_M, I_O, S_M, S_O, E_M, E_O}, L3_Repl) {} {
986    zz_recycleRequestQueue;
987  }
988
989  transition({O_M, O_O, O_E, O_S, M_M, M_O, M_E, M_S}, L3_Repl) {} {
990    zz_recycleRequestQueue;
991  }
992
993  transition({I_E, I_S, S_E, S_S, E_E, E_S}, L3_Repl) {} {
994    zz_recycleRequestQueue;
995  }
996
997  transition({M, O}, PrbInvData, I) {TagArrayRead, TagArrayWrite, DataArrayRead} {
998    pd_sendProbeResponseData;
999    i_invL3;
1000    pp_popProbeQueue;
1001  }
1002
1003  transition({E, S, I}, PrbInvData, I) {TagArrayRead, TagArrayWrite} {
1004    pi_sendProbeResponseInv;
1005    i_invL3;  // nothing will happen in I
1006    pp_popProbeQueue;
1007  }
1008
1009  transition({M, O, E, S, I}, PrbInv, I) {TagArrayRead, TagArrayWrite} {
1010    pi_sendProbeResponseInv;
1011    i_invL3; // nothing will happen in I
1012    pp_popProbeQueue;
1013  }
1014
1015  transition({M, O}, PrbShrData, O) {TagArrayRead, DataArrayRead, TagArrayWrite} {
1016    pd_sendProbeResponseData;
1017    pp_popProbeQueue;
1018  }
1019
1020  transition({E, S}, PrbShrData, S) {TagArrayRead, TagArrayWrite} {
1021    ph_sendProbeResponseHit;
1022    pp_popProbeQueue;
1023  }
1024
1025  transition(I, PrbShrData) {TagArrayRead} {
1026    pm_sendProbeResponseMiss;
1027    pp_popProbeQueue;
1028  }
1029
1030  transition(MO_I, PrbInvData, I_C) {TagArrayWrite, DataArrayRead} {
1031    pdt_sendProbeResponseDataFromTBE;
1032    mc_cancelMemWriteback;
1033    pp_popProbeQueue;
1034  }
1035
1036  transition(MO_I, PrbInv, I_C) {TagArrayWrite} {
1037    pi_sendProbeResponseInv;
1038    mc_cancelMemWriteback;
1039    pp_popProbeQueue;
1040  }
1041
1042  transition(MO_I, PrbShrData) {DataArrayRead} {
1043    pdt_sendProbeResponseDataFromTBE;
1044    pp_popProbeQueue;
1045  }
1046
1047  transition(I_C, {PrbInvData, PrbInv}) {} {
1048    pi_sendProbeResponseInv;
1049    pp_popProbeQueue;
1050  }
1051
1052  transition(I_C, PrbShrData) {} {
1053    pm_sendProbeResponseMiss;
1054    pp_popProbeQueue;
1055  }
1056
1057  transition(I_I, {WBAck}, I_CD) {TagArrayWrite} {
1058    pn_popNBResponseQueue;
1059  }
1060
1061  transition(MOD_I, WBAck, D_I) {DataArrayRead} {
1062    wb_data;
1063    pn_popNBResponseQueue;
1064  }
1065
1066  transition(MO_I, WBAck, I) {DataArrayRead, TagArrayWrite} {
1067    wb_data;
1068    dt_deallocateTBE;
1069    pn_popNBResponseQueue;
1070  }
1071
1072  transition(I_C, {WBAck}, I) {TagArrayWrite} {
1073    dt_deallocateTBE;
1074    pn_popNBResponseQueue;
1075  }
1076
1077  transition({I_M, I_O, I_E, I_S}, CancelWB, I) {TagArrayWrite} {
1078    uu_sendUnblock;
1079    dt_deallocateTBE;
1080    i_invL3;
1081    p_popRequestQueue;
1082  }
1083
1084  transition({S_S, S_O, S_M, S_E}, CancelWB, S) {TagArrayWrite} {
1085    uu_sendUnblock;
1086    dt_deallocateTBE;
1087    p_popRequestQueue;
1088  }
1089
1090  transition({E_M, E_O, E_E, E_S}, CancelWB, E) {TagArrayWrite} {
1091    uu_sendUnblock;
1092    dt_deallocateTBE;
1093    p_popRequestQueue;
1094  }
1095
1096  transition({O_M, O_O, O_E, O_S}, CancelWB, O) {TagArrayWrite} {
1097    uu_sendUnblock;
1098    dt_deallocateTBE;
1099    p_popRequestQueue;
1100  }
1101
1102  transition({M_M, M_O, M_E, M_S}, CancelWB, M) {TagArrayWrite} {
1103    uu_sendUnblock;
1104    dt_deallocateTBE;
1105    p_popRequestQueue;
1106  }
1107
1108  transition(D_I, CancelWB, I) {TagArrayWrite} {
1109    uu_sendUnblock;
1110    dt_deallocateTBE;
1111    p_popRequestQueue;
1112  }
1113
1114  transition(MOD_I, CancelWB, MO_I) {TagArrayWrite} {
1115    uu_sendUnblock;
1116    rf_resetFrom;
1117    p_popRequestQueue;
1118  }
1119
1120  transition(I_I, CancelWB, I_C) {TagArrayWrite} {
1121    uu_sendUnblock;
1122    rf_resetFrom;
1123    mc_cancelMemWriteback;
1124    p_popRequestQueue;
1125  }
1126
1127  transition(I_CD, CancelWB, I) {TagArrayWrite} {
1128    uu_sendUnblock;
1129    dt_deallocateTBE;
1130    mc_cancelMemWriteback;
1131    p_popRequestQueue;
1132  }
1133
1134}
1135