mem-cache: Create an address aware TempCacheBlk
[gem5.git] / src / mem / protocol / MOESI_AMD_Base-dir.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:Directory, "AMD Baseline protocol")
37 : DirectoryMemory * directory;
38 CacheMemory * L3CacheMemory;
39 Cycles response_latency := 5;
40 Cycles l3_hit_latency := 50;
41 bool noTCCdir := "False";
42 bool CPUonly := "False";
43 int TCC_select_num_bits;
44 bool useL3OnWT := "False";
45 Cycles to_memory_controller_latency := 1;
46
47 // From the Cores
48 MessageBuffer * requestFromCores, network="From", virtual_network="0", vnet_type="request";
49 MessageBuffer * responseFromCores, network="From", virtual_network="2", vnet_type="response";
50 MessageBuffer * unblockFromCores, network="From", virtual_network="4", vnet_type="unblock";
51
52 MessageBuffer * probeToCore, network="To", virtual_network="0", vnet_type="request";
53 MessageBuffer * responseToCore, network="To", virtual_network="2", vnet_type="response";
54
55 MessageBuffer * triggerQueue;
56 MessageBuffer * L3triggerQueue;
57 MessageBuffer * responseFromMemory;
58 {
59 // STATES
60 state_declaration(State, desc="Directory states", default="Directory_State_U") {
61 U, AccessPermission:Backing_Store, desc="unblocked";
62 BL, AccessPermission:Busy, desc="got L3 WB request";
63 // BL is Busy because it's possible for the data only to be in the network
64 // in the WB, L3 has sent it and gone on with its business in possibly I
65 // state.
66 BS_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
67 BM_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
68 B_M, AccessPermission:Backing_Store, desc="blocked waiting for memory";
69 BP, AccessPermission:Backing_Store, desc="blocked waiting for probes, no need for memory";
70 BS_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
71 BM_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
72 B_PM, AccessPermission:Backing_Store, desc="blocked waiting for probes and Memory";
73 BS_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
74 BM_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
75 B_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory";
76 B, AccessPermission:Backing_Store, desc="sent response, Blocked til ack";
77 }
78
79 // Events
80 enumeration(Event, desc="Directory events") {
81 // CPU requests
82 RdBlkS, desc="...";
83 RdBlkM, desc="...";
84 RdBlk, desc="...";
85 CtoD, desc="...";
86 WriteThrough, desc="WriteThrough Message";
87 Atomic, desc="Atomic Message";
88
89 // writebacks
90 VicDirty, desc="...";
91 VicClean, desc="...";
92 CPUData, desc="WB data from CPU";
93 StaleWB, desc="Notification that WB has been superceded by a probe";
94
95 // probe responses
96 CPUPrbResp, desc="Probe Response Msg";
97
98 ProbeAcksComplete, desc="Probe Acks Complete";
99
100 L3Hit, desc="Hit in L3 return data to core";
101
102 // Memory Controller
103 MemData, desc="Fetched data from memory arrives";
104 WBAck, desc="Writeback Ack from memory arrives";
105
106 CoreUnblock, desc="Core received data, unblock";
107 UnblockWriteThrough, desc="Unblock because of writethrough request finishing";
108
109 StaleVicDirty, desc="Core invalidated before VicDirty processed";
110 }
111
112 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") {
113 L3DataArrayRead, desc="Read the data array";
114 L3DataArrayWrite, desc="Write the data array";
115 L3TagArrayRead, desc="Read the data array";
116 L3TagArrayWrite, desc="Write the data array";
117 }
118
119 // TYPES
120
121 // DirectoryEntry
122 structure(Entry, desc="...", interface="AbstractEntry") {
123 State DirectoryState, desc="Directory state";
124 DataBlock DataBlk, desc="data for the block";
125 NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore";
126 }
127
128 structure(CacheEntry, desc="...", interface="AbstractCacheEntry") {
129 DataBlock DataBlk, desc="data for the block";
130 MachineID LastSender, desc="Mach which this block came from";
131 }
132
133 structure(TBE, desc="...") {
134 State TBEState, desc="Transient state";
135 DataBlock DataBlk, desc="data for the block";
136 bool Dirty, desc="Is the data dirty?";
137 int NumPendingAcks, desc="num acks expected";
138 MachineID OriginalRequestor, desc="Original Requestor";
139 MachineID WTRequestor, desc="WT Requestor";
140 bool Cached, desc="data hit in Cache";
141 bool MemData, desc="Got MemData?",default="false";
142 bool wtData, desc="Got write through data?",default="false";
143 bool atomicData, desc="Got Atomic op?",default="false";
144 Cycles InitialRequestTime, desc="...";
145 Cycles ForwardRequestTime, desc="...";
146 Cycles ProbeRequestStartTime, desc="...";
147 MachineID LastSender, desc="Mach which this block came from";
148 bool L3Hit, default="false", desc="Was this an L3 hit?";
149 uint64_t probe_id, desc="probe id for lifetime profiling";
150 WriteMask writeMask, desc="outstanding write through mask";
151 }
152
153 structure(TBETable, external="yes") {
154 TBE lookup(Addr);
155 void allocate(Addr);
156 void deallocate(Addr);
157 bool isPresent(Addr);
158 }
159
160 TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs";
161
162 int TCC_select_low_bit, default="RubySystem::getBlockSizeBits()";
163
164 Tick clockEdge();
165 Tick cyclesToTicks(Cycles c);
166
167 void set_tbe(TBE a);
168 void unset_tbe();
169 void wakeUpAllBuffers();
170 void wakeUpBuffers(Addr a);
171 Cycles curCycle();
172
173 Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
174 Entry dir_entry := static_cast(Entry, "pointer", directory.lookup(addr));
175
176 if (is_valid(dir_entry)) {
177 return dir_entry;
178 }
179
180 dir_entry := static_cast(Entry, "pointer",
181 directory.allocate(addr, new Entry));
182 return dir_entry;
183 }
184
185 DataBlock getDataBlock(Addr addr), return_by_ref="yes" {
186 TBE tbe := TBEs.lookup(addr);
187 if (is_valid(tbe) && tbe.MemData) {
188 DPRINTF(RubySlicc, "Returning DataBlk from TBE %s:%s\n", addr, tbe);
189 return tbe.DataBlk;
190 }
191 DPRINTF(RubySlicc, "Returning DataBlk from Dir %s:%s\n", addr, getDirectoryEntry(addr));
192 return getDirectoryEntry(addr).DataBlk;
193 }
194
195 State getState(TBE tbe, CacheEntry entry, Addr addr) {
196 return getDirectoryEntry(addr).DirectoryState;
197 }
198
199 void setState(TBE tbe, CacheEntry entry, Addr addr, State state) {
200 getDirectoryEntry(addr).DirectoryState := state;
201 }
202
203 void functionalRead(Addr addr, Packet *pkt) {
204 TBE tbe := TBEs.lookup(addr);
205 if(is_valid(tbe)) {
206 testAndRead(addr, tbe.DataBlk, pkt);
207 } else {
208 functionalMemoryRead(pkt);
209 }
210 }
211
212 int functionalWrite(Addr addr, Packet *pkt) {
213 int num_functional_writes := 0;
214
215 TBE tbe := TBEs.lookup(addr);
216 if(is_valid(tbe)) {
217 num_functional_writes := num_functional_writes +
218 testAndWrite(addr, tbe.DataBlk, pkt);
219 }
220
221 num_functional_writes := num_functional_writes
222 + functionalMemoryWrite(pkt);
223 return num_functional_writes;
224 }
225
226 AccessPermission getAccessPermission(Addr addr) {
227 // For this Directory, all permissions are just tracked in Directory, since
228 // it's not possible to have something in TBE but not Dir, just keep track
229 // of state all in one place.
230 if (directory.isPresent(addr)) {
231 return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
232 }
233
234 return AccessPermission:NotPresent;
235 }
236
237 void setAccessPermission(CacheEntry entry, Addr addr, State state) {
238 getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state));
239 }
240
241 void recordRequestType(RequestType request_type, Addr addr) {
242 if (request_type == RequestType:L3DataArrayRead) {
243 L3CacheMemory.recordRequestType(CacheRequestType:DataArrayRead, addr);
244 } else if (request_type == RequestType:L3DataArrayWrite) {
245 L3CacheMemory.recordRequestType(CacheRequestType:DataArrayWrite, addr);
246 } else if (request_type == RequestType:L3TagArrayRead) {
247 L3CacheMemory.recordRequestType(CacheRequestType:TagArrayRead, addr);
248 } else if (request_type == RequestType:L3TagArrayWrite) {
249 L3CacheMemory.recordRequestType(CacheRequestType:TagArrayWrite, addr);
250 }
251 }
252
253 bool checkResourceAvailable(RequestType request_type, Addr addr) {
254 if (request_type == RequestType:L3DataArrayRead) {
255 return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
256 } else if (request_type == RequestType:L3DataArrayWrite) {
257 return L3CacheMemory.checkResourceAvailable(CacheResourceType:DataArray, addr);
258 } else if (request_type == RequestType:L3TagArrayRead) {
259 return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
260 } else if (request_type == RequestType:L3TagArrayWrite) {
261 return L3CacheMemory.checkResourceAvailable(CacheResourceType:TagArray, addr);
262 } else {
263 error("Invalid RequestType type in checkResourceAvailable");
264 return true;
265 }
266 }
267
268 // ** OUT_PORTS **
269 out_port(probeNetwork_out, NBProbeRequestMsg, probeToCore);
270 out_port(responseNetwork_out, ResponseMsg, responseToCore);
271
272 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
273 out_port(L3TriggerQueue_out, TriggerMsg, L3triggerQueue);
274
275 // ** IN_PORTS **
276
277 // Trigger Queue
278 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
279 if (triggerQueue_in.isReady(clockEdge())) {
280 peek(triggerQueue_in, TriggerMsg) {
281 TBE tbe := TBEs.lookup(in_msg.addr);
282 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
283 if (in_msg.Type == TriggerType:AcksComplete) {
284 trigger(Event:ProbeAcksComplete, in_msg.addr, entry, tbe);
285 }else if (in_msg.Type == TriggerType:UnblockWriteThrough) {
286 trigger(Event:UnblockWriteThrough, in_msg.addr, entry, tbe);
287 } else {
288 error("Unknown trigger msg");
289 }
290 }
291 }
292 }
293
294 in_port(L3TriggerQueue_in, TriggerMsg, L3triggerQueue, rank=4) {
295 if (L3TriggerQueue_in.isReady(clockEdge())) {
296 peek(L3TriggerQueue_in, TriggerMsg) {
297 TBE tbe := TBEs.lookup(in_msg.addr);
298 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
299 if (in_msg.Type == TriggerType:L3Hit) {
300 trigger(Event:L3Hit, in_msg.addr, entry, tbe);
301 } else {
302 error("Unknown trigger msg");
303 }
304 }
305 }
306 }
307
308 // Unblock Network
309 in_port(unblockNetwork_in, UnblockMsg, unblockFromCores, rank=3) {
310 if (unblockNetwork_in.isReady(clockEdge())) {
311 peek(unblockNetwork_in, UnblockMsg) {
312 TBE tbe := TBEs.lookup(in_msg.addr);
313 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
314 trigger(Event:CoreUnblock, in_msg.addr, entry, tbe);
315 }
316 }
317 }
318
319 // Core response network
320 in_port(responseNetwork_in, ResponseMsg, responseFromCores, rank=2) {
321 if (responseNetwork_in.isReady(clockEdge())) {
322 peek(responseNetwork_in, ResponseMsg) {
323 TBE tbe := TBEs.lookup(in_msg.addr);
324 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
325 if (in_msg.Type == CoherenceResponseType:CPUPrbResp) {
326 trigger(Event:CPUPrbResp, in_msg.addr, entry, tbe);
327 } else if (in_msg.Type == CoherenceResponseType:CPUData) {
328 trigger(Event:CPUData, in_msg.addr, entry, tbe);
329 } else if (in_msg.Type == CoherenceResponseType:StaleNotif) {
330 trigger(Event:StaleWB, in_msg.addr, entry, tbe);
331 } else {
332 error("Unexpected response type");
333 }
334 }
335 }
336 }
337
338 // off-chip memory request/response is done
339 in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=1) {
340 if (memQueue_in.isReady(clockEdge())) {
341 peek(memQueue_in, MemoryMsg) {
342 TBE tbe := TBEs.lookup(in_msg.addr);
343 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
344 if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
345 trigger(Event:MemData, in_msg.addr, entry, tbe);
346 DPRINTF(RubySlicc, "%s\n", in_msg);
347 } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
348 trigger(Event:WBAck, in_msg.addr, entry, tbe); // ignore WBAcks, don't care about them.
349 } else {
350 DPRINTF(RubySlicc, "%s\n", in_msg.Type);
351 error("Invalid message");
352 }
353 }
354 }
355 }
356
357 in_port(requestNetwork_in, CPURequestMsg, requestFromCores, rank=0) {
358 if (requestNetwork_in.isReady(clockEdge())) {
359 peek(requestNetwork_in, CPURequestMsg) {
360 TBE tbe := TBEs.lookup(in_msg.addr);
361 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(in_msg.addr));
362 if (in_msg.Type == CoherenceRequestType:RdBlk) {
363 trigger(Event:RdBlk, in_msg.addr, entry, tbe);
364 } else if (in_msg.Type == CoherenceRequestType:RdBlkS) {
365 trigger(Event:RdBlkS, in_msg.addr, entry, tbe);
366 } else if (in_msg.Type == CoherenceRequestType:RdBlkM) {
367 trigger(Event:RdBlkM, in_msg.addr, entry, tbe);
368 } else if (in_msg.Type == CoherenceRequestType:WriteThrough) {
369 trigger(Event:WriteThrough, in_msg.addr, entry, tbe);
370 } else if (in_msg.Type == CoherenceRequestType:Atomic) {
371 trigger(Event:Atomic, in_msg.addr, entry, tbe);
372 } else if (in_msg.Type == CoherenceRequestType:VicDirty) {
373 if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
374 DPRINTF(RubySlicc, "Dropping VicDirty for address %s\n", in_msg.addr);
375 trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
376 } else {
377 DPRINTF(RubySlicc, "Got VicDirty from %s on %s\n", in_msg.Requestor, in_msg.addr);
378 trigger(Event:VicDirty, in_msg.addr, entry, tbe);
379 }
380 } else if (in_msg.Type == CoherenceRequestType:VicClean) {
381 if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) {
382 DPRINTF(RubySlicc, "Dropping VicClean for address %s\n", in_msg.addr);
383 trigger(Event:StaleVicDirty, in_msg.addr, entry, tbe);
384 } else {
385 DPRINTF(RubySlicc, "Got VicClean from %s on %s\n", in_msg.Requestor, in_msg.addr);
386 trigger(Event:VicClean, in_msg.addr, entry, tbe);
387 }
388 } else {
389 error("Bad request message type");
390 }
391 }
392 }
393 }
394
395 // Actions
396 action(s_sendResponseS, "s", desc="send Shared response") {
397 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
398 out_msg.addr := address;
399 out_msg.Type := CoherenceResponseType:NBSysResp;
400 if (tbe.L3Hit) {
401 out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
402 } else {
403 out_msg.Sender := machineID;
404 }
405 out_msg.Destination.add(tbe.OriginalRequestor);
406 out_msg.DataBlk := tbe.DataBlk;
407 out_msg.MessageSize := MessageSizeType:Response_Data;
408 out_msg.Dirty := false;
409 out_msg.State := CoherenceState:Shared;
410 out_msg.InitialRequestTime := tbe.InitialRequestTime;
411 out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
412 out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
413 out_msg.OriginalResponder := tbe.LastSender;
414 out_msg.L3Hit := tbe.L3Hit;
415 DPRINTF(RubySlicc, "%s\n", out_msg);
416 }
417 }
418
419 action(es_sendResponseES, "es", desc="send Exclusive or Shared response") {
420 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
421 out_msg.addr := address;
422 out_msg.Type := CoherenceResponseType:NBSysResp;
423 if (tbe.L3Hit) {
424 out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
425 } else {
426 out_msg.Sender := machineID;
427 }
428 out_msg.Destination.add(tbe.OriginalRequestor);
429 out_msg.DataBlk := tbe.DataBlk;
430 out_msg.MessageSize := MessageSizeType:Response_Data;
431 out_msg.Dirty := tbe.Dirty;
432 if (tbe.Cached) {
433 out_msg.State := CoherenceState:Shared;
434 } else {
435 out_msg.State := CoherenceState:Exclusive;
436 }
437 out_msg.InitialRequestTime := tbe.InitialRequestTime;
438 out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
439 out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
440 out_msg.OriginalResponder := tbe.LastSender;
441 out_msg.L3Hit := tbe.L3Hit;
442 DPRINTF(RubySlicc, "%s\n", out_msg);
443 }
444 }
445
446 action(m_sendResponseM, "m", desc="send Modified response") {
447 if (tbe.wtData) {
448 enqueue(triggerQueue_out, TriggerMsg, 1) {
449 out_msg.addr := address;
450 out_msg.Type := TriggerType:UnblockWriteThrough;
451 }
452 }else{
453 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
454 out_msg.addr := address;
455 out_msg.Type := CoherenceResponseType:NBSysResp;
456 if (tbe.L3Hit) {
457 out_msg.Sender := createMachineID(MachineType:L3Cache, intToID(0));
458 } else {
459 out_msg.Sender := machineID;
460 }
461 out_msg.Destination.add(tbe.OriginalRequestor);
462 out_msg.DataBlk := tbe.DataBlk;
463 out_msg.MessageSize := MessageSizeType:Response_Data;
464 out_msg.Dirty := tbe.Dirty;
465 out_msg.State := CoherenceState:Modified;
466 out_msg.CtoD := false;
467 out_msg.InitialRequestTime := tbe.InitialRequestTime;
468 out_msg.ForwardRequestTime := tbe.ForwardRequestTime;
469 out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
470 out_msg.OriginalResponder := tbe.LastSender;
471 if(tbe.atomicData){
472 out_msg.WTRequestor := tbe.WTRequestor;
473 }
474 out_msg.L3Hit := tbe.L3Hit;
475 DPRINTF(RubySlicc, "%s\n", out_msg);
476 }
477 if (tbe.atomicData) {
478 enqueue(triggerQueue_out, TriggerMsg, 1) {
479 out_msg.addr := address;
480 out_msg.Type := TriggerType:UnblockWriteThrough;
481 }
482 }
483 }
484 }
485
486 action(c_sendResponseCtoD, "c", desc="send CtoD Ack") {
487 enqueue(responseNetwork_out, ResponseMsg, response_latency) {
488 out_msg.addr := address;
489 out_msg.Type := CoherenceResponseType:NBSysResp;
490 out_msg.Sender := machineID;
491 out_msg.Destination.add(tbe.OriginalRequestor);
492 out_msg.MessageSize := MessageSizeType:Response_Control;
493 out_msg.Dirty := false;
494 out_msg.State := CoherenceState:Modified;
495 out_msg.CtoD := true;
496 out_msg.InitialRequestTime := tbe.InitialRequestTime;
497 out_msg.ForwardRequestTime := curCycle();
498 out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime;
499 DPRINTF(RubySlicc, "%s\n", out_msg);
500 }
501 }
502
503 action(w_sendResponseWBAck, "w", desc="send WB Ack") {
504 peek(requestNetwork_in, CPURequestMsg) {
505 enqueue(responseNetwork_out, ResponseMsg, 1) {
506 out_msg.addr := address;
507 out_msg.Type := CoherenceResponseType:NBSysWBAck;
508 out_msg.Destination.add(in_msg.Requestor);
509 out_msg.WTRequestor := in_msg.WTRequestor;
510 out_msg.Sender := machineID;
511 out_msg.MessageSize := MessageSizeType:Writeback_Control;
512 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
513 out_msg.ForwardRequestTime := curCycle();
514 out_msg.ProbeRequestStartTime := curCycle();
515 }
516 }
517 }
518
519 action(l_queueMemWBReq, "lq", desc="Write WB data to memory") {
520 peek(responseNetwork_in, ResponseMsg) {
521 queueMemoryWrite(machineID, address, to_memory_controller_latency,
522 in_msg.DataBlk);
523 }
524 }
525
526 action(l_queueMemRdReq, "lr", desc="Read data from memory") {
527 peek(requestNetwork_in, CPURequestMsg) {
528 if (L3CacheMemory.isTagPresent(address)) {
529 enqueue(L3TriggerQueue_out, TriggerMsg, l3_hit_latency) {
530 out_msg.addr := address;
531 out_msg.Type := TriggerType:L3Hit;
532 DPRINTF(RubySlicc, "%s\n", out_msg);
533 }
534 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
535 if (tbe.Dirty == false) {
536 tbe.DataBlk := entry.DataBlk;
537 }
538 tbe.LastSender := entry.LastSender;
539 tbe.L3Hit := true;
540 tbe.MemData := true;
541 L3CacheMemory.deallocate(address);
542 } else {
543 queueMemoryRead(machineID, address, to_memory_controller_latency);
544 }
545 }
546 }
547
548 action(dc_probeInvCoreData, "dc", desc="probe inv cores, return data") {
549 peek(requestNetwork_in, CPURequestMsg) {
550 enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
551 out_msg.addr := address;
552 out_msg.Type := ProbeRequestType:PrbInv;
553 out_msg.ReturnData := true;
554 out_msg.MessageSize := MessageSizeType:Control;
555 out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
556
557 // add relevant TCC node to list. This replaces all TCPs and SQCs
558 if (((in_msg.Type == CoherenceRequestType:WriteThrough ||
559 in_msg.Type == CoherenceRequestType:Atomic) &&
560 in_msg.NoWriteConflict) ||
561 CPUonly) {
562 } else if (noTCCdir) {
563 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
564 TCC_select_low_bit, TCC_select_num_bits));
565 } else {
566 out_msg.Destination.add(mapAddressToRange(address,
567 MachineType:TCCdir,
568 TCC_select_low_bit, TCC_select_num_bits));
569 }
570 out_msg.Destination.remove(in_msg.Requestor);
571 tbe.NumPendingAcks := out_msg.Destination.count();
572 if (tbe.NumPendingAcks == 0) {
573 enqueue(triggerQueue_out, TriggerMsg, 1) {
574 out_msg.addr := address;
575 out_msg.Type := TriggerType:AcksComplete;
576 }
577 }
578 DPRINTF(RubySlicc, "%s\n", out_msg);
579 APPEND_TRANSITION_COMMENT(" dc: Acks remaining: ");
580 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
581 tbe.ProbeRequestStartTime := curCycle();
582 }
583 }
584 }
585
586 action(sc_probeShrCoreData, "sc", desc="probe shared cores, return data") {
587 peek(requestNetwork_in, CPURequestMsg) { // not the right network?
588 enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
589 out_msg.addr := address;
590 out_msg.Type := ProbeRequestType:PrbDowngrade;
591 out_msg.ReturnData := true;
592 out_msg.MessageSize := MessageSizeType:Control;
593 out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
594 // add relevant TCC node to the list. This replaces all TCPs and SQCs
595 if (noTCCdir || CPUonly) {
596 //Don't need to notify TCC about reads
597 } else {
598 out_msg.Destination.add(mapAddressToRange(address,
599 MachineType:TCCdir,
600 TCC_select_low_bit, TCC_select_num_bits));
601 tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
602 }
603 if (noTCCdir && !CPUonly) {
604 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
605 TCC_select_low_bit, TCC_select_num_bits));
606 }
607 out_msg.Destination.remove(in_msg.Requestor);
608 tbe.NumPendingAcks := out_msg.Destination.count();
609 if (tbe.NumPendingAcks == 0) {
610 enqueue(triggerQueue_out, TriggerMsg, 1) {
611 out_msg.addr := address;
612 out_msg.Type := TriggerType:AcksComplete;
613 }
614 }
615 DPRINTF(RubySlicc, "%s\n", (out_msg));
616 APPEND_TRANSITION_COMMENT(" sc: Acks remaining: ");
617 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
618 tbe.ProbeRequestStartTime := curCycle();
619 }
620 }
621 }
622
623 action(ic_probeInvCore, "ic", desc="probe invalidate core, no return data needed") {
624 peek(requestNetwork_in, CPURequestMsg) { // not the right network?
625 enqueue(probeNetwork_out, NBProbeRequestMsg, response_latency) {
626 out_msg.addr := address;
627 out_msg.Type := ProbeRequestType:PrbInv;
628 out_msg.ReturnData := false;
629 out_msg.MessageSize := MessageSizeType:Control;
630 out_msg.Destination.broadcast(MachineType:CorePair); // won't be realistic for multisocket
631
632 // add relevant TCC node to the list. This replaces all TCPs and SQCs
633 if (noTCCdir && !CPUonly) {
634 out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
635 TCC_select_low_bit, TCC_select_num_bits));
636 } else {
637 if (!noTCCdir) {
638 out_msg.Destination.add(mapAddressToRange(address,
639 MachineType:TCCdir,
640 TCC_select_low_bit,
641 TCC_select_num_bits));
642 }
643 }
644 out_msg.Destination.remove(in_msg.Requestor);
645 tbe.NumPendingAcks := out_msg.Destination.count();
646 if (tbe.NumPendingAcks == 0) {
647 enqueue(triggerQueue_out, TriggerMsg, 1) {
648 out_msg.addr := address;
649 out_msg.Type := TriggerType:AcksComplete;
650 }
651 }
652 APPEND_TRANSITION_COMMENT(" ic: Acks remaining: ");
653 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
654 DPRINTF(RubySlicc, "%s\n", out_msg);
655 tbe.ProbeRequestStartTime := curCycle();
656 }
657 }
658 }
659
660 action(d_writeDataToMemory, "d", desc="Write data to memory") {
661 peek(responseNetwork_in, ResponseMsg) {
662 getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
663 if (tbe.Dirty == false) {
664 // have to update the TBE, too, because of how this
665 // directory deals with functional writes
666 tbe.DataBlk := in_msg.DataBlk;
667 }
668 }
669 }
670
671 action(t_allocateTBE, "t", desc="allocate TBE Entry") {
672 check_allocate(TBEs);
673 peek(requestNetwork_in, CPURequestMsg) {
674 TBEs.allocate(address);
675 set_tbe(TBEs.lookup(address));
676 if (in_msg.Type == CoherenceRequestType:WriteThrough) {
677 tbe.writeMask.clear();
678 tbe.writeMask.orMask(in_msg.writeMask);
679 tbe.wtData := true;
680 tbe.WTRequestor := in_msg.WTRequestor;
681 tbe.LastSender := in_msg.Requestor;
682 }
683 if (in_msg.Type == CoherenceRequestType:Atomic) {
684 tbe.writeMask.clear();
685 tbe.writeMask.orMask(in_msg.writeMask);
686 tbe.atomicData := true;
687 tbe.WTRequestor := in_msg.WTRequestor;
688 tbe.LastSender := in_msg.Requestor;
689 }
690 tbe.DataBlk := getDirectoryEntry(address).DataBlk; // Data only for WBs
691 tbe.Dirty := false;
692 if (in_msg.Type == CoherenceRequestType:WriteThrough) {
693 tbe.DataBlk.copyPartial(in_msg.DataBlk,in_msg.writeMask);
694 tbe.Dirty := true;
695 }
696 tbe.OriginalRequestor := in_msg.Requestor;
697 tbe.NumPendingAcks := 0;
698 tbe.Cached := in_msg.ForceShared;
699 tbe.InitialRequestTime := in_msg.InitialRequestTime;
700 }
701 }
702
703 action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") {
704 if (tbe.Dirty == false) {
705 getDirectoryEntry(address).DataBlk := tbe.DataBlk;
706 }
707 TBEs.deallocate(address);
708 unset_tbe();
709 }
710
711 action(wd_writeBackData, "wd", desc="Write back data if needed") {
712 if (tbe.wtData) {
713 getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk, tbe.writeMask);
714 } else if (tbe.atomicData) {
715 tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask);
716 getDirectoryEntry(address).DataBlk := tbe.DataBlk;
717 } else if (tbe.Dirty == false) {
718 getDirectoryEntry(address).DataBlk := tbe.DataBlk;
719 }
720 }
721
722 action(mt_writeMemDataToTBE, "mt", desc="write Mem data to TBE") {
723 peek(memQueue_in, MemoryMsg) {
724 if (tbe.wtData == true) {
725 // do nothing
726 } else if (tbe.Dirty == false) {
727 tbe.DataBlk := getDirectoryEntry(address).DataBlk;
728 }
729 tbe.MemData := true;
730 }
731 }
732
733 action(y_writeProbeDataToTBE, "y", desc="write Probe Data to TBE") {
734 peek(responseNetwork_in, ResponseMsg) {
735 if (in_msg.Dirty) {
736 if (tbe.wtData) {
737 DataBlock tmp := in_msg.DataBlk;
738 tmp.copyPartial(tbe.DataBlk,tbe.writeMask);
739 tbe.DataBlk := tmp;
740 tbe.writeMask.fillMask();
741 } else if (tbe.Dirty) {
742 if(tbe.atomicData == false && tbe.wtData == false) {
743 DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender);
744 assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data
745 }
746 } else {
747 tbe.DataBlk := in_msg.DataBlk;
748 tbe.Dirty := in_msg.Dirty;
749 tbe.LastSender := in_msg.Sender;
750 }
751 }
752 if (in_msg.Hit) {
753 tbe.Cached := true;
754 }
755 }
756 }
757
758 action(mwc_markSinkWriteCancel, "mwc", desc="Mark to sink impending VicDirty") {
759 peek(responseNetwork_in, ResponseMsg) {
760 getDirectoryEntry(address).VicDirtyIgnore.add(in_msg.Sender);
761 APPEND_TRANSITION_COMMENT(" setting bit to sink VicDirty ");
762 }
763 }
764
765 action(x_decrementAcks, "x", desc="decrement Acks pending") {
766 tbe.NumPendingAcks := tbe.NumPendingAcks - 1;
767 APPEND_TRANSITION_COMMENT(" Acks remaining: ");
768 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
769 }
770
771 action(o_checkForCompletion, "o", desc="check for ack completion") {
772 if (tbe.NumPendingAcks == 0) {
773 enqueue(triggerQueue_out, TriggerMsg, 1) {
774 out_msg.addr := address;
775 out_msg.Type := TriggerType:AcksComplete;
776 }
777 }
778 APPEND_TRANSITION_COMMENT(" Check: Acks remaining: ");
779 APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks);
780 }
781
782 action(rv_removeVicDirtyIgnore, "rv", desc="Remove ignored core") {
783 peek(requestNetwork_in, CPURequestMsg) {
784 getDirectoryEntry(address).VicDirtyIgnore.remove(in_msg.Requestor);
785 }
786 }
787
788 action(al_allocateL3Block, "al", desc="allocate the L3 block on WB") {
789 peek(responseNetwork_in, ResponseMsg) {
790 if (L3CacheMemory.isTagPresent(address)) {
791 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
792 APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
793 entry.DataBlk := in_msg.DataBlk;
794 entry.LastSender := in_msg.Sender;
795 } else {
796 if (L3CacheMemory.cacheAvail(address) == false) {
797 Addr victim := L3CacheMemory.cacheProbe(address);
798 CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
799 L3CacheMemory.lookup(victim));
800 queueMemoryWrite(machineID, victim, to_memory_controller_latency,
801 victim_entry.DataBlk);
802 L3CacheMemory.deallocate(victim);
803 }
804 assert(L3CacheMemory.cacheAvail(address));
805 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
806 APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
807 entry.DataBlk := in_msg.DataBlk;
808
809 entry.LastSender := in_msg.Sender;
810 }
811 }
812 }
813
814 action(alwt_allocateL3BlockOnWT, "alwt", desc="allocate the L3 block on WT") {
815 if ((tbe.wtData || tbe.atomicData) && useL3OnWT) {
816 if (L3CacheMemory.isTagPresent(address)) {
817 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.lookup(address));
818 APPEND_TRANSITION_COMMENT(" al wrote data to L3 (hit) ");
819 entry.DataBlk := tbe.DataBlk;
820 entry.LastSender := tbe.LastSender;
821 } else {
822 if (L3CacheMemory.cacheAvail(address) == false) {
823 Addr victim := L3CacheMemory.cacheProbe(address);
824 CacheEntry victim_entry := static_cast(CacheEntry, "pointer",
825 L3CacheMemory.lookup(victim));
826 queueMemoryWrite(machineID, victim, to_memory_controller_latency,
827 victim_entry.DataBlk);
828 L3CacheMemory.deallocate(victim);
829 }
830 assert(L3CacheMemory.cacheAvail(address));
831 CacheEntry entry := static_cast(CacheEntry, "pointer", L3CacheMemory.allocate(address, new CacheEntry));
832 APPEND_TRANSITION_COMMENT(" al wrote data to L3 ");
833 entry.DataBlk := tbe.DataBlk;
834 entry.LastSender := tbe.LastSender;
835 }
836 }
837 }
838
839 action(sf_setForwardReqTime, "sf", desc="...") {
840 tbe.ForwardRequestTime := curCycle();
841 }
842
843 action(dl_deallocateL3, "dl", desc="deallocate the L3 block") {
844 L3CacheMemory.deallocate(address);
845 }
846
847 action(p_popRequestQueue, "p", desc="pop request queue") {
848 requestNetwork_in.dequeue(clockEdge());
849 }
850
851 action(pr_popResponseQueue, "pr", desc="pop response queue") {
852 responseNetwork_in.dequeue(clockEdge());
853 }
854
855 action(pm_popMemQueue, "pm", desc="pop mem queue") {
856 memQueue_in.dequeue(clockEdge());
857 }
858
859 action(pt_popTriggerQueue, "pt", desc="pop trigger queue") {
860 triggerQueue_in.dequeue(clockEdge());
861 }
862
863 action(ptl_popTriggerQueue, "ptl", desc="pop L3 trigger queue") {
864 L3TriggerQueue_in.dequeue(clockEdge());
865 }
866
867 action(pu_popUnblockQueue, "pu", desc="pop unblock queue") {
868 unblockNetwork_in.dequeue(clockEdge());
869 }
870
871 action(zz_recycleRequestQueue, "zz", desc="recycle request queue") {
872 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
873 }
874
875 action(yy_recycleResponseQueue, "yy", desc="recycle response queue") {
876 responseNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency));
877 }
878
879 action(st_stallAndWaitRequest, "st", desc="Stall and wait on the address") {
880 stall_and_wait(requestNetwork_in, address);
881 }
882
883 action(wa_wakeUpDependents, "wa", desc="Wake up any requests waiting for this address") {
884 wakeUpBuffers(address);
885 }
886
887 action(wa_wakeUpAllDependents, "waa", desc="Wake up any requests waiting for this region") {
888 wakeUpAllBuffers();
889 }
890
891 action(z_stall, "z", desc="...") {
892 }
893
894 // TRANSITIONS
895 transition({BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {RdBlkS, RdBlkM, RdBlk, CtoD}) {
896 st_stallAndWaitRequest;
897 }
898
899 // It may be possible to save multiple invalidations here!
900 transition({BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, {Atomic, WriteThrough}) {
901 st_stallAndWaitRequest;
902 }
903
904
905 // transitions from U
906 transition(U, {RdBlkS}, BS_PM) {L3TagArrayRead} {
907 t_allocateTBE;
908 l_queueMemRdReq;
909 sc_probeShrCoreData;
910 p_popRequestQueue;
911 }
912
913 transition(U, WriteThrough, BM_PM) {L3TagArrayRead, L3TagArrayWrite} {
914 t_allocateTBE;
915 w_sendResponseWBAck;
916 l_queueMemRdReq;
917 dc_probeInvCoreData;
918 p_popRequestQueue;
919 }
920
921 transition(U, Atomic, BM_PM) {L3TagArrayRead, L3TagArrayWrite} {
922 t_allocateTBE;
923 l_queueMemRdReq;
924 dc_probeInvCoreData;
925 p_popRequestQueue;
926 }
927
928 transition(U, {RdBlkM}, BM_PM) {L3TagArrayRead} {
929 t_allocateTBE;
930 l_queueMemRdReq;
931 dc_probeInvCoreData;
932 p_popRequestQueue;
933 }
934
935 transition(U, RdBlk, B_PM) {L3TagArrayRead}{
936 t_allocateTBE;
937 l_queueMemRdReq;
938 sc_probeShrCoreData;
939 p_popRequestQueue;
940 }
941
942 transition(U, CtoD, BP) {L3TagArrayRead} {
943 t_allocateTBE;
944 ic_probeInvCore;
945 p_popRequestQueue;
946 }
947
948 transition(U, VicDirty, BL) {L3TagArrayRead} {
949 t_allocateTBE;
950 w_sendResponseWBAck;
951 p_popRequestQueue;
952 }
953
954 transition(U, VicClean, BL) {L3TagArrayRead} {
955 t_allocateTBE;
956 w_sendResponseWBAck;
957 p_popRequestQueue;
958 }
959
960 transition(BL, {VicDirty, VicClean}) {
961 zz_recycleRequestQueue;
962 }
963
964 transition(BL, CPUData, U) {L3TagArrayWrite, L3DataArrayWrite} {
965 d_writeDataToMemory;
966 al_allocateL3Block;
967 wa_wakeUpDependents;
968 dt_deallocateTBE;
969 pr_popResponseQueue;
970 }
971
972 transition(BL, StaleWB, U) {L3TagArrayWrite} {
973 dt_deallocateTBE;
974 wa_wakeUpAllDependents;
975 pr_popResponseQueue;
976 }
977
978 transition({B, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm}, {VicDirty, VicClean}) {
979 z_stall;
980 }
981
982 transition({U, BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, WBAck) {
983 pm_popMemQueue;
984 }
985
986 transition({U, BL, BS_M, BM_M, B_M, BP, BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, B}, StaleVicDirty) {
987 rv_removeVicDirtyIgnore;
988 w_sendResponseWBAck;
989 p_popRequestQueue;
990 }
991
992 transition({B}, CoreUnblock, U) {
993 wa_wakeUpDependents;
994 pu_popUnblockQueue;
995 }
996
997 transition(B, UnblockWriteThrough, U) {
998 wa_wakeUpDependents;
999 pt_popTriggerQueue;
1000 }
1001
1002 transition(BS_PM, MemData, BS_Pm) {} {
1003 mt_writeMemDataToTBE;
1004 pm_popMemQueue;
1005 }
1006
1007 transition(BM_PM, MemData, BM_Pm){} {
1008 mt_writeMemDataToTBE;
1009 pm_popMemQueue;
1010 }
1011
1012 transition(B_PM, MemData, B_Pm){} {
1013 mt_writeMemDataToTBE;
1014 pm_popMemQueue;
1015 }
1016
1017 transition(BS_PM, L3Hit, BS_Pm) {} {
1018 ptl_popTriggerQueue;
1019 }
1020
1021 transition(BM_PM, L3Hit, BM_Pm) {} {
1022 ptl_popTriggerQueue;
1023 }
1024
1025 transition(B_PM, L3Hit, B_Pm) {} {
1026 ptl_popTriggerQueue;
1027 }
1028
1029 transition(BS_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
1030 mt_writeMemDataToTBE;
1031 s_sendResponseS;
1032 wd_writeBackData;
1033 alwt_allocateL3BlockOnWT;
1034 dt_deallocateTBE;
1035 pm_popMemQueue;
1036 }
1037
1038 transition(BM_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
1039 mt_writeMemDataToTBE;
1040 m_sendResponseM;
1041 wd_writeBackData;
1042 alwt_allocateL3BlockOnWT;
1043 dt_deallocateTBE;
1044 pm_popMemQueue;
1045 }
1046
1047 transition(B_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} {
1048 mt_writeMemDataToTBE;
1049 es_sendResponseES;
1050 wd_writeBackData;
1051 alwt_allocateL3BlockOnWT;
1052 dt_deallocateTBE;
1053 pm_popMemQueue;
1054 }
1055
1056 transition(BS_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} {
1057 s_sendResponseS;
1058 wd_writeBackData;
1059 alwt_allocateL3BlockOnWT;
1060 dt_deallocateTBE;
1061 ptl_popTriggerQueue;
1062 }
1063
1064 transition(BM_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} {
1065 m_sendResponseM;
1066 wd_writeBackData;
1067 alwt_allocateL3BlockOnWT;
1068 dt_deallocateTBE;
1069 ptl_popTriggerQueue;
1070 }
1071
1072 transition(B_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} {
1073 es_sendResponseES;
1074 wd_writeBackData;
1075 alwt_allocateL3BlockOnWT;
1076 dt_deallocateTBE;
1077 ptl_popTriggerQueue;
1078 }
1079
1080 transition({BS_PM, BM_PM, B_PM, BS_Pm, BM_Pm, B_Pm, BP}, CPUPrbResp) {
1081 y_writeProbeDataToTBE;
1082 x_decrementAcks;
1083 o_checkForCompletion;
1084 pr_popResponseQueue;
1085 }
1086
1087 transition(BS_PM, ProbeAcksComplete, BS_M) {} {
1088 sf_setForwardReqTime;
1089 pt_popTriggerQueue;
1090 }
1091
1092 transition(BM_PM, ProbeAcksComplete, BM_M) {} {
1093 sf_setForwardReqTime;
1094 pt_popTriggerQueue;
1095 }
1096
1097 transition(B_PM, ProbeAcksComplete, B_M){} {
1098 sf_setForwardReqTime;
1099 pt_popTriggerQueue;
1100 }
1101
1102 transition(BS_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
1103 sf_setForwardReqTime;
1104 s_sendResponseS;
1105 wd_writeBackData;
1106 alwt_allocateL3BlockOnWT;
1107 dt_deallocateTBE;
1108 pt_popTriggerQueue;
1109 }
1110
1111 transition(BM_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
1112 sf_setForwardReqTime;
1113 m_sendResponseM;
1114 wd_writeBackData;
1115 alwt_allocateL3BlockOnWT;
1116 dt_deallocateTBE;
1117 pt_popTriggerQueue;
1118 }
1119
1120 transition(B_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} {
1121 sf_setForwardReqTime;
1122 es_sendResponseES;
1123 wd_writeBackData;
1124 alwt_allocateL3BlockOnWT;
1125 dt_deallocateTBE;
1126 pt_popTriggerQueue;
1127 }
1128
1129 transition(BP, ProbeAcksComplete, B){L3TagArrayWrite, L3TagArrayWrite} {
1130 sf_setForwardReqTime;
1131 c_sendResponseCtoD;
1132 wd_writeBackData;
1133 alwt_allocateL3BlockOnWT;
1134 dt_deallocateTBE;
1135 pt_popTriggerQueue;
1136 }
1137 }