This patch removes the WARN_* and ERROR_* from src/mem/ruby/common/Debug.hh file...
[gem5.git] / src / mem / protocol / MOESI_hammer-dir.sm
1 /*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * Copyright (c) 2009 Advanced Micro Devices, Inc.
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 * AMD's contributions to the MOESI hammer protocol do not constitute an
30 * endorsement of its similarity to any AMD products.
31 *
32 * Authors: Milo Martin
33 * Brad Beckmann
34 */
35
36 machine(Directory, "AMD Hammer-like protocol")
37 : DirectoryMemory * directory,
38 CacheMemory * probeFilter,
39 MemoryControl * memBuffer,
40 int memory_controller_latency = 2,
41 bool probe_filter_enabled = false
42 {
43
44 MessageBuffer forwardFromDir, network="To", virtual_network="3", ordered="false";
45 MessageBuffer responseFromDir, network="To", virtual_network="4", ordered="false";
46 //
47 // For a finite buffered network, note that the DMA response network only
48 // works at this relatively lower numbered (lower priority) virtual network
49 // because the trigger queue decouples cache responses from DMA responses.
50 //
51 MessageBuffer dmaResponseFromDir, network="To", virtual_network="1", ordered="true";
52
53 MessageBuffer unblockToDir, network="From", virtual_network="5", ordered="false";
54 MessageBuffer responseToDir, network="From", virtual_network="4", ordered="false";
55 MessageBuffer requestToDir, network="From", virtual_network="2", ordered="false", recycle_latency="1";
56 MessageBuffer dmaRequestToDir, network="From", virtual_network="0", ordered="true";
57
58 // STATES
59 enumeration(State, desc="Directory states", default="Directory_State_E") {
60 // Base states
61 NX, desc="Not Owner, probe filter entry exists, block in O at Owner";
62 NO, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
63 S, desc="Data clean, probe filter entry exists pointing to the current owner";
64 O, desc="Data clean, probe filter entry exists";
65 E, desc="Exclusive Owner, no probe filter entry";
66
67 O_R, desc="Was data Owner, replacing probe filter entry";
68 S_R, desc="Was Not Owner or Sharer, replacing probe filter entry";
69 NO_R, desc="Was Not Owner or Sharer, replacing probe filter entry";
70
71 NO_B, "NO^B", desc="Not Owner, Blocked";
72 NO_B_X, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
73 NO_B_S, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
74 NO_B_S_W, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
75 O_B, "O^B", desc="Owner, Blocked";
76 NO_B_W, desc="Not Owner, Blocked, waiting for Dram";
77 O_B_W, desc="Owner, Blocked, waiting for Dram";
78 NO_W, desc="Not Owner, waiting for Dram";
79 O_W, desc="Owner, waiting for Dram";
80 NO_DW_B_W, desc="Not Owner, Dma Write waiting for Dram and cache responses";
81 NO_DR_B_W, desc="Not Owner, Dma Read waiting for Dram and cache responses";
82 NO_DR_B_D, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
83 NO_DR_B, desc="Not Owner, Dma Read waiting for cache responses";
84 NO_DW_W, desc="Not Owner, Dma Write waiting for Dram";
85 O_DR_B_W, desc="Owner, Dma Read waiting for Dram and cache responses";
86 O_DR_B, desc="Owner, Dma Read waiting for cache responses";
87 WB, desc="Blocked on a writeback";
88 WB_O_W, desc="Blocked on memory write, will go to O";
89 WB_E_W, desc="Blocked on memory write, will go to E";
90 }
91
92 // Events
93 enumeration(Event, desc="Directory events") {
94 GETX, desc="A GETX arrives";
95 GETS, desc="A GETS arrives";
96 PUT, desc="A PUT arrives";
97 Unblock, desc="An unblock message arrives";
98 UnblockS, desc="An unblock message arrives";
99 UnblockM, desc="An unblock message arrives";
100 Writeback_Clean, desc="The final part of a PutX (no data)";
101 Writeback_Dirty, desc="The final part of a PutX (data)";
102 Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)";
103 Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)";
104
105 // Probe filter
106 Pf_Replacement, desc="probe filter replacement";
107
108 // DMA requests
109 DMA_READ, desc="A DMA Read memory request";
110 DMA_WRITE, desc="A DMA Write memory request";
111
112 // Memory Controller
113 Memory_Data, desc="Fetched data from memory arrives";
114 Memory_Ack, desc="Writeback Ack from memory arrives";
115
116 // Cache responses required to handle DMA
117 Ack, desc="Received an ack message";
118 Shared_Ack, desc="Received an ack message, responder has a shared copy";
119 Shared_Data, desc="Received a data message, responder has a shared copy";
120 Data, desc="Received a data message, responder had a owner or exclusive copy, they gave it to us";
121 Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us";
122
123 // Triggers
124 All_acks_and_shared_data, desc="Received shared data and message acks";
125 All_acks_and_owner_data, desc="Received shared data and message acks";
126 All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy";
127 All_Unblocks, desc="Received all unblocks for a merged gets request";
128 }
129
130 // TYPES
131
132 // DirectoryEntry
133 structure(Entry, desc="...", interface="AbstractEntry") {
134 State DirectoryState, desc="Directory state";
135 DataBlock DataBlk, desc="data for the block";
136 }
137
138 // ProbeFilterEntry
139 structure(PfEntry, desc="...", interface="AbstractCacheEntry") {
140 State PfState, desc="Directory state";
141 MachineID Owner, desc="Owner node";
142 DataBlock DataBlk, desc="data for the block";
143 }
144
145 // TBE entries for DMA requests
146 structure(TBE, desc="TBE entries for outstanding DMA requests") {
147 Address PhysicalAddress, desc="physical address";
148 State TBEState, desc="Transient State";
149 CoherenceResponseType ResponseType, desc="The type for the subsequent response message";
150 int Acks, default="0", desc="The number of acks that the waiting response represents";
151 DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory";
152 DataBlock DataBlk, desc="The current view of system memory";
153 int Len, desc="...";
154 MachineID DmaRequestor, desc="DMA requestor";
155 NetDest GetSRequestors, desc="GETS merged requestors";
156 int NumPendingMsgs, desc="Number of pending acks/messages";
157 bool CacheDirty, default="false", desc="Indicates whether a cache has responded with dirty data";
158 bool Sharers, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
159 bool Owned, default="false", desc="Indicates whether a cache has indicated it is currently a sharer";
160 }
161
162 external_type(TBETable) {
163 TBE lookup(Address);
164 void allocate(Address);
165 void deallocate(Address);
166 bool isPresent(Address);
167 }
168
169 // ** OBJECTS **
170
171 TBETable TBEs, template_hack="<Directory_TBE>";
172
173 Entry getDirectoryEntry(Address addr), return_by_ref="yes" {
174 return static_cast(Entry, directory[addr]);
175 }
176
177 PfEntry getPfEntry(Address addr), return_by_ref="yes" {
178 return static_cast(PfEntry, probeFilter[addr]);
179 }
180
181 State getState(Address addr) {
182 if (TBEs.isPresent(addr)) {
183 return TBEs[addr].TBEState;
184 } else {
185 if (probe_filter_enabled) {
186 if (probeFilter.isTagPresent(addr)) {
187 assert(getPfEntry(addr).PfState == getDirectoryEntry(addr).DirectoryState);
188 } else {
189 assert(getDirectoryEntry(addr).DirectoryState == State:E);
190 }
191 }
192 return getDirectoryEntry(addr).DirectoryState;
193 }
194 }
195
196 void setState(Address addr, State state) {
197 if (TBEs.isPresent(addr)) {
198 TBEs[addr].TBEState := state;
199 }
200 if (probe_filter_enabled) {
201 if (probeFilter.isTagPresent(addr)) {
202 getPfEntry(addr).PfState := state;
203 }
204 if (state == State:NX || state == State:NO || state == State:S || state == State:O) {
205 assert(probeFilter.isTagPresent(addr));
206 }
207 }
208 if (state == State:E || state == State:NX || state == State:NO || state == State:S ||
209 state == State:O) {
210 assert(TBEs.isPresent(addr) == false);
211 }
212 getDirectoryEntry(addr).DirectoryState := state;
213 }
214
215 Event cache_request_to_event(CoherenceRequestType type) {
216 if (type == CoherenceRequestType:GETS) {
217 return Event:GETS;
218 } else if (type == CoherenceRequestType:GETX) {
219 return Event:GETX;
220 } else {
221 error("Invalid CoherenceRequestType");
222 }
223 }
224
225 MessageBuffer triggerQueue, ordered="true";
226
227 // ** OUT_PORTS **
228 out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
229 out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
230 out_port(responseNetwork_out, ResponseMsg, responseFromDir);
231 out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir);
232 out_port(triggerQueue_out, TriggerMsg, triggerQueue);
233
234 //
235 // Memory buffer for memory controller to DIMM communication
236 //
237 out_port(memQueue_out, MemoryMsg, memBuffer);
238
239 // ** IN_PORTS **
240
241 // Trigger Queue
242 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) {
243 if (triggerQueue_in.isReady()) {
244 peek(triggerQueue_in, TriggerMsg) {
245 if (in_msg.Type == TriggerType:ALL_ACKS) {
246 trigger(Event:All_acks_and_owner_data, in_msg.Address);
247 } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) {
248 trigger(Event:All_acks_and_shared_data, in_msg.Address);
249 } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) {
250 trigger(Event:All_acks_and_data_no_sharers, in_msg.Address);
251 } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) {
252 trigger(Event:All_Unblocks, in_msg.Address);
253 } else {
254 error("Unexpected message");
255 }
256 }
257 }
258 }
259
260 in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) {
261 if (unblockNetwork_in.isReady()) {
262 peek(unblockNetwork_in, ResponseMsg) {
263 if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
264 trigger(Event:Unblock, in_msg.Address);
265 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
266 trigger(Event:UnblockS, in_msg.Address);
267 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) {
268 trigger(Event:UnblockM, in_msg.Address);
269 } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) {
270 trigger(Event:Writeback_Clean, in_msg.Address);
271 } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) {
272 trigger(Event:Writeback_Dirty, in_msg.Address);
273 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) {
274 trigger(Event:Writeback_Exclusive_Clean, in_msg.Address);
275 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
276 trigger(Event:Writeback_Exclusive_Dirty, in_msg.Address);
277 } else {
278 error("Invalid message");
279 }
280 }
281 }
282 }
283
284 // Response Network
285 in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) {
286 if (responseToDir_in.isReady()) {
287 peek(responseToDir_in, ResponseMsg) {
288 if (in_msg.Type == CoherenceResponseType:ACK) {
289 trigger(Event:Ack, in_msg.Address);
290 } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) {
291 trigger(Event:Shared_Ack, in_msg.Address);
292 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) {
293 trigger(Event:Shared_Data, in_msg.Address);
294 } else if (in_msg.Type == CoherenceResponseType:DATA) {
295 trigger(Event:Data, in_msg.Address);
296 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
297 trigger(Event:Exclusive_Data, in_msg.Address);
298 } else {
299 error("Unexpected message");
300 }
301 }
302 }
303 }
304
305 // off-chip memory request/response is done
306 in_port(memQueue_in, MemoryMsg, memBuffer, rank=2) {
307 if (memQueue_in.isReady()) {
308 peek(memQueue_in, MemoryMsg) {
309 if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
310 trigger(Event:Memory_Data, in_msg.Address);
311 } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
312 trigger(Event:Memory_Ack, in_msg.Address);
313 } else {
314 DPRINTF(RubySlicc, "%d\n", in_msg.Type);
315 error("Invalid message");
316 }
317 }
318 }
319 }
320
321 in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) {
322 if (requestQueue_in.isReady()) {
323 peek(requestQueue_in, RequestMsg) {
324 if (in_msg.Type == CoherenceRequestType:PUT) {
325 trigger(Event:PUT, in_msg.Address);
326 } else {
327 if (probe_filter_enabled) {
328 if (probeFilter.isTagPresent(in_msg.Address)) {
329 trigger(cache_request_to_event(in_msg.Type), in_msg.Address);
330 } else {
331 if (probeFilter.cacheAvail(in_msg.Address)) {
332 trigger(cache_request_to_event(in_msg.Type), in_msg.Address);
333 } else {
334 trigger(Event:Pf_Replacement, probeFilter.cacheProbe(in_msg.Address));
335 }
336 }
337 } else {
338 trigger(cache_request_to_event(in_msg.Type), in_msg.Address);
339 }
340 }
341 }
342 }
343 }
344
345 in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) {
346 if (dmaRequestQueue_in.isReady()) {
347 peek(dmaRequestQueue_in, DMARequestMsg) {
348 if (in_msg.Type == DMARequestType:READ) {
349 trigger(Event:DMA_READ, in_msg.LineAddress);
350 } else if (in_msg.Type == DMARequestType:WRITE) {
351 trigger(Event:DMA_WRITE, in_msg.LineAddress);
352 } else {
353 error("Invalid message");
354 }
355 }
356 }
357 }
358
359 // Actions
360
361 action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) {
362 if (probe_filter_enabled) {
363 assert(probeFilter.isTagPresent(address));
364 probeFilter.setMRU(address);
365 }
366 }
367
368 action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") {
369 if (probe_filter_enabled) {
370 assert(probeFilter.isTagPresent(address));
371 peek(unblockNetwork_in, ResponseMsg) {
372 assert(getPfEntry(address).Owner != in_msg.Sender);
373 }
374 }
375 }
376
377 action(uo_updateOwnerIfPf, "uo", desc="update owner") {
378 if (probe_filter_enabled) {
379 assert(probeFilter.isTagPresent(address));
380 peek(unblockNetwork_in, ResponseMsg) {
381 getPfEntry(address).Owner := in_msg.Sender;
382 }
383 }
384 }
385
386 action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
387 peek(requestQueue_in, RequestMsg) {
388 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
389 out_msg.Address := address;
390 out_msg.Type := CoherenceRequestType:WB_ACK;
391 out_msg.Requestor := in_msg.Requestor;
392 out_msg.Destination.add(in_msg.Requestor);
393 out_msg.MessageSize := MessageSizeType:Writeback_Control;
394 }
395 }
396 }
397
398 action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
399 peek(requestQueue_in, RequestMsg) {
400 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
401 out_msg.Address := address;
402 out_msg.Type := CoherenceRequestType:WB_NACK;
403 out_msg.Requestor := in_msg.Requestor;
404 out_msg.Destination.add(in_msg.Requestor);
405 out_msg.MessageSize := MessageSizeType:Writeback_Control;
406 }
407 }
408 }
409
410 action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") {
411 if (probe_filter_enabled) {
412 peek(requestQueue_in, RequestMsg) {
413 probeFilter.allocate(address, new PfEntry);
414 getPfEntry(in_msg.Address).Owner := in_msg.Requestor;
415 }
416 }
417 }
418
419 action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") {
420 if (probe_filter_enabled) {
421 probeFilter.deallocate(address);
422 }
423 }
424
425 action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") {
426 if (probe_filter_enabled && probeFilter.isTagPresent(address)) {
427 probeFilter.deallocate(address);
428 }
429 }
430
431 action(v_allocateTBE, "v", desc="Allocate TBE") {
432 peek(requestQueue_in, RequestMsg) {
433 TBEs.allocate(address);
434 TBEs[address].PhysicalAddress := address;
435 TBEs[address].ResponseType := CoherenceResponseType:NULL;
436 }
437 }
438
439 action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") {
440 peek(dmaRequestQueue_in, DMARequestMsg) {
441 TBEs.allocate(address);
442 TBEs[address].DmaDataBlk := in_msg.DataBlk;
443 TBEs[address].PhysicalAddress := in_msg.PhysicalAddress;
444 TBEs[address].Len := in_msg.Len;
445 TBEs[address].DmaRequestor := in_msg.Requestor;
446 TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
447 //
448 // One ack for each last-level cache
449 //
450 TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache);
451 //
452 // Assume initially that the caches store a clean copy and that memory
453 // will provide the data
454 //
455 TBEs[address].CacheDirty := false;
456 }
457 }
458
459 action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") {
460 TBEs[address].NumPendingMsgs := machineCount(MachineType:L1Cache);
461 }
462
463 action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") {
464 TBEs[address].NumPendingMsgs := 1;
465 }
466
467 action(w_deallocateTBE, "w", desc="Deallocate TBE") {
468 TBEs.deallocate(address);
469 }
470
471 action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") {
472 TBEs[address].Acks := 1;
473 }
474
475 action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") {
476 if (probe_filter_enabled) {
477 TBEs[address].Acks := machineCount(MachineType:L1Cache);
478 } else {
479 TBEs[address].Acks := 1;
480 }
481 }
482
483 action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") {
484 peek(responseToDir_in, ResponseMsg) {
485 assert(in_msg.Acks > 0);
486 DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs);
487 //
488 // Note that cache data responses will have an ack count of 2. However,
489 // directory DMA requests must wait for acks from all LLC caches, so
490 // only decrement by 1.
491 //
492 TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1;
493 DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs);
494 }
495 }
496
497 action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") {
498 peek(unblockNetwork_in, ResponseMsg) {
499 assert(in_msg.Type == CoherenceResponseType:UNBLOCKS);
500 DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs);
501 //
502 // Note that cache data responses will have an ack count of 2. However,
503 // directory DMA requests must wait for acks from all LLC caches, so
504 // only decrement by 1.
505 //
506 TBEs[address].NumPendingMsgs := TBEs[address].NumPendingMsgs - 1;
507 DPRINTF(RubySlicc, "%d\n", TBEs[address].NumPendingMsgs);
508 }
509 }
510
511 action(n_popResponseQueue, "n", desc="Pop response queue") {
512 responseToDir_in.dequeue();
513 }
514
515 action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") {
516 if (TBEs[address].NumPendingMsgs == 0) {
517 enqueue(triggerQueue_out, TriggerMsg) {
518 out_msg.Address := address;
519 if (TBEs[address].Sharers) {
520 if (TBEs[address].Owned) {
521 out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS;
522 } else {
523 out_msg.Type := TriggerType:ALL_ACKS;
524 }
525 } else {
526 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
527 }
528 }
529 }
530 }
531
532 action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") {
533 if (TBEs[address].NumPendingMsgs == 0) {
534 enqueue(triggerQueue_out, TriggerMsg) {
535 out_msg.Address := address;
536 out_msg.Type := TriggerType:ALL_UNBLOCKS;
537 }
538 }
539 }
540
541 action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") {
542 TBEs[address].NumPendingMsgs := TBEs[address].GetSRequestors.count();
543 }
544
545 action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") {
546 if (probe_filter_enabled) {
547 TBEs[address].NumPendingMsgs := 0;
548 }
549 }
550
551 action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") {
552 if (TBEs[address].NumPendingMsgs == 0) {
553 assert(probe_filter_enabled);
554 enqueue(triggerQueue_out, TriggerMsg) {
555 out_msg.Address := address;
556 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS;
557 }
558 }
559 }
560
561 action(d_sendData, "d", desc="Send data to requestor") {
562 peek(memQueue_in, MemoryMsg) {
563 enqueue(responseNetwork_out, ResponseMsg, latency="1") {
564 out_msg.Address := address;
565 out_msg.Type := TBEs[address].ResponseType;
566 out_msg.Sender := machineID;
567 out_msg.Destination.add(in_msg.OriginalRequestorMachId);
568 out_msg.DataBlk := in_msg.DataBlk;
569 DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk);
570 out_msg.Dirty := false; // By definition, the block is now clean
571 out_msg.Acks := TBEs[address].Acks;
572 DPRINTF(RubySlicc, "%d\n", out_msg.Acks);
573 assert(out_msg.Acks > 0);
574 out_msg.MessageSize := MessageSizeType:Response_Data;
575 }
576 }
577 }
578
579 action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") {
580 peek(memQueue_in, MemoryMsg) {
581 enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
582 out_msg.PhysicalAddress := address;
583 out_msg.LineAddress := address;
584 out_msg.Type := DMAResponseType:DATA;
585 //
586 // we send the entire data block and rely on the dma controller to
587 // split it up if need be
588 //
589 out_msg.DataBlk := in_msg.DataBlk;
590 out_msg.Destination.add(TBEs[address].DmaRequestor);
591 out_msg.MessageSize := MessageSizeType:Response_Data;
592 }
593 }
594 }
595
596 action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") {
597 peek(triggerQueue_in, TriggerMsg) {
598 enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
599 out_msg.PhysicalAddress := address;
600 out_msg.LineAddress := address;
601 out_msg.Type := DMAResponseType:DATA;
602 //
603 // we send the entire data block and rely on the dma controller to
604 // split it up if need be
605 //
606 out_msg.DataBlk := TBEs[address].DataBlk;
607 out_msg.Destination.add(TBEs[address].DmaRequestor);
608 out_msg.MessageSize := MessageSizeType:Response_Data;
609 }
610 }
611 }
612
613 action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") {
614 enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="1") {
615 out_msg.PhysicalAddress := address;
616 out_msg.LineAddress := address;
617 out_msg.Type := DMAResponseType:ACK;
618 out_msg.Destination.add(TBEs[address].DmaRequestor);
619 out_msg.MessageSize := MessageSizeType:Writeback_Control;
620 }
621 }
622
623 action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") {
624 peek(requestQueue_in, RequestMsg) {
625 TBEs[address].ResponseType := CoherenceResponseType:DATA_EXCLUSIVE;
626 }
627 }
628
629 action(r_recordDataInTBE, "rt", desc="Record Data in TBE") {
630 peek(requestQueue_in, RequestMsg) {
631 TBEs[address].ResponseType := CoherenceResponseType:DATA;
632 }
633 }
634
635 action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") {
636 peek(requestQueue_in, RequestMsg) {
637 TBEs[address].GetSRequestors.add(in_msg.Requestor);
638 }
639 }
640
641 action(r_setSharerBit, "r", desc="We saw other sharers") {
642 TBEs[address].Sharers := true;
643 }
644
645 action(so_setOwnerBit, "so", desc="We saw other sharers") {
646 TBEs[address].Sharers := true;
647 TBEs[address].Owned := true;
648 }
649
650 action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
651 peek(requestQueue_in, RequestMsg) {
652 enqueue(memQueue_out, MemoryMsg, latency="1") {
653 out_msg.Address := address;
654 out_msg.Type := MemoryRequestType:MEMORY_READ;
655 out_msg.Sender := machineID;
656 out_msg.OriginalRequestorMachId := in_msg.Requestor;
657 out_msg.MessageSize := in_msg.MessageSize;
658 out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
659 DPRINTF(RubySlicc, "%s\n", out_msg);
660 }
661 }
662 }
663
664 action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") {
665 peek(dmaRequestQueue_in, DMARequestMsg) {
666 enqueue(memQueue_out, MemoryMsg, latency="1") {
667 out_msg.Address := address;
668 out_msg.Type := MemoryRequestType:MEMORY_READ;
669 out_msg.Sender := machineID;
670 out_msg.OriginalRequestorMachId := in_msg.Requestor;
671 out_msg.MessageSize := in_msg.MessageSize;
672 out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
673 DPRINTF(RubySlicc, "%s\n", out_msg);
674 }
675 }
676 }
677
678 action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") {
679 if ((machineCount(MachineType:L1Cache) > 1) && (TBEs[address].Acks <= 1)) {
680 peek(requestQueue_in, RequestMsg) {
681 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
682 out_msg.Address := address;
683 out_msg.Type := in_msg.Type;
684 out_msg.Requestor := in_msg.Requestor;
685 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
686 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
687 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
688 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
689 out_msg.ForwardRequestTime := get_time();
690 }
691 }
692 }
693 }
694
695 action(ia_invalidateAllRequest, "ia", desc="invalidate all copies") {
696 if (machineCount(MachineType:L1Cache) > 1) {
697 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
698 out_msg.Address := address;
699 out_msg.Type := CoherenceRequestType:INV;
700 out_msg.Requestor := machineID;
701 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
702 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
703 }
704 }
705 }
706
707 action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") {
708 if (machineCount(MachineType:L1Cache) > 1) {
709 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
710 out_msg.Address := address;
711 out_msg.Type := CoherenceRequestType:INV;
712 out_msg.Requestor := machineID;
713 out_msg.Destination.add(getPfEntry(address).Owner);
714 out_msg.MessageSize := MessageSizeType:Request_Control;
715 out_msg.DirectedProbe := true;
716 }
717 }
718 }
719
720 action(fb_forwardRequestBcast, "fb", desc="Forward requests to all nodes") {
721 if (machineCount(MachineType:L1Cache) > 1) {
722 peek(requestQueue_in, RequestMsg) {
723 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
724 out_msg.Address := address;
725 out_msg.Type := in_msg.Type;
726 out_msg.Requestor := in_msg.Requestor;
727 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
728 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
729 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
730 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
731 out_msg.ForwardRequestTime := get_time();
732 }
733 }
734 }
735 }
736
737 action(fr_forwardMergeReadRequestsToOwner, "frr", desc="Forward coalesced read request to owner") {
738 assert(machineCount(MachineType:L1Cache) > 1);
739 //
740 // Fixme! The unblock network should not stall on the forward network. Add a trigger queue to
741 // decouple the two.
742 //
743 peek(unblockNetwork_in, ResponseMsg) {
744 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
745 out_msg.Address := address;
746 out_msg.Type := CoherenceRequestType:MERGED_GETS;
747 out_msg.MergedRequestors := TBEs[address].GetSRequestors;
748 if (in_msg.Type == CoherenceResponseType:UNBLOCKS) {
749 out_msg.Destination.add(in_msg.CurOwner);
750 } else {
751 out_msg.Destination.add(in_msg.Sender);
752 }
753 out_msg.MessageSize := MessageSizeType:Request_Control;
754 out_msg.InitialRequestTime := zero_time();
755 out_msg.ForwardRequestTime := get_time();
756 }
757 }
758 }
759
760 action(fc_forwardRequestConditionalOwner, "fc", desc="Forward request to one or more nodes") {
761 assert(machineCount(MachineType:L1Cache) > 1);
762 if (probe_filter_enabled) {
763 peek(requestQueue_in, RequestMsg) {
764 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
765 out_msg.Address := address;
766 out_msg.Type := in_msg.Type;
767 out_msg.Requestor := in_msg.Requestor;
768 out_msg.Destination.add(getPfEntry(address).Owner);
769 out_msg.MessageSize := MessageSizeType:Request_Control;
770 out_msg.DirectedProbe := true;
771 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
772 out_msg.ForwardRequestTime := get_time();
773 }
774 }
775 } else {
776 peek(requestQueue_in, RequestMsg) {
777 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
778 out_msg.Address := address;
779 out_msg.Type := in_msg.Type;
780 out_msg.Requestor := in_msg.Requestor;
781 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches
782 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
783 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
784 out_msg.InitialRequestTime := in_msg.InitialRequestTime;
785 out_msg.ForwardRequestTime := get_time();
786 }
787 }
788 }
789 }
790
791 action(f_forwardWriteFromDma, "fw", desc="Forward requests") {
792 if (TBEs[address].NumPendingMsgs > 0) {
793 peek(dmaRequestQueue_in, DMARequestMsg) {
794 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
795 out_msg.Address := address;
796 out_msg.Type := CoherenceRequestType:GETX;
797 //
798 // Send to all L1 caches, since the requestor is the memory controller
799 // itself
800 //
801 out_msg.Requestor := machineID;
802 out_msg.Destination.broadcast(MachineType:L1Cache);
803 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
804 }
805 }
806 }
807 }
808
809 action(f_forwardReadFromDma, "fr", desc="Forward requests") {
810 if (TBEs[address].NumPendingMsgs > 0) {
811 peek(dmaRequestQueue_in, DMARequestMsg) {
812 enqueue(forwardNetwork_out, RequestMsg, latency=memory_controller_latency) {
813 out_msg.Address := address;
814 out_msg.Type := CoherenceRequestType:GETS;
815 //
816 // Send to all L1 caches, since the requestor is the memory controller
817 // itself
818 //
819 out_msg.Requestor := machineID;
820 out_msg.Destination.broadcast(MachineType:L1Cache);
821 out_msg.MessageSize := MessageSizeType:Broadcast_Control;
822 }
823 }
824 }
825 }
826
827 action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
828 requestQueue_in.dequeue();
829 }
830
831 action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
832 peek(unblockNetwork_in, ResponseMsg) {
833 APPEND_TRANSITION_COMMENT(in_msg.Sender);
834 }
835 unblockNetwork_in.dequeue();
836 }
837
838 action(k_wakeUpDependents, "k", desc="wake-up dependents") {
839 wake_up_dependents(address);
840 }
841
842 action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
843 memQueue_in.dequeue();
844 }
845
846 action(g_popTriggerQueue, "g", desc="Pop trigger queue") {
847 triggerQueue_in.dequeue();
848 }
849
850 action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") {
851 dmaRequestQueue_in.dequeue();
852 }
853
854 action(zd_stallAndWaitDMARequest, "zd", desc="Stall and wait the dma request queue") {
855 peek(dmaRequestQueue_in, DMARequestMsg) {
856 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
857 }
858 stall_and_wait(dmaRequestQueue_in, address);
859 }
860
861 action(r_recordMemoryData, "rd", desc="record data from memory to TBE") {
862 peek(memQueue_in, MemoryMsg) {
863 if (TBEs[address].CacheDirty == false) {
864 TBEs[address].DataBlk := in_msg.DataBlk;
865 }
866 }
867 }
868
869 action(r_recordCacheData, "rc", desc="record data from cache response to TBE") {
870 peek(responseToDir_in, ResponseMsg) {
871 TBEs[address].CacheDirty := true;
872 TBEs[address].DataBlk := in_msg.DataBlk;
873 }
874 }
875
876 action(wr_writeResponseDataToMemory, "wr", desc="Write response data to memory") {
877 peek(responseToDir_in, ResponseMsg) {
878 getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
879 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
880 in_msg.Address, in_msg.DataBlk);
881 }
882 }
883
884 action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
885 peek(unblockNetwork_in, ResponseMsg) {
886 assert(in_msg.Dirty);
887 assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
888 getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
889 DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
890 in_msg.Address, in_msg.DataBlk);
891 }
892 }
893
894 action(dwt_writeDmaDataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
895 DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
896 getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk;
897 DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
898 getDirectoryEntry(address).DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len);
899 DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
900 }
901
902 action(wdt_writeDataFromTBE, "wdt", desc="DMA Write data to memory from TBE") {
903 DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
904 getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk;
905 DPRINTF(RubySlicc, "%s\n", getDirectoryEntry(address).DataBlk);
906 }
907
908 action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") {
909 assert(TBEs[address].CacheDirty);
910 }
911
912 action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") {
913 if (probe_filter_enabled) {
914 peek(requestQueue_in, RequestMsg) {
915 assert(getPfEntry(address).Owner != in_msg.Requestor);
916 }
917 }
918 }
919
920 action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
921 peek(unblockNetwork_in, ResponseMsg) {
922 enqueue(memQueue_out, MemoryMsg, latency="1") {
923 out_msg.Address := address;
924 out_msg.Type := MemoryRequestType:MEMORY_WB;
925 DPRINTF(RubySlicc, "%s\n", out_msg);
926 }
927 }
928 }
929
930 action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") {
931 enqueue(memQueue_out, MemoryMsg, latency="1") {
932 out_msg.Address := address;
933 out_msg.Type := MemoryRequestType:MEMORY_WB;
934 // first, initialize the data blk to the current version of system memory
935 out_msg.DataBlk := TBEs[address].DataBlk;
936 // then add the dma write data
937 out_msg.DataBlk.copyPartial(TBEs[address].DmaDataBlk, addressOffset(TBEs[address].PhysicalAddress), TBEs[address].Len);
938 DPRINTF(RubySlicc, "%s\n", out_msg);
939 }
940 }
941
942 action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
943 peek(unblockNetwork_in, ResponseMsg) {
944 assert(in_msg.Dirty == false);
945 assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
946
947 // NOTE: The following check would not be valid in a real
948 // implementation. We include the data in the "dataless"
949 // message so we can assert the clean data matches the datablock
950 // in memory
951 assert(getDirectoryEntry(address).DataBlk == in_msg.DataBlk);
952 }
953 }
954
955 action(z_stallAndWaitRequest, "z", desc="Recycle the request queue") {
956 peek(requestQueue_in, RequestMsg) {
957 APPEND_TRANSITION_COMMENT(in_msg.Requestor);
958 }
959 stall_and_wait(requestQueue_in, address);
960 }
961
962 // TRANSITIONS
963
964 // Transitions out of E state
965 transition(E, GETX, NO_B_W) {
966 pfa_probeFilterAllocate;
967 v_allocateTBE;
968 rx_recordExclusiveInTBE;
969 saa_setAcksToAllIfPF;
970 qf_queueMemoryFetchRequest;
971 fn_forwardRequestIfNecessary;
972 i_popIncomingRequestQueue;
973 }
974
975 transition(E, GETS, NO_B_W) {
976 pfa_probeFilterAllocate;
977 v_allocateTBE;
978 rx_recordExclusiveInTBE;
979 saa_setAcksToAllIfPF;
980 qf_queueMemoryFetchRequest;
981 fn_forwardRequestIfNecessary;
982 i_popIncomingRequestQueue;
983 }
984
985 transition(E, DMA_READ, NO_DR_B_W) {
986 vd_allocateDmaRequestInTBE;
987 qd_queueMemoryRequestFromDmaRead;
988 spa_setPendingAcksToZeroIfPF;
989 f_forwardReadFromDma;
990 p_popDmaRequestQueue;
991 }
992
993 transition(E, DMA_WRITE, NO_DW_B_W) {
994 vd_allocateDmaRequestInTBE;
995 spa_setPendingAcksToZeroIfPF;
996 sc_signalCompletionIfPF;
997 f_forwardWriteFromDma;
998 p_popDmaRequestQueue;
999 }
1000
1001 // Transitions out of O state
1002 transition(O, GETX, NO_B_W) {
1003 r_setMRU;
1004 v_allocateTBE;
1005 r_recordDataInTBE;
1006 sa_setAcksToOne;
1007 qf_queueMemoryFetchRequest;
1008 fb_forwardRequestBcast;
1009 i_popIncomingRequestQueue;
1010 }
1011
1012 // This transition is dumb, if a shared copy exists on-chip, then that should
1013 // provide data, not slow off-chip dram. The problem is that the current
1014 // caches don't provide data in S state
1015 transition(O, GETS, O_B_W) {
1016 r_setMRU;
1017 v_allocateTBE;
1018 r_recordDataInTBE;
1019 saa_setAcksToAllIfPF;
1020 qf_queueMemoryFetchRequest;
1021 fn_forwardRequestIfNecessary;
1022 i_popIncomingRequestQueue;
1023 }
1024
1025 transition(O, DMA_READ, O_DR_B_W) {
1026 vd_allocateDmaRequestInTBE;
1027 spa_setPendingAcksToZeroIfPF;
1028 qd_queueMemoryRequestFromDmaRead;
1029 f_forwardReadFromDma;
1030 p_popDmaRequestQueue;
1031 }
1032
1033 transition(O, Pf_Replacement, O_R) {
1034 v_allocateTBE;
1035 pa_setPendingMsgsToAll;
1036 ia_invalidateAllRequest;
1037 pfd_probeFilterDeallocate;
1038 }
1039
1040 transition(S, Pf_Replacement, S_R) {
1041 v_allocateTBE;
1042 pa_setPendingMsgsToAll;
1043 ia_invalidateAllRequest;
1044 pfd_probeFilterDeallocate;
1045 }
1046
1047 transition(NO, Pf_Replacement, NO_R) {
1048 v_allocateTBE;
1049 po_setPendingMsgsToOne;
1050 io_invalidateOwnerRequest;
1051 pfd_probeFilterDeallocate;
1052 }
1053
1054 transition(NX, Pf_Replacement, NO_R) {
1055 v_allocateTBE;
1056 pa_setPendingMsgsToAll;
1057 ia_invalidateAllRequest;
1058 pfd_probeFilterDeallocate;
1059 }
1060
1061 transition({O, S, NO, NX}, DMA_WRITE, NO_DW_B_W) {
1062 vd_allocateDmaRequestInTBE;
1063 f_forwardWriteFromDma;
1064 p_popDmaRequestQueue;
1065 }
1066
1067 // Transitions out of NO state
1068 transition(NX, GETX, NO_B) {
1069 r_setMRU;
1070 fb_forwardRequestBcast;
1071 i_popIncomingRequestQueue;
1072 }
1073
1074 // Transitions out of NO state
1075 transition(NO, GETX, NO_B) {
1076 r_setMRU;
1077 ano_assertNotOwner;
1078 fc_forwardRequestConditionalOwner;
1079 i_popIncomingRequestQueue;
1080 }
1081
1082 transition(S, GETX, NO_B) {
1083 r_setMRU;
1084 fb_forwardRequestBcast;
1085 i_popIncomingRequestQueue;
1086 }
1087
1088 transition(S, GETS, NO_B) {
1089 r_setMRU;
1090 ano_assertNotOwner;
1091 fb_forwardRequestBcast;
1092 i_popIncomingRequestQueue;
1093 }
1094
1095 transition({NX, NO}, GETS, NO_B) {
1096 r_setMRU;
1097 ano_assertNotOwner;
1098 fc_forwardRequestConditionalOwner;
1099 i_popIncomingRequestQueue;
1100 }
1101
1102 transition({NO, NX, S}, PUT, WB) {
1103 //
1104 // note that the PUT requestor may not be the current owner if an invalidate
1105 // raced with PUT
1106 //
1107 a_sendWriteBackAck;
1108 i_popIncomingRequestQueue;
1109 }
1110
1111 transition({NO, NX, S}, DMA_READ, NO_DR_B_D) {
1112 vd_allocateDmaRequestInTBE;
1113 f_forwardReadFromDma;
1114 p_popDmaRequestQueue;
1115 }
1116
1117 // Nack PUT requests when races cause us to believe we own the data
1118 transition({O, E}, PUT) {
1119 b_sendWriteBackNack;
1120 i_popIncomingRequestQueue;
1121 }
1122
1123 // Blocked transient states
1124 transition({NO_B_X, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1125 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1126 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R},
1127 {GETS, GETX, PUT, Pf_Replacement}) {
1128 z_stallAndWaitRequest;
1129 }
1130
1131 transition(NO_B, GETX, NO_B_X) {
1132 z_stallAndWaitRequest;
1133 }
1134
1135 transition(NO_B, {PUT, Pf_Replacement}) {
1136 z_stallAndWaitRequest;
1137 }
1138
1139 transition(NO_B_S, {GETX, PUT, Pf_Replacement}) {
1140 z_stallAndWaitRequest;
1141 }
1142
1143 transition({NO_B, NO_B_S, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D,
1144 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W,
1145 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R},
1146 {DMA_READ, DMA_WRITE}) {
1147 zd_stallAndWaitDMARequest;
1148 }
1149
1150 // merge GETS into one response
1151 transition(NO_B, GETS, NO_B_S) {
1152 v_allocateTBE;
1153 rs_recordGetSRequestor;
1154 i_popIncomingRequestQueue;
1155 }
1156
1157 transition(NO_B_S, GETS) {
1158 rs_recordGetSRequestor;
1159 i_popIncomingRequestQueue;
1160 }
1161
1162 // unblock responses
1163 transition({NO_B, NO_B_X}, UnblockS, NX) {
1164 k_wakeUpDependents;
1165 j_popIncomingUnblockQueue;
1166 }
1167
1168 transition({NO_B, NO_B_X}, UnblockM, NO) {
1169 uo_updateOwnerIfPf;
1170 k_wakeUpDependents;
1171 j_popIncomingUnblockQueue;
1172 }
1173
1174 transition(NO_B_S, UnblockS, NO_B_S_W) {
1175 fr_forwardMergeReadRequestsToOwner;
1176 sp_setPendingMsgsToMergedSharers;
1177 j_popIncomingUnblockQueue;
1178 }
1179
1180 transition(NO_B_S, UnblockM, NO_B_S_W) {
1181 uo_updateOwnerIfPf;
1182 fr_forwardMergeReadRequestsToOwner;
1183 sp_setPendingMsgsToMergedSharers;
1184 j_popIncomingUnblockQueue;
1185 }
1186
1187 transition(NO_B_S_W, UnblockS) {
1188 mu_decrementNumberOfUnblocks;
1189 os_checkForMergedGetSCompletion;
1190 j_popIncomingUnblockQueue;
1191 }
1192
1193 transition(NO_B_S_W, All_Unblocks, NX) {
1194 w_deallocateTBE;
1195 k_wakeUpDependents;
1196 g_popTriggerQueue;
1197 }
1198
1199 transition(O_B, UnblockS, O) {
1200 k_wakeUpDependents;
1201 j_popIncomingUnblockQueue;
1202 }
1203
1204 transition(NO_B_W, Memory_Data, NO_B) {
1205 d_sendData;
1206 w_deallocateTBE;
1207 l_popMemQueue;
1208 }
1209
1210 transition(NO_DR_B_W, Memory_Data, NO_DR_B) {
1211 r_recordMemoryData;
1212 o_checkForCompletion;
1213 l_popMemQueue;
1214 }
1215
1216 transition(O_DR_B_W, Memory_Data, O_DR_B) {
1217 r_recordMemoryData;
1218 dr_sendDmaData;
1219 o_checkForCompletion;
1220 l_popMemQueue;
1221 }
1222
1223 transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) {
1224 m_decrementNumberOfMessages;
1225 o_checkForCompletion;
1226 n_popResponseQueue;
1227 }
1228
1229 transition({O_R, S_R, NO_R}, Ack) {
1230 m_decrementNumberOfMessages;
1231 o_checkForCompletion;
1232 n_popResponseQueue;
1233 }
1234
1235 transition(S_R, Data) {
1236 wr_writeResponseDataToMemory;
1237 m_decrementNumberOfMessages;
1238 o_checkForCompletion;
1239 n_popResponseQueue;
1240 }
1241
1242 transition(NO_R, {Data, Exclusive_Data}) {
1243 wr_writeResponseDataToMemory;
1244 m_decrementNumberOfMessages;
1245 o_checkForCompletion;
1246 n_popResponseQueue;
1247 }
1248
1249 transition({O_R, S_R, NO_R}, All_acks_and_data_no_sharers, E) {
1250 w_deallocateTBE;
1251 k_wakeUpDependents;
1252 g_popTriggerQueue;
1253 }
1254
1255 transition({NO_DR_B_W, O_DR_B_W}, Ack) {
1256 m_decrementNumberOfMessages;
1257 n_popResponseQueue;
1258 }
1259
1260 transition(NO_DR_B_W, Shared_Ack) {
1261 m_decrementNumberOfMessages;
1262 r_setSharerBit;
1263 n_popResponseQueue;
1264 }
1265
1266 transition(O_DR_B, Shared_Ack) {
1267 m_decrementNumberOfMessages;
1268 so_setOwnerBit;
1269 o_checkForCompletion;
1270 n_popResponseQueue;
1271 }
1272
1273 transition(O_DR_B_W, Shared_Ack) {
1274 m_decrementNumberOfMessages;
1275 so_setOwnerBit;
1276 n_popResponseQueue;
1277 }
1278
1279 transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) {
1280 m_decrementNumberOfMessages;
1281 r_setSharerBit;
1282 o_checkForCompletion;
1283 n_popResponseQueue;
1284 }
1285
1286 transition(NO_DR_B_W, Shared_Data) {
1287 r_recordCacheData;
1288 m_decrementNumberOfMessages;
1289 so_setOwnerBit;
1290 o_checkForCompletion;
1291 n_popResponseQueue;
1292 }
1293
1294 transition({NO_DR_B, NO_DR_B_D}, Shared_Data) {
1295 r_recordCacheData;
1296 m_decrementNumberOfMessages;
1297 so_setOwnerBit;
1298 o_checkForCompletion;
1299 n_popResponseQueue;
1300 }
1301
1302 transition(NO_DR_B_W, {Exclusive_Data, Data}) {
1303 r_recordCacheData;
1304 m_decrementNumberOfMessages;
1305 n_popResponseQueue;
1306 }
1307
1308 transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, {Exclusive_Data, Data}) {
1309 r_recordCacheData;
1310 m_decrementNumberOfMessages;
1311 o_checkForCompletion;
1312 n_popResponseQueue;
1313 }
1314
1315 transition(NO_DR_B, All_acks_and_owner_data, O) {
1316 //
1317 // Note that the DMA consistency model allows us to send the DMA device
1318 // a response as soon as we receive valid data and prior to receiving
1319 // all acks. However, to simplify the protocol we wait for all acks.
1320 //
1321 dt_sendDmaDataFromTbe;
1322 wdt_writeDataFromTBE;
1323 w_deallocateTBE;
1324 k_wakeUpDependents;
1325 g_popTriggerQueue;
1326 }
1327
1328 transition(NO_DR_B, All_acks_and_shared_data, S) {
1329 //
1330 // Note that the DMA consistency model allows us to send the DMA device
1331 // a response as soon as we receive valid data and prior to receiving
1332 // all acks. However, to simplify the protocol we wait for all acks.
1333 //
1334 dt_sendDmaDataFromTbe;
1335 wdt_writeDataFromTBE;
1336 w_deallocateTBE;
1337 k_wakeUpDependents;
1338 g_popTriggerQueue;
1339 }
1340
1341 transition(NO_DR_B_D, All_acks_and_owner_data, O) {
1342 //
1343 // Note that the DMA consistency model allows us to send the DMA device
1344 // a response as soon as we receive valid data and prior to receiving
1345 // all acks. However, to simplify the protocol we wait for all acks.
1346 //
1347 dt_sendDmaDataFromTbe;
1348 wdt_writeDataFromTBE;
1349 w_deallocateTBE;
1350 k_wakeUpDependents;
1351 g_popTriggerQueue;
1352 }
1353
1354 transition(NO_DR_B_D, All_acks_and_shared_data, S) {
1355 //
1356 // Note that the DMA consistency model allows us to send the DMA device
1357 // a response as soon as we receive valid data and prior to receiving
1358 // all acks. However, to simplify the protocol we wait for all acks.
1359 //
1360 dt_sendDmaDataFromTbe;
1361 wdt_writeDataFromTBE;
1362 w_deallocateTBE;
1363 k_wakeUpDependents;
1364 g_popTriggerQueue;
1365 }
1366
1367 transition(O_DR_B, All_acks_and_owner_data, O) {
1368 wdt_writeDataFromTBE;
1369 w_deallocateTBE;
1370 k_wakeUpDependents;
1371 g_popTriggerQueue;
1372 }
1373
1374 transition(O_DR_B, All_acks_and_data_no_sharers, E) {
1375 wdt_writeDataFromTBE;
1376 w_deallocateTBE;
1377 pfd_probeFilterDeallocate;
1378 k_wakeUpDependents;
1379 g_popTriggerQueue;
1380 }
1381
1382 transition(NO_DR_B, All_acks_and_data_no_sharers, E) {
1383 //
1384 // Note that the DMA consistency model allows us to send the DMA device
1385 // a response as soon as we receive valid data and prior to receiving
1386 // all acks. However, to simplify the protocol we wait for all acks.
1387 //
1388 dt_sendDmaDataFromTbe;
1389 wdt_writeDataFromTBE;
1390 w_deallocateTBE;
1391 ppfd_possibleProbeFilterDeallocate;
1392 k_wakeUpDependents;
1393 g_popTriggerQueue;
1394 }
1395
1396 transition(NO_DR_B_D, All_acks_and_data_no_sharers, E) {
1397 a_assertCacheData;
1398 //
1399 // Note that the DMA consistency model allows us to send the DMA device
1400 // a response as soon as we receive valid data and prior to receiving
1401 // all acks. However, to simplify the protocol we wait for all acks.
1402 //
1403 dt_sendDmaDataFromTbe;
1404 wdt_writeDataFromTBE;
1405 w_deallocateTBE;
1406 ppfd_possibleProbeFilterDeallocate;
1407 k_wakeUpDependents;
1408 g_popTriggerQueue;
1409 }
1410
1411 transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) {
1412 dwt_writeDmaDataFromTBE;
1413 ld_queueMemoryDmaWrite;
1414 g_popTriggerQueue;
1415 }
1416
1417 transition(NO_DW_W, Memory_Ack, E) {
1418 da_sendDmaAck;
1419 w_deallocateTBE;
1420 ppfd_possibleProbeFilterDeallocate;
1421 k_wakeUpDependents;
1422 l_popMemQueue;
1423 }
1424
1425 transition(O_B_W, Memory_Data, O_B) {
1426 d_sendData;
1427 w_deallocateTBE;
1428 l_popMemQueue;
1429 }
1430
1431 transition(NO_B_W, UnblockM, NO_W) {
1432 uo_updateOwnerIfPf;
1433 j_popIncomingUnblockQueue;
1434 }
1435
1436 transition(NO_B_W, UnblockS, NO_W) {
1437 j_popIncomingUnblockQueue;
1438 }
1439
1440 transition(O_B_W, UnblockS, O_W) {
1441 j_popIncomingUnblockQueue;
1442 }
1443
1444 transition(NO_W, Memory_Data, NO) {
1445 w_deallocateTBE;
1446 k_wakeUpDependents;
1447 l_popMemQueue;
1448 }
1449
1450 transition(O_W, Memory_Data, O) {
1451 w_deallocateTBE;
1452 k_wakeUpDependents;
1453 l_popMemQueue;
1454 }
1455
1456 // WB State Transistions
1457 transition(WB, Writeback_Dirty, WB_O_W) {
1458 l_writeDataToMemory;
1459 l_queueMemoryWBRequest;
1460 j_popIncomingUnblockQueue;
1461 }
1462
1463 transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
1464 l_writeDataToMemory;
1465 l_queueMemoryWBRequest;
1466 j_popIncomingUnblockQueue;
1467 }
1468
1469 transition(WB_E_W, Memory_Ack, E) {
1470 pfd_probeFilterDeallocate;
1471 k_wakeUpDependents;
1472 l_popMemQueue;
1473 }
1474
1475 transition(WB_O_W, Memory_Ack, O) {
1476 k_wakeUpDependents;
1477 l_popMemQueue;
1478 }
1479
1480 transition(WB, Writeback_Clean, O) {
1481 ll_checkIncomingWriteback;
1482 k_wakeUpDependents;
1483 j_popIncomingUnblockQueue;
1484 }
1485
1486 transition(WB, Writeback_Exclusive_Clean, E) {
1487 ll_checkIncomingWriteback;
1488 pfd_probeFilterDeallocate;
1489 k_wakeUpDependents;
1490 j_popIncomingUnblockQueue;
1491 }
1492
1493 transition(WB, Unblock, NO) {
1494 auno_assertUnblockerNotOwner;
1495 k_wakeUpDependents;
1496 j_popIncomingUnblockQueue;
1497 }
1498 }