ruby: cleaning up RubyQueue and RubyNetwork dprintfs
[gem5.git] / src / mem / protocol / MESI_CMP_directory-L2cache.sm
1
2 /*
3 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
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
30 /*
31 * $Id: MSI_MOSI_CMP_directory-L2cache.sm 1.12 05/01/19 15:55:40-06:00 beckmann@s0-28.cs.wisc.edu $
32 *
33 */
34
35 machine(L2Cache, "MESI Directory L2 Cache CMP")
36 : CacheMemory * L2cacheMemory,
37 int l2_request_latency = 2,
38 int l2_response_latency = 2,
39 int to_l1_latency = 1
40 {
41 // L2 BANK QUEUES
42 // From local bank of L2 cache TO the network
43 MessageBuffer DirRequestFromL2Cache, network="To", virtual_network="0", ordered="false"; // this L2 bank -> Memory
44 MessageBuffer L1RequestFromL2Cache, network="To", virtual_network="0", ordered="false"; // this L2 bank -> a local L1
45 MessageBuffer responseFromL2Cache, network="To", virtual_network="1", ordered="false"; // this L2 bank -> a local L1 || Memory
46
47 // FROM the network to this local bank of L2 cache
48 MessageBuffer unblockToL2Cache, network="From", virtual_network="2", ordered="false"; // a local L1 || Memory -> this L2 bank
49 MessageBuffer L1RequestToL2Cache, network="From", virtual_network="0", ordered="false"; // a local L1 -> this L2 bank
50 MessageBuffer responseToL2Cache, network="From", virtual_network="1", ordered="false"; // a local L1 || Memory -> this L2 bank
51 // MessageBuffer unblockToL2Cache, network="From", virtual_network="4", ordered="false"; // a local L1 || Memory -> this L2 bank
52
53 // STATES
54 enumeration(State, desc="L2 Cache states", default="L2Cache_State_NP") {
55 // Base states
56 NP, desc="Not present in either cache";
57 SS, desc="L2 cache entry Shared, also present in one or more L1s";
58 M, desc="L2 cache entry Modified, not present in any L1s", format="!b";
59 MT, desc="L2 cache entry Modified in a local L1, assume L2 copy stale", format="!b";
60
61 // L2 replacement
62 M_I, desc="L2 cache replacing, have all acks, sent dirty data to memory, waiting for ACK from memory";
63 MT_I, desc="L2 cache replacing, getting data from exclusive";
64 MCT_I, desc="L2 cache replacing, clean in L2, getting data or ack from exclusive";
65 I_I, desc="L2 replacing clean data, need to inv sharers and then drop data";
66 S_I, desc="L2 replacing dirty data, collecting acks from L1s";
67
68 // Transient States for fetching data from memory
69 ISS, desc="L2 idle, got single L1_GETS, issued memory fetch, have not seen response yet";
70 IS, desc="L2 idle, got L1_GET_INSTR or multiple L1_GETS, issued memory fetch, have not seen response yet";
71 IM, desc="L2 idle, got L1_GETX, issued memory fetch, have not seen response(s) yet";
72
73 // Blocking states
74 SS_MB, desc="Blocked for L1_GETX from SS";
75 MT_MB, desc="Blocked for L1_GETX from MT";
76 M_MB, desc="Blocked for L1_GETX from M";
77
78 MT_IIB, desc="Blocked for L1_GETS from MT, waiting for unblock and data";
79 MT_IB, desc="Blocked for L1_GETS from MT, got unblock, waiting for data";
80 MT_SB, desc="Blocked for L1_GETS from MT, got data, waiting for unblock";
81
82 }
83
84 // EVENTS
85 enumeration(Event, desc="L2 Cache events") {
86 // L2 events
87
88 // events initiated by the local L1s
89 L1_GET_INSTR, desc="a L1I GET INSTR request for a block maped to us";
90 L1_GETS, desc="a L1D GETS request for a block maped to us";
91 L1_GETX, desc="a L1D GETX request for a block maped to us";
92 L1_UPGRADE, desc="a L1D GETX request for a block maped to us";
93
94 L1_PUTX, desc="L1 replacing data";
95 L1_PUTX_old, desc="L1 replacing data, but no longer sharer";
96
97 Fwd_L1_GETX, desc="L1 did not have data, so we supply";
98 Fwd_L1_GETS, desc="L1 did not have data, so we supply";
99 Fwd_L1_GET_INSTR, desc="L1 did not have data, so we supply";
100
101 // events initiated by this L2
102 L2_Replacement, desc="L2 Replacement", format="!r";
103 L2_Replacement_clean, desc="L2 Replacement, but data is clean", format="!r";
104
105 // events from memory controller
106 Mem_Data, desc="data from memory", format="!r";
107 Mem_Ack, desc="ack from memory", format="!r";
108
109 // M->S data writeback
110 WB_Data, desc="data from L1";
111 WB_Data_clean, desc="clean data from L1";
112 Ack, desc="writeback ack";
113 Ack_all, desc="writeback ack";
114
115 Unblock, desc="Unblock from L1 requestor";
116 Unblock_Cancel, desc="Unblock from L1 requestor (FOR XACT MEMORY)";
117 Exclusive_Unblock, desc="Unblock from L1 requestor";
118
119 MEM_Inv, desc="Invalidation from directory";
120
121 }
122
123 // TYPES
124
125 // CacheEntry
126 structure(Entry, desc="...", interface="AbstractCacheEntry") {
127 State CacheState, desc="cache state";
128 NetDest Sharers, desc="tracks the L1 shares on-chip";
129 MachineID Exclusive, desc="Exclusive holder of block";
130 DataBlock DataBlk, desc="data for the block";
131 bool Dirty, default="false", desc="data is dirty";
132 }
133
134 // TBE fields
135 structure(TBE, desc="...") {
136 Address Address, desc="Physical address for this TBE";
137 State TBEState, desc="Transient state";
138 DataBlock DataBlk, desc="Buffer for the data block";
139 bool Dirty, default="false", desc="Data is Dirty";
140
141 NetDest L1_GetS_IDs, desc="Set of the internal processors that want the block in shared state";
142 MachineID L1_GetX_ID, desc="ID of the L1 cache to forward the block to once we get a response";
143 bool isPrefetch, desc="Set if this was caused by a prefetch";
144
145 int pendingAcks, desc="number of pending acks for invalidates during writeback";
146 }
147
148 external_type(TBETable) {
149 TBE lookup(Address);
150 void allocate(Address);
151 void deallocate(Address);
152 bool isPresent(Address);
153 }
154
155 TBETable L2_TBEs, template_hack="<L2Cache_TBE>";
156
157 void set_cache_entry(AbstractCacheEntry a);
158 void unset_cache_entry();
159 void set_tbe(TBE a);
160 void unset_tbe();
161
162 // inclusive cache, returns L2 entries only
163 Entry getCacheEntry(Address addr), return_by_pointer="yes" {
164 return static_cast(Entry, "pointer", L2cacheMemory[addr]);
165 }
166
167 std::string getCoherenceRequestTypeStr(CoherenceRequestType type) {
168 return CoherenceRequestType_to_string(type);
169 }
170
171 bool isOneSharerLeft(Address addr, MachineID requestor, Entry cache_entry) {
172 assert(is_valid(cache_entry));
173 assert(cache_entry.Sharers.isElement(requestor));
174 return (cache_entry.Sharers.count() == 1);
175 }
176
177 bool isSharer(Address addr, MachineID requestor, Entry cache_entry) {
178 if (is_valid(cache_entry)) {
179 return cache_entry.Sharers.isElement(requestor);
180 } else {
181 return false;
182 }
183 }
184
185 void addSharer(Address addr, MachineID requestor, Entry cache_entry) {
186 assert(is_valid(cache_entry));
187 DPRINTF(RubySlicc, "machineID: %s, requestor: %s, address: %s\n",
188 machineID, requestor, addr);
189 cache_entry.Sharers.add(requestor);
190 }
191
192 State getState(TBE tbe, Entry cache_entry, Address addr) {
193 if(is_valid(tbe)) {
194 return tbe.TBEState;
195 } else if (is_valid(cache_entry)) {
196 return cache_entry.CacheState;
197 }
198 return State:NP;
199 }
200
201 std::string getStateStr(TBE tbe, Entry cache_entry, Address addr) {
202 return L2Cache_State_to_string(getState(tbe, cache_entry, addr));
203 }
204
205 // when is this called
206 void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
207
208 // MUST CHANGE
209 if (is_valid(tbe)) {
210 tbe.TBEState := state;
211 }
212
213 if (is_valid(cache_entry)) {
214 cache_entry.CacheState := state;
215
216 // Set permission
217 if (state == State:SS ) {
218 cache_entry.changePermission(AccessPermission:Read_Only);
219 } else if (state == State:M) {
220 cache_entry.changePermission(AccessPermission:Read_Write);
221 } else if (state == State:MT) {
222 cache_entry.changePermission(AccessPermission:Stale);
223 } else {
224 cache_entry.changePermission(AccessPermission:Busy);
225 }
226 }
227 }
228
229 Event L1Cache_request_type_to_event(CoherenceRequestType type, Address addr,
230 MachineID requestor, Entry cache_entry) {
231 if(type == CoherenceRequestType:GETS) {
232 return Event:L1_GETS;
233 } else if(type == CoherenceRequestType:GET_INSTR) {
234 return Event:L1_GET_INSTR;
235 } else if (type == CoherenceRequestType:GETX) {
236 return Event:L1_GETX;
237 } else if (type == CoherenceRequestType:UPGRADE) {
238 if ( is_valid(cache_entry) && cache_entry.Sharers.isElement(requestor) ) {
239 return Event:L1_UPGRADE;
240 } else {
241 return Event:L1_GETX;
242 }
243 } else if (type == CoherenceRequestType:PUTX) {
244 if (isSharer(addr, requestor, cache_entry)) {
245 return Event:L1_PUTX;
246 } else {
247 return Event:L1_PUTX_old;
248 }
249 } else {
250 DPRINTF(RubySlicc, "address: %s, Request Type: %s\n", addr, type);
251 error("Invalid L1 forwarded request type");
252 }
253 }
254
255 int getPendingAcks(TBE tbe) {
256 return tbe.pendingAcks;
257 }
258
259 bool isDirty(Entry cache_entry) {
260 assert(is_valid(cache_entry));
261 return cache_entry.Dirty;
262 }
263
264 // ** OUT_PORTS **
265
266 out_port(L1RequestIntraChipL2Network_out, RequestMsg, L1RequestFromL2Cache);
267 out_port(DirRequestIntraChipL2Network_out, RequestMsg, DirRequestFromL2Cache);
268 out_port(responseIntraChipL2Network_out, ResponseMsg, responseFromL2Cache);
269
270
271 in_port(L1unblockNetwork_in, ResponseMsg, unblockToL2Cache) {
272 if(L1unblockNetwork_in.isReady()) {
273 peek(L1unblockNetwork_in, ResponseMsg) {
274 Entry cache_entry := getCacheEntry(in_msg.Address);
275 TBE tbe := L2_TBEs[in_msg.Address];
276 DPRINTF(RubySlicc, "Addr: %s State: %s Sender: %s Type: %s Dest: %s\n",
277 in_msg.Address, getState(tbe, cache_entry, in_msg.Address),
278 in_msg.Sender, in_msg.Type, in_msg.Destination);
279
280 assert(in_msg.Destination.isElement(machineID));
281 if (in_msg.Type == CoherenceResponseType:EXCLUSIVE_UNBLOCK) {
282 trigger(Event:Exclusive_Unblock, in_msg.Address, cache_entry, tbe);
283 } else if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
284 trigger(Event:Unblock, in_msg.Address, cache_entry, tbe);
285 } else {
286 error("unknown unblock message");
287 }
288 }
289 }
290 }
291
292 // Response IntraChip L2 Network - response msg to this particular L2 bank
293 in_port(responseIntraChipL2Network_in, ResponseMsg, responseToL2Cache) {
294 if (responseIntraChipL2Network_in.isReady()) {
295 peek(responseIntraChipL2Network_in, ResponseMsg) {
296 // test wether it's from a local L1 or an off chip source
297 assert(in_msg.Destination.isElement(machineID));
298 Entry cache_entry := getCacheEntry(in_msg.Address);
299 TBE tbe := L2_TBEs[in_msg.Address];
300
301 if(machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) {
302 if(in_msg.Type == CoherenceResponseType:DATA) {
303 if (in_msg.Dirty) {
304 trigger(Event:WB_Data, in_msg.Address, cache_entry, tbe);
305 } else {
306 trigger(Event:WB_Data_clean, in_msg.Address, cache_entry, tbe);
307 }
308 } else if (in_msg.Type == CoherenceResponseType:ACK) {
309 if ((getPendingAcks(tbe) - in_msg.AckCount) == 0) {
310 trigger(Event:Ack_all, in_msg.Address, cache_entry, tbe);
311 } else {
312 trigger(Event:Ack, in_msg.Address, cache_entry, tbe);
313 }
314 } else {
315 error("unknown message type");
316 }
317
318 } else { // external message
319 if(in_msg.Type == CoherenceResponseType:MEMORY_DATA) {
320 // L2 now has data and all off-chip acks
321 trigger(Event:Mem_Data, in_msg.Address, cache_entry, tbe);
322 } else if(in_msg.Type == CoherenceResponseType:MEMORY_ACK) {
323 // L2 now has data and all off-chip acks
324 trigger(Event:Mem_Ack, in_msg.Address, cache_entry, tbe);
325 } else if(in_msg.Type == CoherenceResponseType:INV) {
326 // L2 now has data and all off-chip acks
327 trigger(Event:MEM_Inv, in_msg.Address, cache_entry, tbe);
328 } else {
329 error("unknown message type");
330 }
331 }
332 }
333 } // if not ready, do nothing
334 }
335
336 // L1 Request
337 in_port(L1RequestIntraChipL2Network_in, RequestMsg, L1RequestToL2Cache) {
338 if(L1RequestIntraChipL2Network_in.isReady()) {
339 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
340 Entry cache_entry := getCacheEntry(in_msg.Address);
341 TBE tbe := L2_TBEs[in_msg.Address];
342
343 DPRINTF(RubySlicc, "Addr: %s State: %s Req: %s Type: %s Dest: %s\n",
344 in_msg.Address, getState(tbe, cache_entry, in_msg.Address),
345 in_msg.Requestor, in_msg.Type, in_msg.Destination);
346
347 assert(machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache);
348 assert(in_msg.Destination.isElement(machineID));
349
350 if (is_valid(cache_entry)) {
351 // The L2 contains the block, so proceeded with handling the request
352 trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address,
353 in_msg.Requestor, cache_entry),
354 in_msg.Address, cache_entry, tbe);
355 } else {
356 if (L2cacheMemory.cacheAvail(in_msg.Address)) {
357 // L2 does't have the line, but we have space for it in the L2
358 trigger(L1Cache_request_type_to_event(in_msg.Type, in_msg.Address,
359 in_msg.Requestor, cache_entry),
360 in_msg.Address, cache_entry, tbe);
361 } else {
362 // No room in the L2, so we need to make room before handling the request
363 Entry L2cache_entry := getCacheEntry(L2cacheMemory.cacheProbe(in_msg.Address));
364 if (isDirty(L2cache_entry)) {
365 trigger(Event:L2_Replacement, L2cacheMemory.cacheProbe(in_msg.Address),
366 L2cache_entry, L2_TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]);
367 } else {
368 trigger(Event:L2_Replacement_clean, L2cacheMemory.cacheProbe(in_msg.Address),
369 L2cache_entry, L2_TBEs[L2cacheMemory.cacheProbe(in_msg.Address)]);
370 }
371 }
372 }
373 }
374 }
375 }
376
377
378 // ACTIONS
379
380 action(a_issueFetchToMemory, "a", desc="fetch data from memory") {
381 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
382 enqueue(DirRequestIntraChipL2Network_out, RequestMsg, latency=l2_request_latency) {
383 out_msg.Address := address;
384 out_msg.Type := CoherenceRequestType:GETS;
385 out_msg.Requestor := machineID;
386 out_msg.Destination.add(map_Address_to_Directory(address));
387 out_msg.MessageSize := MessageSizeType:Control;
388 }
389 }
390 }
391
392 action(b_forwardRequestToExclusive, "b", desc="Forward request to the exclusive L1") {
393 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
394 enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) {
395 assert(is_valid(cache_entry));
396 out_msg.Address := address;
397 out_msg.Type := in_msg.Type;
398 out_msg.Requestor := in_msg.Requestor;
399 out_msg.Destination.add(cache_entry.Exclusive);
400 out_msg.MessageSize := MessageSizeType:Request_Control;
401 }
402 }
403 }
404
405 action(c_exclusiveReplacement, "c", desc="Send data to memory") {
406 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
407 assert(is_valid(cache_entry));
408 out_msg.Address := address;
409 out_msg.Type := CoherenceResponseType:MEMORY_DATA;
410 out_msg.Sender := machineID;
411 out_msg.Destination.add(map_Address_to_Directory(address));
412 out_msg.DataBlk := cache_entry.DataBlk;
413 out_msg.Dirty := cache_entry.Dirty;
414 out_msg.MessageSize := MessageSizeType:Response_Data;
415 }
416 }
417
418 action(c_exclusiveCleanReplacement, "cc", desc="Send ack to memory for clean replacement") {
419 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
420 out_msg.Address := address;
421 out_msg.Type := CoherenceResponseType:ACK;
422 out_msg.Sender := machineID;
423 out_msg.Destination.add(map_Address_to_Directory(address));
424 out_msg.MessageSize := MessageSizeType:Response_Control;
425 }
426 }
427
428 action(ct_exclusiveReplacementFromTBE, "ct", desc="Send data to memory") {
429 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
430 assert(is_valid(tbe));
431 out_msg.Address := address;
432 out_msg.Type := CoherenceResponseType:MEMORY_DATA;
433 out_msg.Sender := machineID;
434 out_msg.Destination.add(map_Address_to_Directory(address));
435 out_msg.DataBlk := tbe.DataBlk;
436 out_msg.Dirty := tbe.Dirty;
437 out_msg.MessageSize := MessageSizeType:Response_Data;
438 }
439 }
440
441 action(d_sendDataToRequestor, "d", desc="Send data from cache to reqeustor") {
442 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
443 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
444 assert(is_valid(cache_entry));
445 out_msg.Address := address;
446 out_msg.Type := CoherenceResponseType:DATA;
447 out_msg.Sender := machineID;
448 out_msg.Destination.add(in_msg.Requestor);
449 out_msg.DataBlk := cache_entry.DataBlk;
450 out_msg.Dirty := cache_entry.Dirty;
451 out_msg.MessageSize := MessageSizeType:Response_Data;
452
453 out_msg.AckCount := 0 - cache_entry.Sharers.count();
454 if (cache_entry.Sharers.isElement(in_msg.Requestor)) {
455 out_msg.AckCount := out_msg.AckCount + 1;
456 }
457 }
458 }
459 }
460
461 action(dd_sendExclusiveDataToRequestor, "dd", desc="Send data from cache to reqeustor") {
462 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
463 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
464 assert(is_valid(cache_entry));
465 out_msg.Address := address;
466 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
467 out_msg.Sender := machineID;
468 out_msg.Destination.add(in_msg.Requestor);
469 out_msg.DataBlk := cache_entry.DataBlk;
470 out_msg.Dirty := cache_entry.Dirty;
471 out_msg.MessageSize := MessageSizeType:Response_Data;
472
473 out_msg.AckCount := 0 - cache_entry.Sharers.count();
474 if (cache_entry.Sharers.isElement(in_msg.Requestor)) {
475 out_msg.AckCount := out_msg.AckCount + 1;
476 }
477 }
478 }
479 }
480
481 action(ds_sendSharedDataToRequestor, "ds", desc="Send data from cache to reqeustor") {
482 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
483 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=l2_response_latency) {
484 assert(is_valid(cache_entry));
485 out_msg.Address := address;
486 out_msg.Type := CoherenceResponseType:DATA;
487 out_msg.Sender := machineID;
488 out_msg.Destination.add(in_msg.Requestor);
489 out_msg.DataBlk := cache_entry.DataBlk;
490 out_msg.Dirty := cache_entry.Dirty;
491 out_msg.MessageSize := MessageSizeType:Response_Data;
492 out_msg.AckCount := 0;
493 }
494 }
495 }
496
497 action(e_sendDataToGetSRequestors, "e", desc="Send data from cache to all GetS IDs") {
498 assert(is_valid(tbe));
499 assert(tbe.L1_GetS_IDs.count() > 0);
500 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) {
501 assert(is_valid(cache_entry));
502 out_msg.Address := address;
503 out_msg.Type := CoherenceResponseType:DATA;
504 out_msg.Sender := machineID;
505 out_msg.Destination := tbe.L1_GetS_IDs; // internal nodes
506 out_msg.DataBlk := cache_entry.DataBlk;
507 out_msg.Dirty := cache_entry.Dirty;
508 out_msg.MessageSize := MessageSizeType:Response_Data;
509 }
510 }
511
512 action(ex_sendExclusiveDataToGetSRequestors, "ex", desc="Send data from cache to all GetS IDs") {
513 assert(is_valid(tbe));
514 assert(tbe.L1_GetS_IDs.count() == 1);
515 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) {
516 assert(is_valid(cache_entry));
517 out_msg.Address := address;
518 out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
519 out_msg.Sender := machineID;
520 out_msg.Destination := tbe.L1_GetS_IDs; // internal nodes
521 out_msg.DataBlk := cache_entry.DataBlk;
522 out_msg.Dirty := cache_entry.Dirty;
523 out_msg.MessageSize := MessageSizeType:Response_Data;
524 }
525 }
526
527 action(ee_sendDataToGetXRequestor, "ee", desc="Send data from cache to GetX ID") {
528 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) {
529 assert(is_valid(tbe));
530 assert(is_valid(cache_entry));
531 out_msg.Address := address;
532 out_msg.Type := CoherenceResponseType:DATA;
533 out_msg.Sender := machineID;
534 out_msg.Destination.add(tbe.L1_GetX_ID);
535 DPRINTF(RubySlicc, "%s\n", out_msg.Destination);
536 out_msg.DataBlk := cache_entry.DataBlk;
537 out_msg.Dirty := cache_entry.Dirty;
538 DPRINTF(RubySlicc, "Address: %s, Destination: %s, DataBlock: %s\n",
539 out_msg.Address, out_msg.Destination, out_msg.DataBlk);
540 out_msg.MessageSize := MessageSizeType:Response_Data;
541 }
542 }
543
544 action(f_sendInvToSharers, "f", desc="invalidate sharers for L2 replacement") {
545 enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) {
546 assert(is_valid(cache_entry));
547 out_msg.Address := address;
548 out_msg.Type := CoherenceRequestType:INV;
549 out_msg.Requestor := machineID;
550 out_msg.Destination := cache_entry.Sharers;
551 out_msg.MessageSize := MessageSizeType:Request_Control;
552 }
553 }
554
555 action(fw_sendFwdInvToSharers, "fw", desc="invalidate sharers for request") {
556 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
557 enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) {
558 assert(is_valid(cache_entry));
559 out_msg.Address := address;
560 out_msg.Type := CoherenceRequestType:INV;
561 out_msg.Requestor := in_msg.Requestor;
562 out_msg.Destination := cache_entry.Sharers;
563 out_msg.MessageSize := MessageSizeType:Request_Control;
564 }
565 }
566 }
567
568 action(fwm_sendFwdInvToSharersMinusRequestor, "fwm", desc="invalidate sharers for request, requestor is sharer") {
569 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
570 enqueue(L1RequestIntraChipL2Network_out, RequestMsg, latency=to_l1_latency) {
571 assert(is_valid(cache_entry));
572 out_msg.Address := address;
573 out_msg.Type := CoherenceRequestType:INV;
574 out_msg.Requestor := in_msg.Requestor;
575 out_msg.Destination := cache_entry.Sharers;
576 out_msg.Destination.remove(in_msg.Requestor);
577 out_msg.MessageSize := MessageSizeType:Request_Control;
578 }
579 }
580 }
581
582 // OTHER ACTIONS
583 action(i_allocateTBE, "i", desc="Allocate TBE for internal/external request(isPrefetch=0, number of invalidates=0)") {
584 check_allocate(L2_TBEs);
585 assert(is_valid(cache_entry));
586 L2_TBEs.allocate(address);
587 set_tbe(L2_TBEs[address]);
588 tbe.L1_GetS_IDs.clear();
589 tbe.DataBlk := cache_entry.DataBlk;
590 tbe.Dirty := cache_entry.Dirty;
591 tbe.pendingAcks := cache_entry.Sharers.count();
592 }
593
594 action(s_deallocateTBE, "s", desc="Deallocate external TBE") {
595 L2_TBEs.deallocate(address);
596 unset_tbe();
597 }
598
599 action(jj_popL1RequestQueue, "\j", desc="Pop incoming L1 request queue") {
600 profileMsgDelay(0, L1RequestIntraChipL2Network_in.dequeue_getDelayCycles());
601 }
602
603 action(k_popUnblockQueue, "k", desc="Pop incoming unblock queue") {
604 profileMsgDelay(0, L1unblockNetwork_in.dequeue_getDelayCycles());
605 }
606
607 action(o_popIncomingResponseQueue, "o", desc="Pop Incoming Response queue") {
608 profileMsgDelay(3, responseIntraChipL2Network_in.dequeue_getDelayCycles());
609 }
610
611 action(m_writeDataToCache, "m", desc="Write data from response queue to cache") {
612 peek(responseIntraChipL2Network_in, ResponseMsg) {
613 assert(is_valid(cache_entry));
614 cache_entry.DataBlk := in_msg.DataBlk;
615 cache_entry.Dirty := in_msg.Dirty;
616 }
617 }
618
619 action(mr_writeDataToCacheFromRequest, "mr", desc="Write data from response queue to cache") {
620 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
621 assert(is_valid(cache_entry));
622 cache_entry.DataBlk := in_msg.DataBlk;
623 cache_entry.Dirty := in_msg.Dirty;
624 }
625 }
626
627 action(q_updateAck, "q", desc="update pending ack count") {
628 peek(responseIntraChipL2Network_in, ResponseMsg) {
629 assert(is_valid(tbe));
630 tbe.pendingAcks := tbe.pendingAcks - in_msg.AckCount;
631 APPEND_TRANSITION_COMMENT(in_msg.AckCount);
632 APPEND_TRANSITION_COMMENT(" p: ");
633 APPEND_TRANSITION_COMMENT(tbe.pendingAcks);
634 }
635 }
636
637 action(qq_writeDataToTBE, "\qq", desc="Write data from response queue to TBE") {
638 peek(responseIntraChipL2Network_in, ResponseMsg) {
639 assert(is_valid(tbe));
640 tbe.DataBlk := in_msg.DataBlk;
641 tbe.Dirty := in_msg.Dirty;
642 }
643 }
644
645 action(z_stall, "z", desc="Stall") {
646 }
647
648 action(ss_recordGetSL1ID, "\s", desc="Record L1 GetS for load response") {
649 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
650 assert(is_valid(tbe));
651 tbe.L1_GetS_IDs.add(in_msg.Requestor);
652 }
653 }
654
655 action(xx_recordGetXL1ID, "\x", desc="Record L1 GetX for store response") {
656 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
657 assert(is_valid(tbe));
658 tbe.L1_GetX_ID := in_msg.Requestor;
659 }
660 }
661
662 action(set_setMRU, "\set", desc="set the MRU entry") {
663 L2cacheMemory.setMRU(address);
664 }
665
666 action(qq_allocateL2CacheBlock, "\q", desc="Set L2 cache tag equal to tag of block B.") {
667 if (is_invalid(cache_entry)) {
668 set_cache_entry(L2cacheMemory.allocate(address, new Entry));
669 }
670 }
671
672 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") {
673 L2cacheMemory.deallocate(address);
674 unset_cache_entry();
675 }
676
677 action(t_sendWBAck, "t", desc="Send writeback ACK") {
678 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
679 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) {
680 out_msg.Address := address;
681 out_msg.Type := CoherenceResponseType:WB_ACK;
682 out_msg.Sender := machineID;
683 out_msg.Destination.add(in_msg.Requestor);
684 out_msg.MessageSize := MessageSizeType:Response_Control;
685 }
686 }
687 }
688
689 action(ts_sendInvAckToUpgrader, "ts", desc="Send ACK to upgrader") {
690 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
691 enqueue(responseIntraChipL2Network_out, ResponseMsg, latency=to_l1_latency) {
692 assert(is_valid(cache_entry));
693 out_msg.Address := address;
694 out_msg.Type := CoherenceResponseType:ACK;
695 out_msg.Sender := machineID;
696 out_msg.Destination.add(in_msg.Requestor);
697 out_msg.MessageSize := MessageSizeType:Response_Control;
698 // upgrader doesn't get ack from itself, hence the + 1
699 out_msg.AckCount := 0 - cache_entry.Sharers.count() + 1;
700 }
701 }
702 }
703
704 action(uu_profileMiss, "\u", desc="Profile the demand miss") {
705 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
706 //profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, L1CacheMachIDToProcessorNum(in_msg.Requestor));
707 }
708 }
709
710 action(ww_profileMissNoDir, "\w", desc="Profile this transition at the L2 because Dir won't see the request") {
711 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
712 // profile_request(in_msg.L1CacheStateStr, getStateStr(address), "NA", getCoherenceRequestTypeStr(in_msg.Type));
713 }
714 }
715
716 action(nn_addSharer, "\n", desc="Add L1 sharer to list") {
717 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
718 assert(is_valid(cache_entry));
719 addSharer(address, in_msg.Requestor, cache_entry);
720 APPEND_TRANSITION_COMMENT( cache_entry.Sharers );
721 }
722 }
723
724 action(nnu_addSharerFromUnblock, "\nu", desc="Add L1 sharer to list") {
725 peek(L1unblockNetwork_in, ResponseMsg) {
726 assert(is_valid(cache_entry));
727 addSharer(address, in_msg.Sender, cache_entry);
728 }
729 }
730
731 action(kk_removeRequestSharer, "\k", desc="Remove L1 Request sharer from list") {
732 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
733 assert(is_valid(cache_entry));
734 cache_entry.Sharers.remove(in_msg.Requestor);
735 }
736 }
737
738 action(ll_clearSharers, "\l", desc="Remove all L1 sharers from list") {
739 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
740 assert(is_valid(cache_entry));
741 cache_entry.Sharers.clear();
742 }
743 }
744
745 action(mm_markExclusive, "\m", desc="set the exclusive owner") {
746 peek(L1RequestIntraChipL2Network_in, RequestMsg) {
747 assert(is_valid(cache_entry));
748 cache_entry.Sharers.clear();
749 cache_entry.Exclusive := in_msg.Requestor;
750 addSharer(address, in_msg.Requestor, cache_entry);
751 }
752 }
753
754 action(mmu_markExclusiveFromUnblock, "\mu", desc="set the exclusive owner") {
755 peek(L1unblockNetwork_in, ResponseMsg) {
756 assert(is_valid(cache_entry));
757 cache_entry.Sharers.clear();
758 cache_entry.Exclusive := in_msg.Sender;
759 addSharer(address, in_msg.Sender, cache_entry);
760 }
761 }
762
763 action(zz_recycleL1RequestQueue, "zz", desc="recycle L1 request queue") {
764 L1RequestIntraChipL2Network_in.recycle();
765 }
766
767 action(zn_recycleResponseNetwork, "zn", desc="recycle memory request") {
768 responseIntraChipL2Network_in.recycle();
769 }
770
771
772 //*****************************************************
773 // TRANSITIONS
774 //*****************************************************
775
776
777 //===============================================
778 // BASE STATE - I
779
780 // Transitions from I (Idle)
781 transition({NP, IS, ISS, IM, SS, M, M_I, I_I, S_I, M_MB, MT_IB, MT_SB}, L1_PUTX) {
782 t_sendWBAck;
783 jj_popL1RequestQueue;
784 }
785
786 transition({NP, SS, M, MT, M_I, I_I, S_I, IS, ISS, IM, M_MB, MT_IB, MT_SB}, L1_PUTX_old) {
787 t_sendWBAck;
788 jj_popL1RequestQueue;
789 }
790
791 transition({IM, IS, ISS, SS_MB, M_MB, MT_MB, MT_IIB, MT_IB, MT_SB}, {L2_Replacement, L2_Replacement_clean}) {
792 zz_recycleL1RequestQueue;
793 }
794
795 transition({IM, IS, ISS, SS_MB, M_MB, MT_MB, MT_IIB, MT_IB, MT_SB}, MEM_Inv) {
796 zn_recycleResponseNetwork;
797 }
798
799 transition({S_I, M_I, MT_I}, MEM_Inv) {
800 o_popIncomingResponseQueue;
801 }
802
803
804 transition({SS_MB, M_MB, MT_MB, MT_IIB, MT_IB, MT_SB}, {L1_GETS, L1_GET_INSTR, L1_GETX, L1_UPGRADE}) {
805 zz_recycleL1RequestQueue;
806 }
807
808
809 transition(NP, L1_GETS, ISS) {
810 qq_allocateL2CacheBlock;
811 ll_clearSharers;
812 nn_addSharer;
813 i_allocateTBE;
814 ss_recordGetSL1ID;
815 a_issueFetchToMemory;
816 uu_profileMiss;
817 jj_popL1RequestQueue;
818 }
819
820 transition(NP, L1_GET_INSTR, IS) {
821 qq_allocateL2CacheBlock;
822 ll_clearSharers;
823 nn_addSharer;
824 i_allocateTBE;
825 ss_recordGetSL1ID;
826 a_issueFetchToMemory;
827 uu_profileMiss;
828 jj_popL1RequestQueue;
829 }
830
831 transition(NP, L1_GETX, IM) {
832 qq_allocateL2CacheBlock;
833 ll_clearSharers;
834 // nn_addSharer;
835 i_allocateTBE;
836 xx_recordGetXL1ID;
837 a_issueFetchToMemory;
838 uu_profileMiss;
839 jj_popL1RequestQueue;
840 }
841
842
843 // transitions from IS/IM
844
845 transition(ISS, Mem_Data, MT_MB) {
846 m_writeDataToCache;
847 ex_sendExclusiveDataToGetSRequestors;
848 s_deallocateTBE;
849 o_popIncomingResponseQueue;
850 }
851
852 transition(IS, Mem_Data, SS) {
853 m_writeDataToCache;
854 e_sendDataToGetSRequestors;
855 s_deallocateTBE;
856 o_popIncomingResponseQueue;
857 }
858
859 transition(IM, Mem_Data, MT_MB) {
860 m_writeDataToCache;
861 ee_sendDataToGetXRequestor;
862 s_deallocateTBE;
863 o_popIncomingResponseQueue;
864 }
865
866 transition({IS, ISS}, {L1_GETS, L1_GET_INSTR}, IS) {
867 nn_addSharer;
868 ss_recordGetSL1ID;
869 uu_profileMiss;
870 jj_popL1RequestQueue;
871 }
872
873 transition({IS, ISS}, L1_GETX) {
874 zz_recycleL1RequestQueue;
875 }
876
877 transition(IM, {L1_GETX, L1_GETS, L1_GET_INSTR}) {
878 zz_recycleL1RequestQueue;
879 }
880
881 // transitions from SS
882 transition(SS, {L1_GETS, L1_GET_INSTR}) {
883 ds_sendSharedDataToRequestor;
884 nn_addSharer;
885 uu_profileMiss;
886 set_setMRU;
887 jj_popL1RequestQueue;
888 }
889
890
891 transition(SS, L1_GETX, SS_MB) {
892 d_sendDataToRequestor;
893 // fw_sendFwdInvToSharers;
894 fwm_sendFwdInvToSharersMinusRequestor;
895 uu_profileMiss;
896 set_setMRU;
897 jj_popL1RequestQueue;
898 }
899
900 transition(SS, L1_UPGRADE, SS_MB) {
901 fwm_sendFwdInvToSharersMinusRequestor;
902 ts_sendInvAckToUpgrader;
903 uu_profileMiss;
904 set_setMRU;
905 jj_popL1RequestQueue;
906 }
907
908 transition(SS, L2_Replacement_clean, I_I) {
909 i_allocateTBE;
910 f_sendInvToSharers;
911 rr_deallocateL2CacheBlock;
912 }
913
914 transition(SS, {L2_Replacement, MEM_Inv}, S_I) {
915 i_allocateTBE;
916 f_sendInvToSharers;
917 rr_deallocateL2CacheBlock;
918 }
919
920
921 transition(M, L1_GETX, MT_MB) {
922 d_sendDataToRequestor;
923 uu_profileMiss;
924 set_setMRU;
925 jj_popL1RequestQueue;
926 }
927
928 transition(M, L1_GET_INSTR, SS) {
929 d_sendDataToRequestor;
930 nn_addSharer;
931 uu_profileMiss;
932 set_setMRU;
933 jj_popL1RequestQueue;
934 }
935
936 transition(M, L1_GETS, MT_MB) {
937 dd_sendExclusiveDataToRequestor;
938 uu_profileMiss;
939 set_setMRU;
940 jj_popL1RequestQueue;
941 }
942
943 transition(M, {L2_Replacement, MEM_Inv}, M_I) {
944 i_allocateTBE;
945 c_exclusiveReplacement;
946 rr_deallocateL2CacheBlock;
947 }
948
949 transition(M, L2_Replacement_clean, M_I) {
950 i_allocateTBE;
951 c_exclusiveCleanReplacement;
952 rr_deallocateL2CacheBlock;
953 }
954
955
956 // transitions from MT
957
958 transition(MT, L1_GETX, MT_MB) {
959 b_forwardRequestToExclusive;
960 uu_profileMiss;
961 set_setMRU;
962 jj_popL1RequestQueue;
963 }
964
965
966 transition(MT, {L1_GETS, L1_GET_INSTR}, MT_IIB) {
967 b_forwardRequestToExclusive;
968 uu_profileMiss;
969 set_setMRU;
970 jj_popL1RequestQueue;
971 }
972
973 transition(MT, {L2_Replacement, MEM_Inv}, MT_I) {
974 i_allocateTBE;
975 f_sendInvToSharers;
976 rr_deallocateL2CacheBlock;
977 }
978
979 transition(MT, L2_Replacement_clean, MCT_I) {
980 i_allocateTBE;
981 f_sendInvToSharers;
982 rr_deallocateL2CacheBlock;
983 }
984
985 transition(MT, L1_PUTX, M) {
986 ll_clearSharers;
987 mr_writeDataToCacheFromRequest;
988 t_sendWBAck;
989 jj_popL1RequestQueue;
990 }
991
992
993 // transitions from blocking states
994 transition(SS_MB, Unblock_Cancel, SS) {
995 k_popUnblockQueue;
996 }
997
998 transition(MT_MB, Unblock_Cancel, MT) {
999 k_popUnblockQueue;
1000 }
1001
1002 transition(MT_IB, Unblock_Cancel, MT) {
1003 k_popUnblockQueue;
1004 }
1005
1006 transition(SS_MB, Exclusive_Unblock, MT) {
1007 // update actual directory
1008 mmu_markExclusiveFromUnblock;
1009 k_popUnblockQueue;
1010 }
1011
1012 transition({M_MB, MT_MB}, Exclusive_Unblock, MT) {
1013 // update actual directory
1014 mmu_markExclusiveFromUnblock;
1015 k_popUnblockQueue;
1016 }
1017
1018 transition(MT_IIB, {L1_PUTX, L1_PUTX_old}){
1019 zz_recycleL1RequestQueue;
1020 }
1021
1022 transition(MT_IIB, Unblock, MT_IB) {
1023 nnu_addSharerFromUnblock;
1024 k_popUnblockQueue;
1025 }
1026
1027 transition(MT_IIB, {WB_Data, WB_Data_clean}, MT_SB) {
1028 m_writeDataToCache;
1029 o_popIncomingResponseQueue;
1030 }
1031
1032 transition(MT_IB, {WB_Data, WB_Data_clean}, SS) {
1033 m_writeDataToCache;
1034 o_popIncomingResponseQueue;
1035 }
1036
1037 transition(MT_SB, Unblock, SS) {
1038 nnu_addSharerFromUnblock;
1039 k_popUnblockQueue;
1040 }
1041
1042 // writeback states
1043 transition({I_I, S_I, MT_I, MCT_I, M_I}, {L1_GETX, L1_UPGRADE, L1_GETS, L1_GET_INSTR}) {
1044 zz_recycleL1RequestQueue;
1045 }
1046
1047 transition(I_I, Ack) {
1048 q_updateAck;
1049 o_popIncomingResponseQueue;
1050 }
1051
1052 transition(I_I, Ack_all, M_I) {
1053 c_exclusiveCleanReplacement;
1054 o_popIncomingResponseQueue;
1055 }
1056
1057 transition({MT_I, MCT_I}, WB_Data, M_I) {
1058 qq_writeDataToTBE;
1059 ct_exclusiveReplacementFromTBE;
1060 o_popIncomingResponseQueue;
1061 }
1062
1063 transition(MCT_I, {WB_Data_clean, Ack_all}, M_I) {
1064 c_exclusiveCleanReplacement;
1065 o_popIncomingResponseQueue;
1066 }
1067
1068 transition(MCT_I, {L1_PUTX, L1_PUTX_old}){
1069 zz_recycleL1RequestQueue;
1070 }
1071
1072 // L1 never changed Dirty data
1073 transition(MT_I, Ack_all, M_I) {
1074 ct_exclusiveReplacementFromTBE;
1075 o_popIncomingResponseQueue;
1076 }
1077
1078 transition(MT_I, {L1_PUTX, L1_PUTX_old}){
1079 zz_recycleL1RequestQueue;
1080 }
1081
1082 // possible race between unblock and immediate replacement
1083 transition({MT_MB,SS_MB}, {L1_PUTX, L1_PUTX_old}) {
1084 zz_recycleL1RequestQueue;
1085 }
1086
1087 transition(MT_I, WB_Data_clean, NP) {
1088 s_deallocateTBE;
1089 o_popIncomingResponseQueue;
1090 }
1091
1092 transition(S_I, Ack) {
1093 q_updateAck;
1094 o_popIncomingResponseQueue;
1095 }
1096
1097 transition(S_I, Ack_all, M_I) {
1098 ct_exclusiveReplacementFromTBE;
1099 o_popIncomingResponseQueue;
1100 }
1101
1102 transition(M_I, Mem_Ack, NP) {
1103 s_deallocateTBE;
1104 o_popIncomingResponseQueue;
1105 }
1106 }