MESI_Three_Level-L1cache.sm revision 14184:11ac1337c5e2
1/*
2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29machine(MachineType:L1Cache, "MESI Directory L1 Cache CMP")
30 : CacheMemory * cache;
31   int l2_select_num_bits;
32   Cycles l1_request_latency := 2;
33   Cycles l1_response_latency := 2;
34   Cycles to_l2_latency := 1;
35
36   // Message Buffers between the L1 and the L0 Cache
37   // From the L1 cache to the L0 cache
38   MessageBuffer * bufferToL0, network="To";
39
40   // From the L0 cache to the L1 cache
41   MessageBuffer * bufferFromL0, network="From";
42
43   // Message queue from this L1 cache TO the network / L2
44   MessageBuffer * requestToL2, network="To", virtual_network="0",
45        vnet_type="request";
46
47   MessageBuffer * responseToL2, network="To", virtual_network="1",
48        vnet_type="response";
49   MessageBuffer * unblockToL2, network="To", virtual_network="2",
50        vnet_type="unblock";
51
52   // To this L1 cache FROM the network / L2
53   MessageBuffer * requestFromL2, network="From", virtual_network="2",
54        vnet_type="request";
55   MessageBuffer * responseFromL2, network="From", virtual_network="1",
56        vnet_type="response";
57
58{
59  // STATES
60  state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
61    // Base states
62    I, AccessPermission:Invalid, desc="a L1 cache entry Idle";
63    S, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
64    SS, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
65    E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive";
66    EE, AccessPermission:Read_Write, desc="a L1 cache entry Exclusive";
67    M, AccessPermission:Maybe_Stale, desc="a L1 cache entry Modified", format="!b";
68    MM, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b";
69
70    // Transient States
71    IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet";
72    IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet";
73    SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet";
74    IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before data because directory doesn't block on GETS hit";
75    M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK";
76    SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2";
77
78    // For all of the following states, invalidate
79    // message has been sent to L0 cache. The response
80    // from the L0 cache has not been seen yet.
81    S_IL0, AccessPermission:Busy;
82    E_IL0, AccessPermission:Busy;
83    M_IL0, AccessPermission:Busy;
84    MM_IL0, AccessPermission:Read_Write;
85    SM_IL0, AccessPermission:Busy;
86  }
87
88  // EVENTS
89  enumeration(Event, desc="Cache events") {
90    // Requests from the L0 cache
91    Load,            desc="Load request";
92    Store,           desc="Store request";
93    WriteBack,       desc="Writeback request";
94
95    // Responses from the L0 Cache
96    // L0 cache received the invalidation message
97    // and has sent the data.
98    L0_DataAck;
99
100    Inv,           desc="Invalidate request from L2 bank";
101
102    // internal generated request
103    // Invalidate the line in L0 due to own requirements
104    L0_Invalidate_Own;
105    // Invalidate the line in L0 due to some other cache's requirements
106    L0_Invalidate_Else;
107    // Invalidate the line in the cache due to some one else / space needs.
108    L1_Replacement;
109
110    // other requests
111    Fwd_GETX,   desc="GETX from other processor";
112    Fwd_GETS,   desc="GETS from other processor";
113
114    Data,       desc="Data for processor";
115    Data_Exclusive,       desc="Data for processor";
116    DataS_fromL1,       desc="data for GETS request, need to unblock directory";
117    Data_all_Acks,       desc="Data for processor, all acks";
118
119    L0_Ack,        desc="Ack for processor";
120    Ack,        desc="Ack for processor";
121    Ack_all,      desc="Last ack for processor";
122
123    WB_Ack,        desc="Ack for replacement";
124  }
125
126  // TYPES
127
128  // CacheEntry
129  structure(Entry, desc="...", interface="AbstractCacheEntry" ) {
130    State CacheState,        desc="cache state";
131    DataBlock DataBlk,       desc="data for the block";
132    bool Dirty, default="false",   desc="data is dirty";
133  }
134
135  // TBE fields
136  structure(TBE, desc="...") {
137    Addr addr,              desc="Physical address for this TBE";
138    State TBEState,        desc="Transient state";
139    DataBlock DataBlk,                desc="Buffer for the data block";
140    bool Dirty, default="false",   desc="data is dirty";
141    int pendingAcks, default="0", desc="number of pending acks";
142  }
143
144  structure(TBETable, external="yes") {
145    TBE lookup(Addr);
146    void allocate(Addr);
147    void deallocate(Addr);
148    bool isPresent(Addr);
149  }
150
151  TBETable TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
152
153  int l2_select_low_bit, default="RubySystem::getBlockSizeBits()";
154
155  Tick clockEdge();
156  Cycles ticksToCycles(Tick t);
157  void set_cache_entry(AbstractCacheEntry a);
158  void unset_cache_entry();
159  void set_tbe(TBE a);
160  void unset_tbe();
161  void wakeUpBuffers(Addr a);
162  void wakeUpAllBuffers(Addr a);
163  void profileMsgDelay(int virtualNetworkType, Cycles c);
164
165  // inclusive cache returns L1 entries only
166  Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
167    Entry cache_entry := static_cast(Entry, "pointer", cache[addr]);
168    return cache_entry;
169  }
170
171  State getState(TBE tbe, Entry cache_entry, Addr addr) {
172    if(is_valid(tbe)) {
173      return tbe.TBEState;
174    } else if (is_valid(cache_entry)) {
175      return cache_entry.CacheState;
176    }
177    return State:I;
178  }
179
180  void setState(TBE tbe, Entry cache_entry, Addr addr, State state) {
181    // MUST CHANGE
182    if(is_valid(tbe)) {
183      tbe.TBEState := state;
184    }
185
186    if (is_valid(cache_entry)) {
187      cache_entry.CacheState := state;
188    }
189  }
190
191  AccessPermission getAccessPermission(Addr addr) {
192    TBE tbe := TBEs[addr];
193    if(is_valid(tbe)) {
194      DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState));
195      return L1Cache_State_to_permission(tbe.TBEState);
196    }
197
198    Entry cache_entry := getCacheEntry(addr);
199    if(is_valid(cache_entry)) {
200      DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState));
201      return L1Cache_State_to_permission(cache_entry.CacheState);
202    }
203
204    DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
205    return AccessPermission:NotPresent;
206  }
207
208  void functionalRead(Addr addr, Packet *pkt) {
209    TBE tbe := TBEs[addr];
210    if(is_valid(tbe)) {
211      testAndRead(addr, tbe.DataBlk, pkt);
212    } else {
213      testAndRead(addr, getCacheEntry(addr).DataBlk, pkt);
214    }
215  }
216
217  int functionalWrite(Addr addr, Packet *pkt) {
218    int num_functional_writes := 0;
219
220    TBE tbe := TBEs[addr];
221    if(is_valid(tbe)) {
222      num_functional_writes := num_functional_writes +
223        testAndWrite(addr, tbe.DataBlk, pkt);
224      return num_functional_writes;
225    }
226
227    num_functional_writes := num_functional_writes +
228        testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt);
229    return num_functional_writes;
230  }
231
232  void setAccessPermission(Entry cache_entry, Addr addr, State state) {
233    if (is_valid(cache_entry)) {
234      cache_entry.changePermission(L1Cache_State_to_permission(state));
235    }
236  }
237
238  Event mandatory_request_type_to_event(CoherenceClass type) {
239    if (type == CoherenceClass:GETS) {
240      return Event:Load;
241    } else if ((type == CoherenceClass:GETX) ||
242               (type == CoherenceClass:UPGRADE)) {
243      return Event:Store;
244    } else if (type == CoherenceClass:PUTX) {
245      return Event:WriteBack;
246    } else {
247      error("Invalid RequestType");
248    }
249  }
250
251  int getPendingAcks(TBE tbe) {
252    return tbe.pendingAcks;
253  }
254
255  bool inL0Cache(State state) {
256    if (state == State:S || state == State:E || state == State:M ||
257        state == State:S_IL0 || state == State:E_IL0 ||
258        state == State:M_IL0 || state == State:SM_IL0) {
259        return true;
260    }
261
262    return false;
263  }
264
265  out_port(requestNetwork_out, RequestMsg, requestToL2);
266  out_port(responseNetwork_out, ResponseMsg, responseToL2);
267  out_port(unblockNetwork_out, ResponseMsg, unblockToL2);
268  out_port(bufferToL0_out, CoherenceMsg, bufferToL0);
269
270  // Response From the L2 Cache to this L1 cache
271  in_port(responseNetwork_in, ResponseMsg, responseFromL2, rank = 3) {
272    if (responseNetwork_in.isReady(clockEdge())) {
273      peek(responseNetwork_in, ResponseMsg) {
274        assert(in_msg.Destination.isElement(machineID));
275
276        Entry cache_entry := getCacheEntry(in_msg.addr);
277        TBE tbe := TBEs[in_msg.addr];
278
279        if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
280          trigger(Event:Data_Exclusive, in_msg.addr, cache_entry, tbe);
281        } else if(in_msg.Type == CoherenceResponseType:DATA) {
282          if ((getState(tbe, cache_entry, in_msg.addr) == State:IS ||
283               getState(tbe, cache_entry, in_msg.addr) == State:IS_I) &&
284              machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) {
285
286              trigger(Event:DataS_fromL1, in_msg.addr, cache_entry, tbe);
287
288          } else if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) {
289            trigger(Event:Data_all_Acks, in_msg.addr, cache_entry, tbe);
290          } else {
291            trigger(Event:Data, in_msg.addr, cache_entry, tbe);
292          }
293        } else if (in_msg.Type == CoherenceResponseType:ACK) {
294          if ( (getPendingAcks(tbe) - in_msg.AckCount) == 0 ) {
295            trigger(Event:Ack_all, in_msg.addr, cache_entry, tbe);
296          } else {
297            trigger(Event:Ack, in_msg.addr, cache_entry, tbe);
298          }
299        } else if (in_msg.Type == CoherenceResponseType:WB_ACK) {
300          trigger(Event:WB_Ack, in_msg.addr, cache_entry, tbe);
301        } else {
302          error("Invalid L1 response type");
303        }
304      }
305    }
306  }
307
308  // Request to this L1 cache from the shared L2
309  in_port(requestNetwork_in, RequestMsg, requestFromL2, rank = 2) {
310    if(requestNetwork_in.isReady(clockEdge())) {
311      peek(requestNetwork_in, RequestMsg) {
312        assert(in_msg.Destination.isElement(machineID));
313        Entry cache_entry := getCacheEntry(in_msg.addr);
314        TBE tbe := TBEs[in_msg.addr];
315
316        if (in_msg.Type == CoherenceRequestType:INV) {
317            if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
318                trigger(Event:L0_Invalidate_Else, in_msg.addr,
319                        cache_entry, tbe);
320            }  else {
321                trigger(Event:Inv, in_msg.addr, cache_entry, tbe);
322            }
323        } else if (in_msg.Type == CoherenceRequestType:GETX ||
324                   in_msg.Type == CoherenceRequestType:UPGRADE) {
325            if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
326                trigger(Event:L0_Invalidate_Else, in_msg.addr,
327                        cache_entry, tbe);
328            } else {
329                trigger(Event:Fwd_GETX, in_msg.addr, cache_entry, tbe);
330            }
331        } else if (in_msg.Type == CoherenceRequestType:GETS) {
332            if (is_valid(cache_entry) && inL0Cache(cache_entry.CacheState)) {
333                trigger(Event:L0_Invalidate_Else, in_msg.addr,
334                        cache_entry, tbe);
335            } else {
336                trigger(Event:Fwd_GETS, in_msg.addr, cache_entry, tbe);
337            }
338        } else {
339          error("Invalid forwarded request type");
340        }
341      }
342    }
343  }
344
345  // Requests to this L1 cache from the L0 cache.
346  in_port(messageBufferFromL0_in, CoherenceMsg, bufferFromL0, rank = 0) {
347    if (messageBufferFromL0_in.isReady(clockEdge())) {
348      peek(messageBufferFromL0_in, CoherenceMsg) {
349        Entry cache_entry := getCacheEntry(in_msg.addr);
350        TBE tbe := TBEs[in_msg.addr];
351
352        if(in_msg.Class == CoherenceClass:INV_DATA) {
353            trigger(Event:L0_DataAck, in_msg.addr, cache_entry, tbe);
354        }  else if (in_msg.Class == CoherenceClass:INV_ACK) {
355            trigger(Event:L0_Ack, in_msg.addr, cache_entry, tbe);
356        }  else {
357            if (is_valid(cache_entry)) {
358                trigger(mandatory_request_type_to_event(in_msg.Class),
359                        in_msg.addr, cache_entry, tbe);
360            } else {
361                if (cache.cacheAvail(in_msg.addr)) {
362                    // L1 does't have the line, but we have space for it
363                    // in the L1 let's see if the L2 has it
364                    trigger(mandatory_request_type_to_event(in_msg.Class),
365                            in_msg.addr, cache_entry, tbe);
366                } else {
367                    // No room in the L1, so we need to make room in the L1
368                    Entry victim_entry :=
369                        getCacheEntry(cache.cacheProbe(in_msg.addr));
370                    TBE victim_tbe := TBEs[cache.cacheProbe(in_msg.addr)];
371
372                    if (is_valid(victim_entry) && inL0Cache(victim_entry.CacheState)) {
373                        trigger(Event:L0_Invalidate_Own,
374                                cache.cacheProbe(in_msg.addr),
375                                victim_entry, victim_tbe);
376                    }  else {
377                        trigger(Event:L1_Replacement,
378                                cache.cacheProbe(in_msg.addr),
379                                victim_entry, victim_tbe);
380                    }
381                }
382            }
383        }
384      }
385    }
386  }
387
388  // ACTIONS
389  action(a_issueGETS, "a", desc="Issue GETS") {
390    peek(messageBufferFromL0_in, CoherenceMsg) {
391      enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
392        out_msg.addr := address;
393        out_msg.Type := CoherenceRequestType:GETS;
394        out_msg.Requestor := machineID;
395        out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
396                          l2_select_low_bit, l2_select_num_bits, clusterID));
397        DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
398                address, out_msg.Destination);
399        out_msg.MessageSize := MessageSizeType:Control;
400        out_msg.AccessMode := in_msg.AccessMode;
401      }
402    }
403  }
404
405  action(b_issueGETX, "b", desc="Issue GETX") {
406    peek(messageBufferFromL0_in, CoherenceMsg) {
407      enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
408        out_msg.addr := address;
409        out_msg.Type := CoherenceRequestType:GETX;
410        out_msg.Requestor := machineID;
411        DPRINTF(RubySlicc, "%s\n", machineID);
412        out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
413                          l2_select_low_bit, l2_select_num_bits, clusterID));
414        DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
415                address, out_msg.Destination);
416        out_msg.MessageSize := MessageSizeType:Control;
417        out_msg.AccessMode := in_msg.AccessMode;
418      }
419    }
420  }
421
422  action(c_issueUPGRADE, "c", desc="Issue GETX") {
423    peek(messageBufferFromL0_in, CoherenceMsg) {
424      enqueue(requestNetwork_out, RequestMsg, l1_request_latency) {
425        out_msg.addr := address;
426        out_msg.Type := CoherenceRequestType:UPGRADE;
427        out_msg.Requestor := machineID;
428        out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
429                          l2_select_low_bit, l2_select_num_bits, clusterID));
430        DPRINTF(RubySlicc, "address: %#x, destination: %s\n",
431                address, out_msg.Destination);
432        out_msg.MessageSize := MessageSizeType:Control;
433        out_msg.AccessMode := in_msg.AccessMode;
434      }
435    }
436  }
437
438  action(d_sendDataToRequestor, "d", desc="send data to requestor") {
439    peek(requestNetwork_in, RequestMsg) {
440      enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
441        assert(is_valid(cache_entry));
442        out_msg.addr := address;
443        out_msg.Type := CoherenceResponseType:DATA;
444        out_msg.DataBlk := cache_entry.DataBlk;
445        out_msg.Dirty := cache_entry.Dirty;
446        out_msg.Sender := machineID;
447        out_msg.Destination.add(in_msg.Requestor);
448        out_msg.MessageSize := MessageSizeType:Response_Data;
449      }
450    }
451  }
452
453  action(d2_sendDataToL2, "d2", desc="send data to the L2 cache because of M downgrade") {
454    enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
455      assert(is_valid(cache_entry));
456      out_msg.addr := address;
457      out_msg.Type := CoherenceResponseType:DATA;
458      out_msg.DataBlk := cache_entry.DataBlk;
459      out_msg.Dirty := cache_entry.Dirty;
460      out_msg.Sender := machineID;
461      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
462                          l2_select_low_bit, l2_select_num_bits, clusterID));
463      out_msg.MessageSize := MessageSizeType:Response_Data;
464    }
465  }
466
467  action(dt_sendDataToRequestor_fromTBE, "dt", desc="send data to requestor") {
468    peek(requestNetwork_in, RequestMsg) {
469      enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
470        assert(is_valid(tbe));
471        out_msg.addr := address;
472        out_msg.Type := CoherenceResponseType:DATA;
473        out_msg.DataBlk := tbe.DataBlk;
474        out_msg.Dirty := tbe.Dirty;
475        out_msg.Sender := machineID;
476        out_msg.Destination.add(in_msg.Requestor);
477        out_msg.MessageSize := MessageSizeType:Response_Data;
478      }
479    }
480  }
481
482  action(d2t_sendDataToL2_fromTBE, "d2t", desc="send data to the L2 cache") {
483    enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
484      assert(is_valid(tbe));
485      out_msg.addr := address;
486      out_msg.Type := CoherenceResponseType:DATA;
487      out_msg.DataBlk := tbe.DataBlk;
488      out_msg.Dirty := tbe.Dirty;
489      out_msg.Sender := machineID;
490      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
491                          l2_select_low_bit, l2_select_num_bits, clusterID));
492      out_msg.MessageSize := MessageSizeType:Response_Data;
493    }
494  }
495
496  action(e_sendAckToRequestor, "e", desc="send invalidate ack to requestor (could be L2 or L1)") {
497    peek(requestNetwork_in, RequestMsg) {
498      enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
499        out_msg.addr := address;
500        out_msg.Type := CoherenceResponseType:ACK;
501        out_msg.Sender := machineID;
502        out_msg.Destination.add(in_msg.Requestor);
503        out_msg.MessageSize := MessageSizeType:Response_Control;
504      }
505    }
506  }
507
508  action(f_sendDataToL2, "f", desc="send data to the L2 cache") {
509    enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
510      assert(is_valid(cache_entry));
511      out_msg.addr := address;
512      out_msg.Type := CoherenceResponseType:DATA;
513      out_msg.DataBlk := cache_entry.DataBlk;
514      out_msg.Dirty := cache_entry.Dirty;
515      out_msg.Sender := machineID;
516      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
517                          l2_select_low_bit, l2_select_num_bits, clusterID));
518      out_msg.MessageSize := MessageSizeType:Writeback_Data;
519    }
520  }
521
522  action(ft_sendDataToL2_fromTBE, "ft", desc="send data to the L2 cache") {
523    enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
524      assert(is_valid(tbe));
525      out_msg.addr := address;
526      out_msg.Type := CoherenceResponseType:DATA;
527      out_msg.DataBlk := tbe.DataBlk;
528      out_msg.Dirty := tbe.Dirty;
529      out_msg.Sender := machineID;
530      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
531                          l2_select_low_bit, l2_select_num_bits, clusterID));
532      out_msg.MessageSize := MessageSizeType:Writeback_Data;
533    }
534  }
535
536  action(fi_sendInvAck, "fi", desc="send data to the L2 cache") {
537    peek(requestNetwork_in, RequestMsg) {
538      enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) {
539        out_msg.addr := address;
540        out_msg.Type := CoherenceResponseType:ACK;
541        out_msg.Sender := machineID;
542        out_msg.Destination.add(in_msg.Requestor);
543        out_msg.MessageSize := MessageSizeType:Response_Control;
544        out_msg.AckCount := 1;
545      }
546    }
547  }
548
549  action(forward_eviction_to_L0, "\cc", desc="sends eviction information to the processor") {
550      enqueue(bufferToL0_out, CoherenceMsg, l1_request_latency) {
551          out_msg.addr := address;
552          out_msg.Class := CoherenceClass:INV;
553          out_msg.Sender := machineID;
554          out_msg.Dest := createMachineID(MachineType:L0Cache, version);
555          out_msg.MessageSize := MessageSizeType:Control;
556      }
557  }
558
559  action(g_issuePUTX, "g", desc="send data to the L2 cache") {
560    enqueue(requestNetwork_out, RequestMsg, l1_response_latency) {
561      assert(is_valid(cache_entry));
562      out_msg.addr := address;
563      out_msg.Type := CoherenceRequestType:PUTX;
564      out_msg.Dirty := cache_entry.Dirty;
565      out_msg.Requestor:= machineID;
566      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
567                          l2_select_low_bit, l2_select_num_bits, clusterID));
568      if (cache_entry.Dirty) {
569        out_msg.MessageSize := MessageSizeType:Writeback_Data;
570        out_msg.DataBlk := cache_entry.DataBlk;
571      } else {
572        out_msg.MessageSize := MessageSizeType:Writeback_Control;
573      }
574    }
575  }
576
577  action(j_sendUnblock, "j", desc="send unblock to the L2 cache") {
578    enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) {
579      out_msg.addr := address;
580      out_msg.Type := CoherenceResponseType:UNBLOCK;
581      out_msg.Sender := machineID;
582      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
583                          l2_select_low_bit, l2_select_num_bits, clusterID));
584      out_msg.MessageSize := MessageSizeType:Response_Control;
585      DPRINTF(RubySlicc, "%#x\n", address);
586    }
587  }
588
589  action(jj_sendExclusiveUnblock, "\j", desc="send unblock to the L2 cache") {
590    enqueue(unblockNetwork_out, ResponseMsg, to_l2_latency) {
591      out_msg.addr := address;
592      out_msg.Type := CoherenceResponseType:EXCLUSIVE_UNBLOCK;
593      out_msg.Sender := machineID;
594      out_msg.Destination.add(mapAddressToRange(address, MachineType:L2Cache,
595                          l2_select_low_bit, l2_select_num_bits, clusterID));
596      out_msg.MessageSize := MessageSizeType:Response_Control;
597      DPRINTF(RubySlicc, "%#x\n", address);
598
599    }
600  }
601
602  action(h_data_to_l0, "h", desc="If not prefetch, send data to the L0 cache.") {
603      enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
604          assert(is_valid(cache_entry));
605
606          out_msg.addr := address;
607          out_msg.Class := CoherenceClass:DATA;
608          out_msg.Sender := machineID;
609          out_msg.Dest := createMachineID(MachineType:L0Cache, version);
610          out_msg.DataBlk := cache_entry.DataBlk;
611          out_msg.MessageSize := MessageSizeType:Response_Data;
612      }
613  }
614
615  action(hh_xdata_to_l0, "\h", desc="If not prefetch, notify sequencer that store completed.") {
616      enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
617          assert(is_valid(cache_entry));
618
619          out_msg.addr := address;
620          out_msg.Class := CoherenceClass:DATA_EXCLUSIVE;
621          out_msg.Sender := machineID;
622          out_msg.Dest := createMachineID(MachineType:L0Cache, version);
623          out_msg.DataBlk := cache_entry.DataBlk;
624          out_msg.Dirty := cache_entry.Dirty;
625          out_msg.MessageSize := MessageSizeType:Response_Data;
626
627          //cache_entry.Dirty := true;
628      }
629  }
630
631  action(h_stale_data_to_l0, "hs", desc="If not prefetch, send data to the L0 cache.") {
632      enqueue(bufferToL0_out, CoherenceMsg, l1_response_latency) {
633          assert(is_valid(cache_entry));
634
635          out_msg.addr := address;
636          out_msg.Class := CoherenceClass:STALE_DATA;
637          out_msg.Sender := machineID;
638          out_msg.Dest := createMachineID(MachineType:L0Cache, version);
639          out_msg.DataBlk := cache_entry.DataBlk;
640          out_msg.Dirty := cache_entry.Dirty;
641          out_msg.MessageSize := MessageSizeType:Response_Data;
642       }
643   }
644
645  action(i_allocateTBE, "i", desc="Allocate TBE (number of invalidates=0)") {
646    check_allocate(TBEs);
647    assert(is_valid(cache_entry));
648    TBEs.allocate(address);
649    set_tbe(TBEs[address]);
650    tbe.Dirty := cache_entry.Dirty;
651    tbe.DataBlk := cache_entry.DataBlk;
652  }
653
654  action(k_popL0RequestQueue, "k", desc="Pop mandatory queue.") {
655    messageBufferFromL0_in.dequeue(clockEdge());
656  }
657
658  action(l_popL2RequestQueue, "l",
659         desc="Pop incoming request queue and profile the delay within this virtual network") {
660    Tick delay := requestNetwork_in.dequeue(clockEdge());
661    profileMsgDelay(2, ticksToCycles(delay));
662  }
663
664  action(o_popL2ResponseQueue, "o",
665         desc="Pop Incoming Response queue and profile the delay within this virtual network") {
666    Tick delay := responseNetwork_in.dequeue(clockEdge());
667    profileMsgDelay(1, ticksToCycles(delay));
668  }
669
670  action(s_deallocateTBE, "s", desc="Deallocate TBE") {
671    TBEs.deallocate(address);
672    unset_tbe();
673  }
674
675  action(u_writeDataFromL0Request, "ureql0", desc="Write data to cache") {
676    peek(messageBufferFromL0_in, CoherenceMsg) {
677      assert(is_valid(cache_entry));
678      if (in_msg.Dirty) {
679          cache_entry.DataBlk := in_msg.DataBlk;
680          cache_entry.Dirty := in_msg.Dirty;
681      }
682    }
683  }
684
685  action(u_writeDataFromL2Response, "uresl2", desc="Write data to cache") {
686    peek(responseNetwork_in, ResponseMsg) {
687      assert(is_valid(cache_entry));
688      cache_entry.DataBlk := in_msg.DataBlk;
689    }
690  }
691
692  action(u_writeDataFromL0Response, "uresl0", desc="Write data to cache") {
693    peek(messageBufferFromL0_in, CoherenceMsg) {
694      assert(is_valid(cache_entry));
695      if (in_msg.Dirty) {
696          cache_entry.DataBlk := in_msg.DataBlk;
697          cache_entry.Dirty := in_msg.Dirty;
698      }
699    }
700  }
701
702  action(q_updateAckCount, "q", desc="Update ack count") {
703    peek(responseNetwork_in, ResponseMsg) {
704      assert(is_valid(tbe));
705      tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount;
706      APPEND_TRANSITION_COMMENT(in_msg.AckCount);
707      APPEND_TRANSITION_COMMENT(" p: ");
708      APPEND_TRANSITION_COMMENT(tbe.pendingAcks);
709    }
710  }
711
712  action(ff_deallocateCacheBlock, "\f",
713         desc="Deallocate L1 cache block.") {
714    if (cache.isTagPresent(address)) {
715      cache.deallocate(address);
716    }
717    unset_cache_entry();
718  }
719
720  action(oo_allocateCacheBlock, "\o", desc="Set cache tag equal to tag of block B.") {
721    if (is_invalid(cache_entry)) {
722      set_cache_entry(cache.allocate(address, new Entry));
723    }
724  }
725
726  action(z0_stallAndWaitL0Queue, "\z0", desc="recycle L0 request queue") {
727    stall_and_wait(messageBufferFromL0_in, address);
728  }
729
730  action(z2_stallAndWaitL2Queue, "\z2", desc="recycle L2 request queue") {
731    stall_and_wait(requestNetwork_in, address);
732  }
733
734  action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
735    wakeUpAllBuffers(address);
736  }
737
738  action(uu_profileMiss, "\um", desc="Profile the demand miss") {
739      ++cache.demand_misses;
740  }
741
742  action(uu_profileHit, "\uh", desc="Profile the demand hit") {
743      ++cache.demand_hits;
744  }
745
746
747  //*****************************************************
748  // TRANSITIONS
749  //*****************************************************
750
751  // Transitions for Load/Store/Replacement/WriteBack from transient states
752  transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK, S_IL0, M_IL0, E_IL0, MM_IL0},
753             {Load, Store, L1_Replacement}) {
754    z0_stallAndWaitL0Queue;
755  }
756
757  transition(I, Load, IS) {
758    oo_allocateCacheBlock;
759    i_allocateTBE;
760    a_issueGETS;
761    uu_profileMiss;
762    k_popL0RequestQueue;
763  }
764
765  transition(I, Store, IM) {
766    oo_allocateCacheBlock;
767    i_allocateTBE;
768    b_issueGETX;
769    uu_profileMiss;
770    k_popL0RequestQueue;
771  }
772
773  transition(I, Inv) {
774    fi_sendInvAck;
775    l_popL2RequestQueue;
776  }
777
778  // Transitions from Shared
779  transition({S,SS}, Load, S) {
780    h_data_to_l0;
781    uu_profileHit;
782    k_popL0RequestQueue;
783  }
784
785  transition(EE, Load, E) {
786    hh_xdata_to_l0;
787    uu_profileHit;
788    k_popL0RequestQueue;
789  }
790
791  transition(MM, Load, M) {
792    hh_xdata_to_l0;
793    uu_profileHit;
794    k_popL0RequestQueue;
795  }
796
797  transition({S,SS}, Store, SM) {
798    i_allocateTBE;
799    c_issueUPGRADE;
800    uu_profileMiss;
801    k_popL0RequestQueue;
802  }
803
804  transition(SS, L1_Replacement, I) {
805    ff_deallocateCacheBlock;
806  }
807
808  transition(S, {L0_Invalidate_Own, L0_Invalidate_Else}, S_IL0) {
809    forward_eviction_to_L0;
810  }
811
812  transition(SS, Inv, I) {
813    fi_sendInvAck;
814    ff_deallocateCacheBlock;
815    l_popL2RequestQueue;
816  }
817
818  // Transitions from Exclusive
819
820  transition({EE,MM}, Store, M) {
821    hh_xdata_to_l0;
822    uu_profileHit;
823    k_popL0RequestQueue;
824  }
825
826  transition(EE, L1_Replacement, M_I) {
827    // silent E replacement??
828    i_allocateTBE;
829    g_issuePUTX;   // send data, but hold in case forwarded request
830    ff_deallocateCacheBlock;
831  }
832
833  transition(EE, Inv, I) {
834    // don't send data
835    fi_sendInvAck;
836    ff_deallocateCacheBlock;
837    l_popL2RequestQueue;
838  }
839
840  transition(EE, Fwd_GETX, I) {
841    d_sendDataToRequestor;
842    ff_deallocateCacheBlock;
843    l_popL2RequestQueue;
844  }
845
846  transition(EE, Fwd_GETS, SS) {
847    d_sendDataToRequestor;
848    d2_sendDataToL2;
849    l_popL2RequestQueue;
850  }
851
852  transition(E, {L0_Invalidate_Own, L0_Invalidate_Else}, E_IL0) {
853    forward_eviction_to_L0;
854  }
855
856  // Transitions from Modified
857  transition(MM, L1_Replacement, M_I) {
858    i_allocateTBE;
859    g_issuePUTX;   // send data, but hold in case forwarded request
860    ff_deallocateCacheBlock;
861  }
862
863  transition({M,E}, WriteBack, MM) {
864    u_writeDataFromL0Request;
865    k_popL0RequestQueue;
866  }
867
868  transition(M_I, WB_Ack, I) {
869    s_deallocateTBE;
870    o_popL2ResponseQueue;
871    ff_deallocateCacheBlock;
872    kd_wakeUpDependents;
873  }
874
875  transition(MM, Inv, I) {
876    f_sendDataToL2;
877    ff_deallocateCacheBlock;
878    l_popL2RequestQueue;
879  }
880
881  transition(M_I, Inv, SINK_WB_ACK) {
882    ft_sendDataToL2_fromTBE;
883    l_popL2RequestQueue;
884  }
885
886  transition(MM, Fwd_GETX, I) {
887    d_sendDataToRequestor;
888    ff_deallocateCacheBlock;
889    l_popL2RequestQueue;
890  }
891
892  transition(MM, Fwd_GETS, SS) {
893    d_sendDataToRequestor;
894    d2_sendDataToL2;
895    l_popL2RequestQueue;
896  }
897
898  transition(M, {L0_Invalidate_Own, L0_Invalidate_Else}, M_IL0) {
899    forward_eviction_to_L0;
900  }
901
902  transition(M_I, Fwd_GETX, SINK_WB_ACK) {
903    dt_sendDataToRequestor_fromTBE;
904    l_popL2RequestQueue;
905  }
906
907  transition(M_I, Fwd_GETS, SINK_WB_ACK) {
908    dt_sendDataToRequestor_fromTBE;
909    d2t_sendDataToL2_fromTBE;
910    l_popL2RequestQueue;
911  }
912
913  // Transitions from IS
914  transition({IS,IS_I}, Inv, IS_I) {
915    fi_sendInvAck;
916    l_popL2RequestQueue;
917  }
918
919  transition(IS, Data_all_Acks, S) {
920    u_writeDataFromL2Response;
921    h_data_to_l0;
922    s_deallocateTBE;
923    o_popL2ResponseQueue;
924    kd_wakeUpDependents;
925  }
926
927  transition(IS_I, Data_all_Acks, I) {
928    u_writeDataFromL2Response;
929    h_stale_data_to_l0;
930    s_deallocateTBE;
931    ff_deallocateCacheBlock;
932    o_popL2ResponseQueue;
933    kd_wakeUpDependents;
934  }
935
936  transition(IS, DataS_fromL1, S) {
937    u_writeDataFromL2Response;
938    j_sendUnblock;
939    h_data_to_l0;
940    s_deallocateTBE;
941    o_popL2ResponseQueue;
942    kd_wakeUpDependents;
943  }
944
945  transition(IS_I, DataS_fromL1, I) {
946    u_writeDataFromL2Response;
947    j_sendUnblock;
948    h_stale_data_to_l0;
949    s_deallocateTBE;
950    ff_deallocateCacheBlock;
951    o_popL2ResponseQueue;
952    kd_wakeUpDependents;
953  }
954
955  // directory is blocked when sending exclusive data
956  transition({IS,IS_I}, Data_Exclusive, E) {
957    u_writeDataFromL2Response;
958    hh_xdata_to_l0;
959    jj_sendExclusiveUnblock;
960    s_deallocateTBE;
961    o_popL2ResponseQueue;
962    kd_wakeUpDependents;
963  }
964
965  // Transitions from IM
966  transition({IM,SM}, Inv, IM) {
967    fi_sendInvAck;
968    l_popL2RequestQueue;
969  }
970
971  transition(IM, Data, SM) {
972    u_writeDataFromL2Response;
973    q_updateAckCount;
974    o_popL2ResponseQueue;
975  }
976
977  transition(IM, Data_all_Acks, M) {
978    u_writeDataFromL2Response;
979    hh_xdata_to_l0;
980    jj_sendExclusiveUnblock;
981    s_deallocateTBE;
982    o_popL2ResponseQueue;
983    kd_wakeUpDependents;
984  }
985
986  transition({SM, IM}, Ack) {
987    q_updateAckCount;
988    o_popL2ResponseQueue;
989  }
990
991  transition(SM, Ack_all, M) {
992    jj_sendExclusiveUnblock;
993    hh_xdata_to_l0;
994    s_deallocateTBE;
995    o_popL2ResponseQueue;
996    kd_wakeUpDependents;
997  }
998
999  transition(SM, L0_Invalidate_Else, SM_IL0) {
1000    forward_eviction_to_L0;
1001  }
1002
1003  transition(SINK_WB_ACK, Inv){
1004    fi_sendInvAck;
1005    l_popL2RequestQueue;
1006  }
1007
1008  transition(SINK_WB_ACK, WB_Ack, I){
1009    s_deallocateTBE;
1010    o_popL2ResponseQueue;
1011    ff_deallocateCacheBlock;
1012    kd_wakeUpDependents;
1013  }
1014
1015  transition({M_IL0, E_IL0}, WriteBack, MM_IL0) {
1016    u_writeDataFromL0Request;
1017    k_popL0RequestQueue;
1018    kd_wakeUpDependents;
1019  }
1020
1021  transition({M_IL0, E_IL0}, L0_DataAck, MM) {
1022    u_writeDataFromL0Response;
1023    k_popL0RequestQueue;
1024    kd_wakeUpDependents;
1025  }
1026
1027  transition({M_IL0, MM_IL0}, L0_Ack, MM) {
1028    k_popL0RequestQueue;
1029    kd_wakeUpDependents;
1030  }
1031
1032  transition(E_IL0, L0_Ack, EE) {
1033    k_popL0RequestQueue;
1034    kd_wakeUpDependents;
1035  }
1036
1037  transition(S_IL0, L0_Ack, SS) {
1038    k_popL0RequestQueue;
1039    kd_wakeUpDependents;
1040  }
1041
1042  transition(SM_IL0, L0_Ack, IM) {
1043    k_popL0RequestQueue;
1044    kd_wakeUpDependents;
1045  }
1046
1047  transition({S_IL0, M_IL0, E_IL0, SM_IL0, SM}, L0_Invalidate_Own) {
1048    z0_stallAndWaitL0Queue;
1049  }
1050
1051  transition({S_IL0, M_IL0, E_IL0, SM_IL0}, L0_Invalidate_Else) {
1052    z2_stallAndWaitL2Queue;
1053  }
1054
1055  transition({S_IL0, M_IL0, E_IL0, MM_IL0}, {Inv, Fwd_GETX, Fwd_GETS}) {
1056    z2_stallAndWaitL2Queue;
1057  }
1058}
1059