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