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