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 36machine(MachineType:Directory, "AMD Hammer-like protocol") 37 : DirectoryMemory * directory; 38 CacheMemory * probeFilter; 39 Cycles from_memory_controller_latency := 2; 40 Cycles to_memory_controller_latency := 1; 41 bool probe_filter_enabled := "False"; 42 bool full_bit_dir_enabled := "False"; 43 44 MessageBuffer * forwardFromDir, network="To", virtual_network="3", 45 vnet_type="forward"; 46 47 MessageBuffer * responseFromDir, network="To", virtual_network="4", 48 vnet_type="response"; 49 50 // For a finite buffered network, note that the DMA response network only 51 // works at this relatively lower numbered (lower priority) virtual network 52 // because the trigger queue decouples cache responses from DMA responses. 53 MessageBuffer * dmaResponseFromDir, network="To", virtual_network="1", 54 vnet_type="response"; 55 56 MessageBuffer * unblockToDir, network="From", virtual_network="5", 57 vnet_type="unblock"; 58 59 MessageBuffer * responseToDir, network="From", virtual_network="4", 60 vnet_type="response"; 61 62 MessageBuffer * requestToDir, network="From", virtual_network="2", 63 vnet_type="request"; 64 65 MessageBuffer * dmaRequestToDir, network="From", virtual_network="0", 66 vnet_type="request"; 67 68 MessageBuffer * triggerQueue; 69 MessageBuffer * responseFromMemory; 70{ 71 // STATES 72 state_declaration(State, desc="Directory states", default="Directory_State_E") { 73 // Base states 74 NX, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in O at Owner"; 75 NO, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in E/M at Owner"; 76 S, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists pointing to the current owner"; 77 O, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists"; 78 E, AccessPermission:Read_Write, desc="Exclusive Owner, no probe filter entry"; 79 80 O_R, AccessPermission:Read_Only, desc="Was data Owner, replacing probe filter entry"; 81 S_R, AccessPermission:Read_Only, desc="Was Not Owner or Sharer, replacing probe filter entry"; 82 NO_R, AccessPermission:Busy, desc="Was Not Owner or Sharer, replacing probe filter entry"; 83 84 NO_B, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked"; 85 NO_B_X, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETX"; 86 NO_B_S, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETS"; 87 NO_B_S_W, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses"; 88 O_B, AccessPermission:Busy, "O^B", desc="Owner, Blocked"; 89 NO_B_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram"; 90 O_B_W, AccessPermission:Busy, desc="Owner, Blocked, waiting for Dram"; 91 NO_W, AccessPermission:Busy, desc="Not Owner, waiting for Dram"; 92 O_W, AccessPermission:Busy, desc="Owner, waiting for Dram"; 93 NO_DW_B_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram and cache responses"; 94 NO_DR_B_W, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for Dram and cache responses"; 95 NO_DR_B_D, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses including dirty data"; 96 NO_DR_B, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses"; 97 NO_DW_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram"; 98 O_DR_B_W, AccessPermission:Busy, desc="Owner, Dma Read waiting for Dram and cache responses"; 99 O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses"; 100 WB, AccessPermission:Busy, desc="Blocked on a writeback"; 101 WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O"; 102 WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E"; 103 104 NO_F, AccessPermission:Busy, desc="Blocked on a flush"; 105 NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram"; 106 } 107 108 // Events 109 enumeration(Event, desc="Directory events") { 110 GETX, desc="A GETX arrives"; 111 GETS, desc="A GETS arrives"; 112 PUT, desc="A PUT arrives"; 113 Unblock, desc="An unblock message arrives"; 114 UnblockS, desc="An unblock message arrives"; 115 UnblockM, desc="An unblock message arrives"; 116 Writeback_Clean, desc="The final part of a PutX (no data)"; 117 Writeback_Dirty, desc="The final part of a PutX (data)"; 118 Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)"; 119 Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)"; 120 121 // Probe filter 122 Pf_Replacement, desc="probe filter replacement"; 123 124 // DMA requests 125 DMA_READ, desc="A DMA Read memory request"; 126 DMA_WRITE, desc="A DMA Write memory request"; 127 128 // Memory Controller 129 Memory_Data, desc="Fetched data from memory arrives"; 130 Memory_Ack, desc="Writeback Ack from memory arrives"; 131 132 // Cache responses required to handle DMA 133 Ack, desc="Received an ack message"; 134 Shared_Ack, desc="Received an ack message, responder has a shared copy"; 135 Shared_Data, desc="Received a data message, responder has a shared copy"; 136 Data, desc="Received a data message, responder had a owner or exclusive copy, they gave it to us"; 137 Exclusive_Data, desc="Received a data message, responder had an exclusive copy, they gave it to us"; 138 139 // Triggers 140 All_acks_and_shared_data, desc="Received shared data and message acks"; 141 All_acks_and_owner_data, desc="Received shared data and message acks"; 142 All_acks_and_data_no_sharers, desc="Received all acks and no other processor has a shared copy"; 143 All_Unblocks, desc="Received all unblocks for a merged gets request"; 144 GETF, desc="A GETF arrives"; 145 PUTF, desc="A PUTF arrives"; 146 } 147 148 // TYPES 149 150 // DirectoryEntry 151 structure(Entry, desc="...", interface="AbstractEntry") { 152 State DirectoryState, desc="Directory state"; 153 } 154 155 // ProbeFilterEntry 156 structure(PfEntry, desc="...", interface="AbstractCacheEntry") { 157 State PfState, desc="Directory state"; 158 MachineID Owner, desc="Owner node"; 159 Set Sharers, desc="sharing vector for full bit directory"; 160 } 161 162 // TBE entries for DMA requests 163 structure(TBE, desc="TBE entries for outstanding DMA requests") { 164 Addr PhysicalAddress, desc="physical address"; 165 State TBEState, desc="Transient State"; 166 CoherenceResponseType ResponseType, desc="The type for the subsequent response message"; 167 int Acks, default="0", desc="The number of acks that the waiting response represents"; 168 int SilentAcks, default="0", desc="The number of silent acks associated with this transaction"; 169 DataBlock DmaDataBlk, desc="DMA Data to be written. Partial blocks need to merged with system memory"; 170 DataBlock DataBlk, desc="The current view of system memory"; 171 int Len, desc="..."; 172 MachineID DmaRequestor, desc="DMA requestor"; 173 NetDest GetSRequestors, desc="GETS merged requestors"; 174 int NumPendingMsgs, desc="Number of pending acks/messages"; 175 bool CacheDirty, default="false", desc="Indicates whether a cache has responded with dirty data"; 176 bool Sharers, default="false", desc="Indicates whether a cache has indicated it is currently a sharer"; 177 bool Owned, default="false", desc="Indicates whether a cache has indicated it is currently a sharer"; 178 } 179 180 structure(TBETable, external="yes") { 181 TBE lookup(Addr); 182 void allocate(Addr); 183 void deallocate(Addr); 184 bool isPresent(Addr); 185 } 186 187 Tick clockEdge(); 188 void set_cache_entry(AbstractCacheEntry b); 189 void unset_cache_entry(); 190 void set_tbe(TBE a); 191 void unset_tbe(); 192 void wakeUpBuffers(Addr a); 193 Cycles curCycle(); 194 195 // ** OBJECTS ** 196 197 Set fwd_set; 198 199 TBETable TBEs, template="<Directory_TBE>", constructor="m_number_of_TBEs"; 200 201 Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" { 202 Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); 203 204 if (is_valid(dir_entry)) { 205 return dir_entry; 206 } 207 208 dir_entry := static_cast(Entry, "pointer", 209 directory.allocate(addr, new Entry)); 210 return dir_entry; 211 } 212 213 PfEntry getProbeFilterEntry(Addr addr), return_by_pointer="yes" { 214 if (probe_filter_enabled || full_bit_dir_enabled) { 215 PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr)); 216 return pfEntry; 217 } 218 return OOD; 219 } 220 221 State getState(TBE tbe, PfEntry pf_entry, Addr addr) { 222 if (is_valid(tbe)) { 223 return tbe.TBEState; 224 } else { 225 if (probe_filter_enabled || full_bit_dir_enabled) { 226 if (is_valid(pf_entry)) { 227 assert(pf_entry.PfState == getDirectoryEntry(addr).DirectoryState); 228 } 229 } 230 return getDirectoryEntry(addr).DirectoryState; 231 } 232 } 233 234 void setState(TBE tbe, PfEntry pf_entry, Addr addr, State state) { 235 if (is_valid(tbe)) { 236 tbe.TBEState := state; 237 } 238 if (probe_filter_enabled || full_bit_dir_enabled) { 239 if (is_valid(pf_entry)) { 240 pf_entry.PfState := state; 241 } 242 if (state == State:NX || state == State:NO || state == State:S || state == State:O) { 243 assert(is_valid(pf_entry)); 244 } 245 if (state == State:E) { 246 assert(is_valid(pf_entry) == false); 247 } 248 } 249 if (state == State:E || state == State:NX || state == State:NO || state == State:S || 250 state == State:O) { 251 assert(is_valid(tbe) == false); 252 } 253 getDirectoryEntry(addr).DirectoryState := state; 254 } 255 256 AccessPermission getAccessPermission(Addr addr) { 257 TBE tbe := TBEs[addr]; 258 if(is_valid(tbe)) { 259 return Directory_State_to_permission(tbe.TBEState); 260 } 261 262 if(directory.isPresent(addr)) { 263 return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState); 264 } 265 266 return AccessPermission:NotPresent; 267 } 268 269 void setAccessPermission(PfEntry pf_entry, Addr addr, State state) { 270 getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state)); 271 } 272 273 void functionalRead(Addr addr, Packet *pkt) { 274 TBE tbe := TBEs[addr]; 275 if(is_valid(tbe)) { 276 testAndRead(addr, tbe.DataBlk, pkt); 277 } else { 278 functionalMemoryRead(pkt); 279 } 280 } 281 282 int functionalWrite(Addr addr, Packet *pkt) { 283 int num_functional_writes := 0; 284 285 TBE tbe := TBEs[addr]; 286 if(is_valid(tbe)) { 287 num_functional_writes := num_functional_writes + 288 testAndWrite(addr, tbe.DataBlk, pkt); 289 } 290 291 num_functional_writes := num_functional_writes + functionalMemoryWrite(pkt); 292 return num_functional_writes; 293 } 294 295 Event cache_request_to_event(CoherenceRequestType type) { 296 if (type == CoherenceRequestType:GETS) { 297 return Event:GETS; 298 } else if (type == CoherenceRequestType:GETX) { 299 return Event:GETX; 300 } else if (type == CoherenceRequestType:GETF) { 301 return Event:GETF; 302 } else { 303 error("Invalid CoherenceRequestType"); 304 } 305 } 306 307 // ** OUT_PORTS ** 308 out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests 309 out_port(forwardNetwork_out, RequestMsg, forwardFromDir); 310 out_port(responseNetwork_out, ResponseMsg, responseFromDir); 311 out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaResponseFromDir); 312 out_port(triggerQueue_out, TriggerMsg, triggerQueue); 313 314 // ** IN_PORTS ** 315 316 // Trigger Queue 317 in_port(triggerQueue_in, TriggerMsg, triggerQueue, rank=5) { 318 if (triggerQueue_in.isReady(clockEdge())) { 319 peek(triggerQueue_in, TriggerMsg) { 320 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr); 321 TBE tbe := TBEs[in_msg.addr]; 322 if (in_msg.Type == TriggerType:ALL_ACKS) { 323 trigger(Event:All_acks_and_owner_data, in_msg.addr, 324 pf_entry, tbe); 325 } else if (in_msg.Type == TriggerType:ALL_ACKS_OWNER_EXISTS) { 326 trigger(Event:All_acks_and_shared_data, in_msg.addr, 327 pf_entry, tbe); 328 } else if (in_msg.Type == TriggerType:ALL_ACKS_NO_SHARERS) { 329 trigger(Event:All_acks_and_data_no_sharers, in_msg.addr, 330 pf_entry, tbe); 331 } else if (in_msg.Type == TriggerType:ALL_UNBLOCKS) { 332 trigger(Event:All_Unblocks, in_msg.addr, 333 pf_entry, tbe); 334 } else { 335 error("Unexpected message"); 336 } 337 } 338 } 339 } 340 341 in_port(unblockNetwork_in, ResponseMsg, unblockToDir, rank=4) { 342 if (unblockNetwork_in.isReady(clockEdge())) { 343 peek(unblockNetwork_in, ResponseMsg) { 344 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr); 345 TBE tbe := TBEs[in_msg.addr]; 346 if (in_msg.Type == CoherenceResponseType:UNBLOCK) { 347 trigger(Event:Unblock, in_msg.addr, pf_entry, tbe); 348 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKS) { 349 trigger(Event:UnblockS, in_msg.addr, pf_entry, tbe); 350 } else if (in_msg.Type == CoherenceResponseType:UNBLOCKM) { 351 trigger(Event:UnblockM, in_msg.addr, pf_entry, tbe); 352 } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) { 353 trigger(Event:Writeback_Clean, in_msg.addr, pf_entry, tbe); 354 } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) { 355 trigger(Event:Writeback_Dirty, in_msg.addr, pf_entry, tbe); 356 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) { 357 trigger(Event:Writeback_Exclusive_Clean, in_msg.addr, 358 pf_entry, tbe); 359 } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) { 360 trigger(Event:Writeback_Exclusive_Dirty, in_msg.addr, 361 pf_entry, tbe); 362 } else { 363 error("Invalid message"); 364 } 365 } 366 } 367 } 368 369 // Response Network 370 in_port(responseToDir_in, ResponseMsg, responseToDir, rank=3) { 371 if (responseToDir_in.isReady(clockEdge())) { 372 peek(responseToDir_in, ResponseMsg) { 373 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr); 374 TBE tbe := TBEs[in_msg.addr]; 375 if (in_msg.Type == CoherenceResponseType:ACK) { 376 trigger(Event:Ack, in_msg.addr, pf_entry, tbe); 377 } else if (in_msg.Type == CoherenceResponseType:ACK_SHARED) { 378 trigger(Event:Shared_Ack, in_msg.addr, pf_entry, tbe); 379 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { 380 trigger(Event:Shared_Data, in_msg.addr, pf_entry, tbe); 381 } else if (in_msg.Type == CoherenceResponseType:DATA) { 382 trigger(Event:Data, in_msg.addr, pf_entry, tbe); 383 } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) { 384 trigger(Event:Exclusive_Data, in_msg.addr, pf_entry, tbe); 385 } else { 386 error("Unexpected message"); 387 } 388 } 389 } 390 } 391 392 // off-chip memory request/response is done 393 in_port(memQueue_in, MemoryMsg, responseFromMemory, rank=2) { 394 if (memQueue_in.isReady(clockEdge())) { 395 peek(memQueue_in, MemoryMsg) { 396 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr); 397 TBE tbe := TBEs[in_msg.addr]; 398 if (in_msg.Type == MemoryRequestType:MEMORY_READ) { 399 trigger(Event:Memory_Data, in_msg.addr, pf_entry, tbe); 400 } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) { 401 trigger(Event:Memory_Ack, in_msg.addr, pf_entry, tbe); 402 } else { 403 DPRINTF(RubySlicc, "%d\n", in_msg.Type); 404 error("Invalid message"); 405 } 406 } 407 } 408 } 409 410 in_port(requestQueue_in, RequestMsg, requestToDir, rank=1) { 411 if (requestQueue_in.isReady(clockEdge())) { 412 peek(requestQueue_in, RequestMsg) { 413 PfEntry pf_entry := getProbeFilterEntry(in_msg.addr); 414 TBE tbe := TBEs[in_msg.addr]; 415 if (in_msg.Type == CoherenceRequestType:PUT) { 416 trigger(Event:PUT, in_msg.addr, pf_entry, tbe); 417 } else if (in_msg.Type == CoherenceRequestType:PUTF) { 418 trigger(Event:PUTF, in_msg.addr, pf_entry, tbe); 419 } else { 420 if (probe_filter_enabled || full_bit_dir_enabled) { 421 if (is_valid(pf_entry)) { 422 trigger(cache_request_to_event(in_msg.Type), in_msg.addr, 423 pf_entry, tbe); 424 } else { 425 if (probeFilter.cacheAvail(in_msg.addr)) { 426 trigger(cache_request_to_event(in_msg.Type), in_msg.addr, 427 pf_entry, tbe); 428 } else { 429 trigger(Event:Pf_Replacement, 430 Addr victim := probeFilter.cacheProbe(in_msg.addr); 431 trigger(Event:Pf_Replacement, 432 victim, getProbeFilterEntry(victim), TBEs[victim]); 433 } 434 } 435 } else { 436 trigger(cache_request_to_event(in_msg.Type), in_msg.addr, 437 pf_entry, tbe); 438 } 439 } 440 } 441 } 442 } 443 444 in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir, rank=0) { 445 if (dmaRequestQueue_in.isReady(clockEdge())) { 446 peek(dmaRequestQueue_in, DMARequestMsg) { 447 PfEntry pf_entry := getProbeFilterEntry(in_msg.LineAddress); 448 TBE tbe := TBEs[in_msg.LineAddress]; 449 if (in_msg.Type == DMARequestType:READ) { 450 trigger(Event:DMA_READ, in_msg.LineAddress, pf_entry, tbe); 451 } else if (in_msg.Type == DMARequestType:WRITE) { 452 trigger(Event:DMA_WRITE, in_msg.LineAddress, pf_entry, tbe); 453 } else { 454 error("Invalid message"); 455 } 456 } 457 } 458 } 459 460 // Actions 461 462 action(r_setMRU, "\rr", desc="manually set the MRU bit for pf entry" ) { 463 if (probe_filter_enabled || full_bit_dir_enabled) { 464 assert(is_valid(cache_entry)); 465 probeFilter.setMRU(address); 466 } 467 } 468 469 action(auno_assertUnblockerNotOwner, "auno", desc="assert unblocker not owner") { 470 if (probe_filter_enabled || full_bit_dir_enabled) { 471 assert(is_valid(cache_entry)); 472 peek(unblockNetwork_in, ResponseMsg) { 473 assert(cache_entry.Owner != in_msg.Sender); 474 if (full_bit_dir_enabled) { 475 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender)) == false); 476 } 477 } 478 } 479 } 480 481 action(uo_updateOwnerIfPf, "uo", desc="update owner") { 482 if (probe_filter_enabled || full_bit_dir_enabled) { 483 assert(is_valid(cache_entry)); 484 peek(unblockNetwork_in, ResponseMsg) { 485 cache_entry.Owner := in_msg.Sender; 486 if (full_bit_dir_enabled) { 487 cache_entry.Sharers.clear(); 488 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender)); 489 APPEND_TRANSITION_COMMENT(cache_entry.Sharers); 490 DPRINTF(RubySlicc, "Sharers = %d\n", cache_entry.Sharers); 491 } 492 } 493 } 494 } 495 496 action(us_updateSharerIfFBD, "us", desc="update sharer if full-bit directory") { 497 if (full_bit_dir_enabled) { 498 assert(probeFilter.isTagPresent(address)); 499 peek(unblockNetwork_in, ResponseMsg) { 500 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Sender)); 501 } 502 } 503 } 504 505 action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") { 506 peek(requestQueue_in, RequestMsg) { 507 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 508 out_msg.addr := address; 509 out_msg.Type := CoherenceRequestType:WB_ACK; 510 out_msg.Requestor := in_msg.Requestor; 511 out_msg.Destination.add(in_msg.Requestor); 512 out_msg.MessageSize := MessageSizeType:Writeback_Control; 513 } 514 } 515 } 516 517 action(oc_sendBlockAck, "oc", desc="Send block ack to the owner") { 518 peek(requestQueue_in, RequestMsg) { 519 if (((probe_filter_enabled || full_bit_dir_enabled) && (in_msg.Requestor == cache_entry.Owner)) || machineCount(MachineType:L1Cache) == 1) { 520 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 521 out_msg.addr := address; 522 out_msg.Type := CoherenceRequestType:BLOCK_ACK; 523 out_msg.Requestor := in_msg.Requestor; 524 out_msg.Destination.add(in_msg.Requestor); 525 out_msg.MessageSize := MessageSizeType:Writeback_Control; 526 } 527 } 528 } 529 } 530 531 action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") { 532 peek(requestQueue_in, RequestMsg) { 533 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 534 out_msg.addr := address; 535 out_msg.Type := CoherenceRequestType:WB_NACK; 536 out_msg.Requestor := in_msg.Requestor; 537 out_msg.Destination.add(in_msg.Requestor); 538 out_msg.MessageSize := MessageSizeType:Writeback_Control; 539 } 540 } 541 } 542 543 action(pfa_probeFilterAllocate, "pfa", desc="Allocate ProbeFilterEntry") { 544 if (probe_filter_enabled || full_bit_dir_enabled) { 545 peek(requestQueue_in, RequestMsg) { 546 set_cache_entry(probeFilter.allocate(address, new PfEntry)); 547 cache_entry.Owner := in_msg.Requestor; 548 cache_entry.Sharers.setSize(machineCount(MachineType:L1Cache)); 549 } 550 } 551 } 552 553 action(pfd_probeFilterDeallocate, "pfd", desc="Deallocate ProbeFilterEntry") { 554 if (probe_filter_enabled || full_bit_dir_enabled) { 555 probeFilter.deallocate(address); 556 unset_cache_entry(); 557 } 558 } 559 560 action(ppfd_possibleProbeFilterDeallocate, "ppfd", desc="Deallocate ProbeFilterEntry") { 561 if ((probe_filter_enabled || full_bit_dir_enabled) && is_valid(cache_entry)) { 562 probeFilter.deallocate(address); 563 unset_cache_entry(); 564 } 565 } 566 567 action(v_allocateTBE, "v", desc="Allocate TBE") { 568 check_allocate(TBEs); 569 peek(requestQueue_in, RequestMsg) { 570 TBEs.allocate(address); 571 set_tbe(TBEs[address]); 572 tbe.PhysicalAddress := address; 573 tbe.ResponseType := CoherenceResponseType:NULL; 574 } 575 } 576 577 action(vd_allocateDmaRequestInTBE, "vd", desc="Record Data in TBE") { 578 check_allocate(TBEs); 579 peek(dmaRequestQueue_in, DMARequestMsg) { 580 TBEs.allocate(address); 581 set_tbe(TBEs[address]); 582 tbe.DmaDataBlk := in_msg.DataBlk; 583 tbe.PhysicalAddress := in_msg.PhysicalAddress; 584 tbe.Len := in_msg.Len; 585 tbe.DmaRequestor := in_msg.Requestor; 586 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; 587 // 588 // One ack for each last-level cache 589 // 590 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); 591 // 592 // Assume initially that the caches store a clean copy and that memory 593 // will provide the data 594 // 595 tbe.CacheDirty := false; 596 } 597 } 598 599 action(pa_setPendingMsgsToAll, "pa", desc="set pending msgs to all") { 600 assert(is_valid(tbe)); 601 if (full_bit_dir_enabled) { 602 assert(is_valid(cache_entry)); 603 tbe.NumPendingMsgs := cache_entry.Sharers.count(); 604 } else { 605 tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); 606 } 607 } 608 609 action(po_setPendingMsgsToOne, "po", desc="set pending msgs to one") { 610 assert(is_valid(tbe)); 611 tbe.NumPendingMsgs := 1; 612 } 613 614 action(w_deallocateTBE, "w", desc="Deallocate TBE") { 615 TBEs.deallocate(address); 616 unset_tbe(); 617 } 618 619 action(sa_setAcksToOne, "sa", desc="Forwarded request, set the ack amount to one") { 620 assert(is_valid(tbe)); 621 peek(requestQueue_in, RequestMsg) { 622 if (full_bit_dir_enabled) { 623 assert(is_valid(cache_entry)); 624 // 625 // If we are using the full-bit directory and no sharers exists beyond 626 // the requestor, then we must set the ack number to all, not one 627 // 628 fwd_set := cache_entry.Sharers; 629 fwd_set.remove(machineIDToNodeID(in_msg.Requestor)); 630 if (fwd_set.count() > 0) { 631 tbe.Acks := 1; 632 tbe.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count(); 633 tbe.SilentAcks := tbe.SilentAcks - 1; 634 } else { 635 tbe.Acks := machineCount(MachineType:L1Cache); 636 tbe.SilentAcks := 0; 637 } 638 } else { 639 tbe.Acks := 1; 640 } 641 } 642 } 643 644 action(saa_setAcksToAllIfPF, "saa", desc="Non-forwarded request, set the ack amount to all") { 645 assert(is_valid(tbe)); 646 if (probe_filter_enabled || full_bit_dir_enabled) { 647 tbe.Acks := machineCount(MachineType:L1Cache); 648 tbe.SilentAcks := 0; 649 } else { 650 tbe.Acks := 1; 651 } 652 } 653 654 action(m_decrementNumberOfMessages, "m", desc="Decrement the number of messages for which we're waiting") { 655 peek(responseToDir_in, ResponseMsg) { 656 assert(is_valid(tbe)); 657 assert(in_msg.Acks > 0); 658 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); 659 // 660 // Note that cache data responses will have an ack count of 2. However, 661 // directory DMA requests must wait for acks from all LLC caches, so 662 // only decrement by 1. 663 // 664 if ((in_msg.Type == CoherenceResponseType:DATA_SHARED) || 665 (in_msg.Type == CoherenceResponseType:DATA) || 666 (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE)) { 667 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1; 668 } else { 669 tbe.NumPendingMsgs := tbe.NumPendingMsgs - in_msg.Acks; 670 } 671 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); 672 } 673 } 674 675 action(mu_decrementNumberOfUnblocks, "mu", desc="Decrement the number of messages for which we're waiting") { 676 peek(unblockNetwork_in, ResponseMsg) { 677 assert(is_valid(tbe)); 678 assert(in_msg.Type == CoherenceResponseType:UNBLOCKS); 679 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); 680 tbe.NumPendingMsgs := tbe.NumPendingMsgs - 1; 681 DPRINTF(RubySlicc, "%d\n", tbe.NumPendingMsgs); 682 } 683 } 684 685 action(n_popResponseQueue, "n", desc="Pop response queue") { 686 responseToDir_in.dequeue(clockEdge()); 687 } 688 689 action(o_checkForCompletion, "o", desc="Check if we have received all the messages required for completion") { 690 assert(is_valid(tbe)); 691 if (tbe.NumPendingMsgs == 0) { 692 enqueue(triggerQueue_out, TriggerMsg) { 693 out_msg.addr := address; 694 if (tbe.Sharers) { 695 if (tbe.Owned) { 696 out_msg.Type := TriggerType:ALL_ACKS_OWNER_EXISTS; 697 } else { 698 out_msg.Type := TriggerType:ALL_ACKS; 699 } 700 } else { 701 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS; 702 } 703 } 704 } 705 } 706 707 action(os_checkForMergedGetSCompletion, "os", desc="Check for merged GETS completion") { 708 assert(is_valid(tbe)); 709 if (tbe.NumPendingMsgs == 0) { 710 enqueue(triggerQueue_out, TriggerMsg) { 711 out_msg.addr := address; 712 out_msg.Type := TriggerType:ALL_UNBLOCKS; 713 } 714 } 715 } 716 717 action(sp_setPendingMsgsToMergedSharers, "sp", desc="Set pending messages to waiting sharers") { 718 assert(is_valid(tbe)); 719 tbe.NumPendingMsgs := tbe.GetSRequestors.count(); 720 } 721 722 action(spa_setPendingAcksToZeroIfPF, "spa", desc="if probe filter, no need to wait for acks") { 723 if (probe_filter_enabled || full_bit_dir_enabled) { 724 assert(is_valid(tbe)); 725 tbe.NumPendingMsgs := 0; 726 } 727 } 728 729 action(sc_signalCompletionIfPF, "sc", desc="indicate that we should skip waiting for cpu acks") { 730 assert(is_valid(tbe)); 731 if (tbe.NumPendingMsgs == 0) { 732 assert(probe_filter_enabled || full_bit_dir_enabled); 733 enqueue(triggerQueue_out, TriggerMsg) { 734 out_msg.addr := address; 735 out_msg.Type := TriggerType:ALL_ACKS_NO_SHARERS; 736 } 737 } 738 } 739 740 action(d_sendData, "d", desc="Send data to requestor") { 741 peek(memQueue_in, MemoryMsg) { 742 enqueue(responseNetwork_out, ResponseMsg, 1) { 743 assert(is_valid(tbe)); 744 out_msg.addr := address; 745 out_msg.Type := tbe.ResponseType; 746 out_msg.Sender := machineID; 747 out_msg.Destination.add(in_msg.OriginalRequestorMachId); 748 out_msg.DataBlk := in_msg.DataBlk; 749 DPRINTF(RubySlicc, "%s\n", out_msg.DataBlk); 750 out_msg.Dirty := false; // By definition, the block is now clean 751 out_msg.Acks := tbe.Acks; 752 out_msg.SilentAcks := tbe.SilentAcks; 753 DPRINTF(RubySlicc, "%d\n", out_msg.Acks); 754 assert(out_msg.Acks > 0); 755 out_msg.MessageSize := MessageSizeType:Response_Data; 756 } 757 } 758 } 759 760 action(dr_sendDmaData, "dr", desc="Send Data to DMA controller from memory") { 761 peek(memQueue_in, MemoryMsg) { 762 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) { 763 assert(is_valid(tbe)); 764 out_msg.PhysicalAddress := address; 765 out_msg.LineAddress := address; 766 out_msg.Type := DMAResponseType:DATA; 767 // 768 // we send the entire data block and rely on the dma controller to 769 // split it up if need be 770 // 771 out_msg.DataBlk := in_msg.DataBlk; 772 out_msg.Destination.add(tbe.DmaRequestor); 773 out_msg.MessageSize := MessageSizeType:Response_Data; 774 } 775 } 776 } 777 778 action(dt_sendDmaDataFromTbe, "dt", desc="Send Data to DMA controller from tbe") { 779 peek(triggerQueue_in, TriggerMsg) { 780 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) { 781 assert(is_valid(tbe)); 782 out_msg.PhysicalAddress := address; 783 out_msg.LineAddress := address; 784 out_msg.Type := DMAResponseType:DATA; 785 // 786 // we send the entire data block and rely on the dma controller to 787 // split it up if need be 788 // 789 out_msg.DataBlk := tbe.DataBlk; 790 out_msg.Destination.add(tbe.DmaRequestor); 791 out_msg.MessageSize := MessageSizeType:Response_Data; 792 } 793 } 794 } 795 796 action(da_sendDmaAck, "da", desc="Send Ack to DMA controller") { 797 enqueue(dmaResponseNetwork_out, DMAResponseMsg, 1) { 798 assert(is_valid(tbe)); 799 out_msg.PhysicalAddress := address; 800 out_msg.LineAddress := address; 801 out_msg.Type := DMAResponseType:ACK; 802 out_msg.Destination.add(tbe.DmaRequestor); 803 out_msg.MessageSize := MessageSizeType:Writeback_Control; 804 } 805 } 806 807 action(rx_recordExclusiveInTBE, "rx", desc="Record Exclusive in TBE") { 808 peek(requestQueue_in, RequestMsg) { 809 assert(is_valid(tbe)); 810 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; 811 } 812 } 813 814 action(r_recordDataInTBE, "rt", desc="Record Data in TBE") { 815 peek(requestQueue_in, RequestMsg) { 816 assert(is_valid(tbe)); 817 if (full_bit_dir_enabled) { 818 fwd_set := cache_entry.Sharers; 819 fwd_set.remove(machineIDToNodeID(in_msg.Requestor)); 820 if (fwd_set.count() > 0) { 821 tbe.ResponseType := CoherenceResponseType:DATA; 822 } else { 823 tbe.ResponseType := CoherenceResponseType:DATA_EXCLUSIVE; 824 } 825 } else { 826 tbe.ResponseType := CoherenceResponseType:DATA; 827 } 828 } 829 } 830 831 action(rs_recordGetSRequestor, "rs", desc="Record GETS requestor in TBE") { 832 peek(requestQueue_in, RequestMsg) { 833 assert(is_valid(tbe)); 834 tbe.GetSRequestors.add(in_msg.Requestor); 835 } 836 } 837 838 action(r_setSharerBit, "r", desc="We saw other sharers") { 839 assert(is_valid(tbe)); 840 tbe.Sharers := true; 841 } 842 843 action(so_setOwnerBit, "so", desc="We saw other sharers") { 844 assert(is_valid(tbe)); 845 tbe.Sharers := true; 846 tbe.Owned := true; 847 } 848 849 action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { 850 peek(requestQueue_in, RequestMsg) { 851 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency); 852 } 853 } 854 855 action(qd_queueMemoryRequestFromDmaRead, "qd", desc="Queue off-chip fetch request") { 856 peek(dmaRequestQueue_in, DMARequestMsg) { 857 queueMemoryRead(in_msg.Requestor, address, to_memory_controller_latency); 858 } 859 } 860 861 action(fn_forwardRequestIfNecessary, "fn", desc="Forward requests if necessary") { 862 assert(is_valid(tbe)); 863 if ((machineCount(MachineType:L1Cache) > 1) && (tbe.Acks <= 1)) { 864 if (full_bit_dir_enabled) { 865 assert(is_valid(cache_entry)); 866 peek(requestQueue_in, RequestMsg) { 867 fwd_set := cache_entry.Sharers; 868 fwd_set.remove(machineIDToNodeID(in_msg.Requestor)); 869 if (fwd_set.count() > 0) { 870 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 871 out_msg.addr := address; 872 out_msg.Type := in_msg.Type; 873 out_msg.Requestor := in_msg.Requestor; 874 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set); 875 out_msg.MessageSize := MessageSizeType:Multicast_Control; 876 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 877 out_msg.ForwardRequestTime := curCycle(); 878 assert(tbe.SilentAcks > 0); 879 out_msg.SilentAcks := tbe.SilentAcks; 880 } 881 } 882 } 883 } else { 884 peek(requestQueue_in, RequestMsg) { 885 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 886 out_msg.addr := address; 887 out_msg.Type := in_msg.Type; 888 out_msg.Requestor := in_msg.Requestor; 889 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches 890 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor 891 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 892 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 893 out_msg.ForwardRequestTime := curCycle(); 894 } 895 } 896 } 897 } 898 } 899 900 action(ia_invalidateAllRequest, "ia", desc="invalidate all copies") { 901 if (machineCount(MachineType:L1Cache) > 1) { 902 if (full_bit_dir_enabled) { 903 assert(cache_entry.Sharers.count() > 0); 904 peek(requestQueue_in, RequestMsg) { 905 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 906 out_msg.addr := address; 907 out_msg.Type := CoherenceRequestType:INV; 908 out_msg.Requestor := machineID; 909 out_msg.Destination.setNetDest(MachineType:L1Cache, cache_entry.Sharers); 910 out_msg.MessageSize := MessageSizeType:Multicast_Control; 911 } 912 } 913 } else { 914 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 915 out_msg.addr := address; 916 out_msg.Type := CoherenceRequestType:INV; 917 out_msg.Requestor := machineID; 918 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches 919 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 920 } 921 } 922 } 923 } 924 925 action(io_invalidateOwnerRequest, "io", desc="invalidate all copies") { 926 if (machineCount(MachineType:L1Cache) > 1) { 927 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 928 assert(is_valid(cache_entry)); 929 out_msg.addr := address; 930 out_msg.Type := CoherenceRequestType:INV; 931 out_msg.Requestor := machineID; 932 out_msg.Destination.add(cache_entry.Owner); 933 out_msg.MessageSize := MessageSizeType:Request_Control; 934 out_msg.DirectedProbe := true; 935 } 936 } 937 } 938 939 action(fb_forwardRequestBcast, "fb", desc="Forward requests to all nodes") { 940 if (machineCount(MachineType:L1Cache) > 1) { 941 peek(requestQueue_in, RequestMsg) { 942 if (full_bit_dir_enabled) { 943 fwd_set := cache_entry.Sharers; 944 fwd_set.remove(machineIDToNodeID(in_msg.Requestor)); 945 if (fwd_set.count() > 0) { 946 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 947 out_msg.addr := address; 948 out_msg.Type := in_msg.Type; 949 out_msg.Requestor := in_msg.Requestor; 950 out_msg.Destination.setNetDest(MachineType:L1Cache, fwd_set); 951 out_msg.MessageSize := MessageSizeType:Multicast_Control; 952 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 953 out_msg.ForwardRequestTime := curCycle(); 954 out_msg.SilentAcks := machineCount(MachineType:L1Cache) - fwd_set.count(); 955 out_msg.SilentAcks := out_msg.SilentAcks - 1; 956 } 957 } 958 } else { 959 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 960 out_msg.addr := address; 961 out_msg.Type := in_msg.Type; 962 out_msg.Requestor := in_msg.Requestor; 963 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches 964 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor 965 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 966 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 967 out_msg.ForwardRequestTime := curCycle(); 968 } 969 } 970 } 971 } else { 972 peek(requestQueue_in, RequestMsg) { 973 enqueue(responseNetwork_out, ResponseMsg, 1) { 974 out_msg.addr := address; 975 out_msg.Type := CoherenceResponseType:ACK; 976 out_msg.Sender := machineID; 977 out_msg.Destination.add(in_msg.Requestor); 978 out_msg.Dirty := false; // By definition, the block is now clean 979 out_msg.Acks := 0; 980 out_msg.SilentAcks := 0; 981 DPRINTF(RubySlicc, "%d\n", out_msg.Acks); 982 out_msg.MessageSize := MessageSizeType:Response_Control; 983 } 984 } 985 } 986 } 987 988 action(fr_forwardMergeReadRequestsToOwner, "frr", desc="Forward coalesced read request to owner") { 989 assert(machineCount(MachineType:L1Cache) > 1); 990 // 991 // Fixme! The unblock network should not stall on the forward network. Add a trigger queue to 992 // decouple the two. 993 // 994 peek(unblockNetwork_in, ResponseMsg) { 995 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 996 assert(is_valid(tbe)); 997 out_msg.addr := address; 998 out_msg.Type := CoherenceRequestType:MERGED_GETS; 999 out_msg.MergedRequestors := tbe.GetSRequestors; 1000 if (in_msg.Type == CoherenceResponseType:UNBLOCKS) { 1001 out_msg.Destination.add(in_msg.CurOwner); 1002 } else { 1003 out_msg.Destination.add(in_msg.Sender); 1004 } 1005 out_msg.MessageSize := MessageSizeType:Request_Control; 1006 out_msg.InitialRequestTime := zero_time(); 1007 out_msg.ForwardRequestTime := curCycle(); 1008 } 1009 } 1010 } 1011 1012 action(fc_forwardRequestConditionalOwner, "fc", desc="Forward request to one or more nodes") { 1013 assert(machineCount(MachineType:L1Cache) > 1); 1014 if (probe_filter_enabled || full_bit_dir_enabled) { 1015 peek(requestQueue_in, RequestMsg) { 1016 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1017 assert(is_valid(cache_entry)); 1018 out_msg.addr := address; 1019 out_msg.Type := in_msg.Type; 1020 out_msg.Requestor := in_msg.Requestor; 1021 out_msg.Destination.add(cache_entry.Owner); 1022 out_msg.MessageSize := MessageSizeType:Request_Control; 1023 out_msg.DirectedProbe := true; 1024 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 1025 out_msg.ForwardRequestTime := curCycle(); 1026 } 1027 } 1028 } else { 1029 peek(requestQueue_in, RequestMsg) { 1030 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1031 out_msg.addr := address; 1032 out_msg.Type := in_msg.Type; 1033 out_msg.Requestor := in_msg.Requestor; 1034 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches 1035 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor 1036 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 1037 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 1038 out_msg.ForwardRequestTime := curCycle(); 1039 } 1040 } 1041 } 1042 } 1043 1044 action(nofc_forwardRequestConditionalOwner, "nofc", desc="Forward request to one or more nodes if the requestor is not the owner") { 1045 if (machineCount(MachineType:L1Cache) > 1) { 1046 1047 if (probe_filter_enabled || full_bit_dir_enabled) { 1048 peek(requestQueue_in, RequestMsg) { 1049 if (in_msg.Requestor != cache_entry.Owner) { 1050 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1051 assert(is_valid(cache_entry)); 1052 out_msg.addr := address; 1053 out_msg.Type := in_msg.Type; 1054 out_msg.Requestor := in_msg.Requestor; 1055 out_msg.Destination.add(cache_entry.Owner); 1056 out_msg.MessageSize := MessageSizeType:Request_Control; 1057 out_msg.DirectedProbe := true; 1058 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 1059 out_msg.ForwardRequestTime := curCycle(); 1060 } 1061 } 1062 } 1063 } else { 1064 peek(requestQueue_in, RequestMsg) { 1065 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1066 out_msg.addr := address; 1067 out_msg.Type := in_msg.Type; 1068 out_msg.Requestor := in_msg.Requestor; 1069 out_msg.Destination.broadcast(MachineType:L1Cache); // Send to all L1 caches 1070 out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor 1071 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 1072 out_msg.InitialRequestTime := in_msg.InitialRequestTime; 1073 out_msg.ForwardRequestTime := curCycle(); 1074 } 1075 } 1076 } 1077 } 1078 } 1079 1080 action(f_forwardWriteFromDma, "fw", desc="Forward requests") { 1081 assert(is_valid(tbe)); 1082 if (tbe.NumPendingMsgs > 0) { 1083 peek(dmaRequestQueue_in, DMARequestMsg) { 1084 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1085 out_msg.addr := address; 1086 out_msg.Type := CoherenceRequestType:GETX; 1087 // 1088 // Send to all L1 caches, since the requestor is the memory controller 1089 // itself 1090 // 1091 out_msg.Requestor := machineID; 1092 out_msg.Destination.broadcast(MachineType:L1Cache); 1093 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 1094 } 1095 } 1096 } 1097 } 1098 1099 action(f_forwardReadFromDma, "fr", desc="Forward requests") { 1100 assert(is_valid(tbe)); 1101 if (tbe.NumPendingMsgs > 0) { 1102 peek(dmaRequestQueue_in, DMARequestMsg) { 1103 enqueue(forwardNetwork_out, RequestMsg, from_memory_controller_latency) { 1104 out_msg.addr := address; 1105 out_msg.Type := CoherenceRequestType:GETS; 1106 // 1107 // Send to all L1 caches, since the requestor is the memory controller 1108 // itself 1109 // 1110 out_msg.Requestor := machineID; 1111 out_msg.Destination.broadcast(MachineType:L1Cache); 1112 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 1113 } 1114 } 1115 } 1116 } 1117 1118 action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") { 1119 requestQueue_in.dequeue(clockEdge()); 1120 } 1121 1122 action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") { 1123 peek(unblockNetwork_in, ResponseMsg) { 1124 APPEND_TRANSITION_COMMENT(in_msg.Sender); 1125 } 1126 unblockNetwork_in.dequeue(clockEdge()); 1127 } 1128 1129 action(k_wakeUpDependents, "k", desc="wake-up dependents") { 1130 wakeUpBuffers(address); 1131 } 1132 1133 action(l_popMemQueue, "q", desc="Pop off-chip request queue") { 1134 memQueue_in.dequeue(clockEdge()); 1135 } 1136 1137 action(g_popTriggerQueue, "g", desc="Pop trigger queue") { 1138 triggerQueue_in.dequeue(clockEdge()); 1139 } 1140 1141 action(p_popDmaRequestQueue, "pd", desc="pop dma request queue") { 1142 dmaRequestQueue_in.dequeue(clockEdge()); 1143 } 1144 1145 action(zd_stallAndWaitDMARequest, "zd", desc="Stall and wait the dma request queue") { 1146 peek(dmaRequestQueue_in, DMARequestMsg) { 1147 APPEND_TRANSITION_COMMENT(in_msg.Requestor); 1148 } 1149 stall_and_wait(dmaRequestQueue_in, address); 1150 } 1151 1152 action(r_recordMemoryData, "rd", desc="record data from memory to TBE") { 1153 peek(memQueue_in, MemoryMsg) { 1154 assert(is_valid(tbe)); 1155 if (tbe.CacheDirty == false) { 1156 tbe.DataBlk := in_msg.DataBlk; 1157 } 1158 } 1159 } 1160 1161 action(r_recordCacheData, "rc", desc="record data from cache response to TBE") { 1162 peek(responseToDir_in, ResponseMsg) { 1163 assert(is_valid(tbe)); 1164 tbe.CacheDirty := true; 1165 tbe.DataBlk := in_msg.DataBlk; 1166 } 1167 } 1168 1169 action(a_assertCacheData, "ac", desc="Assert that a cache provided the data") { 1170 assert(is_valid(tbe)); 1171 assert(tbe.CacheDirty); 1172 } 1173 1174 action(ano_assertNotOwner, "ano", desc="Assert that request is not current owner") { 1175 if (probe_filter_enabled || full_bit_dir_enabled) { 1176 peek(requestQueue_in, RequestMsg) { 1177 assert(is_valid(cache_entry)); 1178 assert(cache_entry.Owner != in_msg.Requestor); 1179 } 1180 } 1181 } 1182 1183 action(ans_assertNotSharer, "ans", desc="Assert that request is not a current sharer") { 1184 if (full_bit_dir_enabled) { 1185 peek(requestQueue_in, RequestMsg) { 1186 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Requestor)) == false); 1187 } 1188 } 1189 } 1190 1191 action(rs_removeSharer, "s", desc="remove current sharer") { 1192 if (full_bit_dir_enabled) { 1193 peek(unblockNetwork_in, ResponseMsg) { 1194 assert(cache_entry.Sharers.isElement(machineIDToNodeID(in_msg.Sender))); 1195 cache_entry.Sharers.remove(machineIDToNodeID(in_msg.Sender)); 1196 } 1197 } 1198 } 1199 1200 action(cs_clearSharers, "cs", desc="clear current sharers") { 1201 if (full_bit_dir_enabled) { 1202 peek(requestQueue_in, RequestMsg) { 1203 cache_entry.Sharers.clear(); 1204 cache_entry.Sharers.add(machineIDToNodeID(in_msg.Requestor)); 1205 } 1206 } 1207 } 1208 1209 action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") { 1210 peek(unblockNetwork_in, ResponseMsg) { 1211 queueMemoryWrite(in_msg.Sender, address, to_memory_controller_latency, 1212 in_msg.DataBlk); 1213 } 1214 } 1215 1216 action(ld_queueMemoryDmaWrite, "ld", desc="Write DMA data to memory") { 1217 assert(is_valid(tbe)); 1218 queueMemoryWritePartial(tbe.DmaRequestor, tbe.PhysicalAddress, 1219 to_memory_controller_latency, tbe.DmaDataBlk, 1220 tbe.Len); 1221 } 1222 1223 action(ly_queueMemoryWriteFromTBE, "ly", desc="Write data to memory from TBE") { 1224 queueMemoryWrite(machineID, address, to_memory_controller_latency, 1225 tbe.DataBlk); 1226 } 1227 1228 action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") { 1229 peek(unblockNetwork_in, ResponseMsg) { 1230 assert(in_msg.Dirty == false); 1231 assert(in_msg.MessageSize == MessageSizeType:Writeback_Control); 1232 DPRINTF(RubySlicc, "%s\n", in_msg.DataBlk); 1233 } 1234 } 1235 1236 action(z_stallAndWaitRequest, "z", desc="Recycle the request queue") { 1237 peek(requestQueue_in, RequestMsg) { 1238 APPEND_TRANSITION_COMMENT(in_msg.Requestor); 1239 } 1240 stall_and_wait(requestQueue_in, address); 1241 } 1242 1243 // TRANSITIONS 1244 1245 // Transitions out of E state 1246 transition(E, GETX, NO_B_W) { 1247 pfa_probeFilterAllocate; 1248 v_allocateTBE; 1249 rx_recordExclusiveInTBE; 1250 saa_setAcksToAllIfPF; 1251 qf_queueMemoryFetchRequest; 1252 fn_forwardRequestIfNecessary; 1253 i_popIncomingRequestQueue; 1254 } 1255 1256 transition(E, GETF, NO_F_W) { 1257 pfa_probeFilterAllocate; 1258 v_allocateTBE; 1259 rx_recordExclusiveInTBE; 1260 saa_setAcksToAllIfPF; 1261 qf_queueMemoryFetchRequest; 1262 fn_forwardRequestIfNecessary; 1263 i_popIncomingRequestQueue; 1264 } 1265 1266 transition(E, GETS, NO_B_W) { 1267 pfa_probeFilterAllocate; 1268 v_allocateTBE; 1269 rx_recordExclusiveInTBE; 1270 saa_setAcksToAllIfPF; 1271 qf_queueMemoryFetchRequest; 1272 fn_forwardRequestIfNecessary; 1273 i_popIncomingRequestQueue; 1274 } 1275 1276 transition(E, DMA_READ, NO_DR_B_W) { 1277 vd_allocateDmaRequestInTBE; 1278 qd_queueMemoryRequestFromDmaRead; 1279 spa_setPendingAcksToZeroIfPF; 1280 f_forwardReadFromDma; 1281 p_popDmaRequestQueue; 1282 } 1283 1284 transition(E, DMA_WRITE, NO_DW_B_W) { 1285 vd_allocateDmaRequestInTBE; 1286 spa_setPendingAcksToZeroIfPF; 1287 sc_signalCompletionIfPF; 1288 f_forwardWriteFromDma; 1289 p_popDmaRequestQueue; 1290 } 1291 1292 // Transitions out of O state 1293 transition(O, GETX, NO_B_W) { 1294 r_setMRU; 1295 v_allocateTBE; 1296 r_recordDataInTBE; 1297 sa_setAcksToOne; 1298 qf_queueMemoryFetchRequest; 1299 fb_forwardRequestBcast; 1300 cs_clearSharers; 1301 i_popIncomingRequestQueue; 1302 } 1303 1304 transition(O, GETF, NO_F_W) { 1305 r_setMRU; 1306 v_allocateTBE; 1307 r_recordDataInTBE; 1308 sa_setAcksToOne; 1309 qf_queueMemoryFetchRequest; 1310 fb_forwardRequestBcast; 1311 cs_clearSharers; 1312 i_popIncomingRequestQueue; 1313 } 1314 1315 // This transition is dumb, if a shared copy exists on-chip, then that should 1316 // provide data, not slow off-chip dram. The problem is that the current 1317 // caches don't provide data in S state 1318 transition(O, GETS, O_B_W) { 1319 r_setMRU; 1320 v_allocateTBE; 1321 r_recordDataInTBE; 1322 saa_setAcksToAllIfPF; 1323 qf_queueMemoryFetchRequest; 1324 fn_forwardRequestIfNecessary; 1325 i_popIncomingRequestQueue; 1326 } 1327 1328 transition(O, DMA_READ, O_DR_B_W) { 1329 vd_allocateDmaRequestInTBE; 1330 spa_setPendingAcksToZeroIfPF; 1331 qd_queueMemoryRequestFromDmaRead; 1332 f_forwardReadFromDma; 1333 p_popDmaRequestQueue; 1334 } 1335 1336 transition(O, Pf_Replacement, O_R) { 1337 v_allocateTBE; 1338 pa_setPendingMsgsToAll; 1339 ia_invalidateAllRequest; 1340 pfd_probeFilterDeallocate; 1341 } 1342 1343 transition(S, Pf_Replacement, S_R) { 1344 v_allocateTBE; 1345 pa_setPendingMsgsToAll; 1346 ia_invalidateAllRequest; 1347 pfd_probeFilterDeallocate; 1348 } 1349 1350 transition(NO, Pf_Replacement, NO_R) { 1351 v_allocateTBE; 1352 po_setPendingMsgsToOne; 1353 io_invalidateOwnerRequest; 1354 pfd_probeFilterDeallocate; 1355 } 1356 1357 transition(NX, Pf_Replacement, NO_R) { 1358 v_allocateTBE; 1359 pa_setPendingMsgsToAll; 1360 ia_invalidateAllRequest; 1361 pfd_probeFilterDeallocate; 1362 } 1363 1364 transition({O, S, NO, NX}, DMA_WRITE, NO_DW_B_W) { 1365 vd_allocateDmaRequestInTBE; 1366 f_forwardWriteFromDma; 1367 p_popDmaRequestQueue; 1368 } 1369 1370 // Transitions out of NO state 1371 transition(NX, GETX, NO_B) { 1372 r_setMRU; 1373 fb_forwardRequestBcast; 1374 cs_clearSharers; 1375 i_popIncomingRequestQueue; 1376 } 1377 1378 transition(NX, GETF, NO_F) { 1379 r_setMRU; 1380 fb_forwardRequestBcast; 1381 cs_clearSharers; 1382 i_popIncomingRequestQueue; 1383 } 1384 1385 // Transitions out of NO state 1386 transition(NO, GETX, NO_B) { 1387 r_setMRU; 1388 ano_assertNotOwner; 1389 fc_forwardRequestConditionalOwner; 1390 cs_clearSharers; 1391 i_popIncomingRequestQueue; 1392 } 1393 1394 transition(NO, GETF, NO_F) { 1395 r_setMRU; 1396 //ano_assertNotOwner; 1397 nofc_forwardRequestConditionalOwner; //forward request if the requester is not the owner 1398 cs_clearSharers; 1399 oc_sendBlockAck; // send ack if the owner 1400 i_popIncomingRequestQueue; 1401 } 1402 1403 transition(S, GETX, NO_B) { 1404 r_setMRU; 1405 fb_forwardRequestBcast; 1406 cs_clearSharers; 1407 i_popIncomingRequestQueue; 1408 } 1409 1410 transition(S, GETF, NO_F) { 1411 r_setMRU; 1412 fb_forwardRequestBcast; 1413 cs_clearSharers; 1414 i_popIncomingRequestQueue; 1415 } 1416 1417 transition(S, GETS, NO_B) { 1418 r_setMRU; 1419 ano_assertNotOwner; 1420 fb_forwardRequestBcast; 1421 i_popIncomingRequestQueue; 1422 } 1423 1424 transition(NO, GETS, NO_B) { 1425 r_setMRU; 1426 ano_assertNotOwner; 1427 ans_assertNotSharer; 1428 fc_forwardRequestConditionalOwner; 1429 i_popIncomingRequestQueue; 1430 } 1431 1432 transition(NX, GETS, NO_B) { 1433 r_setMRU; 1434 ano_assertNotOwner; 1435 fc_forwardRequestConditionalOwner; 1436 i_popIncomingRequestQueue; 1437 } 1438 1439 transition({NO, NX, S}, PUT, WB) { 1440 // 1441 // note that the PUT requestor may not be the current owner if an invalidate 1442 // raced with PUT 1443 // 1444 a_sendWriteBackAck; 1445 i_popIncomingRequestQueue; 1446 } 1447 1448 transition({NO, NX, S}, DMA_READ, NO_DR_B_D) { 1449 vd_allocateDmaRequestInTBE; 1450 f_forwardReadFromDma; 1451 p_popDmaRequestQueue; 1452 } 1453 1454 // Nack PUT requests when races cause us to believe we own the data 1455 transition({O, E}, PUT) { 1456 b_sendWriteBackNack; 1457 i_popIncomingRequestQueue; 1458 } 1459 1460 // Blocked transient states 1461 transition({NO_B_X, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, 1462 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W, 1463 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W}, 1464 {GETS, GETX, GETF, PUT, Pf_Replacement}) { 1465 z_stallAndWaitRequest; 1466 } 1467 1468 transition(NO_F, {GETS, GETX, GETF, PUT, Pf_Replacement}){ 1469 z_stallAndWaitRequest; 1470 } 1471 1472 transition(NO_B, {GETX, GETF}, NO_B_X) { 1473 z_stallAndWaitRequest; 1474 } 1475 1476 transition(NO_B, {PUT, Pf_Replacement}) { 1477 z_stallAndWaitRequest; 1478 } 1479 1480 transition(NO_B_S, {GETX, GETF, PUT, Pf_Replacement}) { 1481 z_stallAndWaitRequest; 1482 } 1483 1484 transition({NO_B_X, NO_B, NO_B_S, O_B, NO_DR_B_W, NO_DW_B_W, NO_B_W, NO_DR_B_D, 1485 NO_DR_B, O_DR_B, O_B_W, O_DR_B_W, NO_DW_W, NO_B_S_W, 1486 NO_W, O_W, WB, WB_E_W, WB_O_W, O_R, S_R, NO_R, NO_F_W}, 1487 {DMA_READ, DMA_WRITE}) { 1488 zd_stallAndWaitDMARequest; 1489 } 1490 1491 // merge GETS into one response 1492 transition(NO_B, GETS, NO_B_S) { 1493 v_allocateTBE; 1494 rs_recordGetSRequestor; 1495 i_popIncomingRequestQueue; 1496 } 1497 1498 transition(NO_B_S, GETS) { 1499 rs_recordGetSRequestor; 1500 i_popIncomingRequestQueue; 1501 } 1502 1503 // unblock responses 1504 transition({NO_B, NO_B_X}, UnblockS, NX) { 1505 us_updateSharerIfFBD; 1506 k_wakeUpDependents; 1507 j_popIncomingUnblockQueue; 1508 } 1509 1510 transition({NO_B, NO_B_X}, UnblockM, NO) { 1511 uo_updateOwnerIfPf; 1512 us_updateSharerIfFBD; 1513 k_wakeUpDependents; 1514 j_popIncomingUnblockQueue; 1515 } 1516 1517 transition(NO_B_S, UnblockS, NO_B_S_W) { 1518 us_updateSharerIfFBD; 1519 fr_forwardMergeReadRequestsToOwner; 1520 sp_setPendingMsgsToMergedSharers; 1521 j_popIncomingUnblockQueue; 1522 } 1523 1524 transition(NO_B_S, UnblockM, NO_B_S_W) { 1525 uo_updateOwnerIfPf; 1526 fr_forwardMergeReadRequestsToOwner; 1527 sp_setPendingMsgsToMergedSharers; 1528 j_popIncomingUnblockQueue; 1529 } 1530 1531 transition(NO_B_S_W, UnblockS) { 1532 us_updateSharerIfFBD; 1533 mu_decrementNumberOfUnblocks; 1534 os_checkForMergedGetSCompletion; 1535 j_popIncomingUnblockQueue; 1536 } 1537 1538 transition(NO_B_S_W, All_Unblocks, NX) { 1539 w_deallocateTBE; 1540 k_wakeUpDependents; 1541 g_popTriggerQueue; 1542 } 1543 1544 transition(O_B, UnblockS, O) { 1545 us_updateSharerIfFBD; 1546 k_wakeUpDependents; 1547 j_popIncomingUnblockQueue; 1548 } 1549 1550 transition(O_B, UnblockM, NO) { 1551 us_updateSharerIfFBD; 1552 uo_updateOwnerIfPf; 1553 k_wakeUpDependents; 1554 j_popIncomingUnblockQueue; 1555 } 1556 1557 transition(NO_B_W, Memory_Data, NO_B) { 1558 d_sendData; 1559 w_deallocateTBE; 1560 l_popMemQueue; 1561 } 1562 1563 transition(NO_F_W, Memory_Data, NO_F) { 1564 d_sendData; 1565 w_deallocateTBE; 1566 l_popMemQueue; 1567 } 1568 1569 transition(NO_DR_B_W, Memory_Data, NO_DR_B) { 1570 r_recordMemoryData; 1571 o_checkForCompletion; 1572 l_popMemQueue; 1573 } 1574 1575 transition(O_DR_B_W, Memory_Data, O_DR_B) { 1576 r_recordMemoryData; 1577 dr_sendDmaData; 1578 o_checkForCompletion; 1579 l_popMemQueue; 1580 } 1581 1582 transition({NO_DR_B, O_DR_B, NO_DR_B_D, NO_DW_B_W}, Ack) { 1583 m_decrementNumberOfMessages; 1584 o_checkForCompletion; 1585 n_popResponseQueue; 1586 } 1587 1588 transition({O_R, S_R, NO_R}, Ack) { 1589 m_decrementNumberOfMessages; 1590 o_checkForCompletion; 1591 n_popResponseQueue; 1592 } 1593 1594 transition(S_R, Data) { 1595 m_decrementNumberOfMessages; 1596 o_checkForCompletion; 1597 n_popResponseQueue; 1598 } 1599 1600 transition(NO_R, {Data, Exclusive_Data}) { 1601 r_recordCacheData; 1602 m_decrementNumberOfMessages; 1603 o_checkForCompletion; 1604 n_popResponseQueue; 1605 } 1606 1607 transition({O_R, S_R}, All_acks_and_data_no_sharers, E) { 1608 w_deallocateTBE; 1609 k_wakeUpDependents; 1610 g_popTriggerQueue; 1611 } 1612 1613 transition(NO_R, All_acks_and_data_no_sharers, WB_E_W) { 1614 ly_queueMemoryWriteFromTBE; 1615 w_deallocateTBE; 1616 k_wakeUpDependents; 1617 g_popTriggerQueue; 1618 } 1619 1620 transition({NO_DR_B_W, O_DR_B_W}, Ack) { 1621 m_decrementNumberOfMessages; 1622 n_popResponseQueue; 1623 } 1624 1625 transition(NO_DR_B_W, Shared_Ack) { 1626 m_decrementNumberOfMessages; 1627 r_setSharerBit; 1628 n_popResponseQueue; 1629 } 1630 1631 transition(O_DR_B, Shared_Ack) { 1632 m_decrementNumberOfMessages; 1633 r_setSharerBit; 1634 o_checkForCompletion; 1635 n_popResponseQueue; 1636 } 1637 1638 transition(O_DR_B_W, Shared_Ack) { 1639 m_decrementNumberOfMessages; 1640 r_setSharerBit; 1641 n_popResponseQueue; 1642 } 1643 1644 transition({NO_DR_B, NO_DR_B_D}, Shared_Ack) { 1645 m_decrementNumberOfMessages; 1646 r_setSharerBit; 1647 o_checkForCompletion; 1648 n_popResponseQueue; 1649 } 1650 1651 transition(NO_DR_B_W, Shared_Data) { 1652 r_recordCacheData; 1653 m_decrementNumberOfMessages; 1654 so_setOwnerBit; 1655 o_checkForCompletion; 1656 n_popResponseQueue; 1657 } 1658 1659 transition({NO_DR_B, NO_DR_B_D}, Shared_Data) { 1660 r_recordCacheData; 1661 m_decrementNumberOfMessages; 1662 so_setOwnerBit; 1663 o_checkForCompletion; 1664 n_popResponseQueue; 1665 } 1666 1667 transition(NO_DR_B_W, {Exclusive_Data, Data}) { 1668 r_recordCacheData; 1669 m_decrementNumberOfMessages; 1670 n_popResponseQueue; 1671 } 1672 1673 transition({NO_DR_B, NO_DR_B_D, NO_DW_B_W}, {Exclusive_Data, Data}) { 1674 r_recordCacheData; 1675 m_decrementNumberOfMessages; 1676 o_checkForCompletion; 1677 n_popResponseQueue; 1678 } 1679 1680 transition(NO_DR_B, All_acks_and_owner_data, WB_O_W) { 1681 // 1682 // Note that the DMA consistency model allows us to send the DMA device 1683 // a response as soon as we receive valid data and prior to receiving 1684 // all acks. However, to simplify the protocol we wait for all acks. 1685 // 1686 dt_sendDmaDataFromTbe; 1687 ly_queueMemoryWriteFromTBE; 1688 w_deallocateTBE; 1689 k_wakeUpDependents; 1690 g_popTriggerQueue; 1691 } 1692 1693 transition(NO_DR_B, All_acks_and_shared_data, S) { 1694 // 1695 // Note that the DMA consistency model allows us to send the DMA device 1696 // a response as soon as we receive valid data and prior to receiving 1697 // all acks. However, to simplify the protocol we wait for all acks. 1698 // 1699 dt_sendDmaDataFromTbe; 1700 w_deallocateTBE; 1701 k_wakeUpDependents; 1702 g_popTriggerQueue; 1703 } 1704 1705 transition(NO_DR_B_D, All_acks_and_owner_data, WB_O_W) { 1706 // 1707 // Note that the DMA consistency model allows us to send the DMA device 1708 // a response as soon as we receive valid data and prior to receiving 1709 // all acks. However, to simplify the protocol we wait for all acks. 1710 // 1711 dt_sendDmaDataFromTbe; 1712 ly_queueMemoryWriteFromTBE; 1713 w_deallocateTBE; 1714 k_wakeUpDependents; 1715 g_popTriggerQueue; 1716 } 1717 1718 transition(NO_DR_B_D, All_acks_and_shared_data, S) { 1719 // 1720 // Note that the DMA consistency model allows us to send the DMA device 1721 // a response as soon as we receive valid data and prior to receiving 1722 // all acks. However, to simplify the protocol we wait for all acks. 1723 // 1724 dt_sendDmaDataFromTbe; 1725 w_deallocateTBE; 1726 k_wakeUpDependents; 1727 g_popTriggerQueue; 1728 } 1729 1730 transition(O_DR_B, All_acks_and_owner_data, WB_O_W) { 1731 ly_queueMemoryWriteFromTBE; 1732 w_deallocateTBE; 1733 k_wakeUpDependents; 1734 g_popTriggerQueue; 1735 } 1736 1737 transition(O_DR_B, All_acks_and_data_no_sharers, WB_E_W) { 1738 ly_queueMemoryWriteFromTBE; 1739 w_deallocateTBE; 1740 pfd_probeFilterDeallocate; 1741 k_wakeUpDependents; 1742 g_popTriggerQueue; 1743 } 1744 1745 transition(NO_DR_B, All_acks_and_data_no_sharers, WB_E_W) { 1746 // 1747 // Note that the DMA consistency model allows us to send the DMA device 1748 // a response as soon as we receive valid data and prior to receiving 1749 // all acks. However, to simplify the protocol we wait for all acks. 1750 // 1751 dt_sendDmaDataFromTbe; 1752 ly_queueMemoryWriteFromTBE; 1753 w_deallocateTBE; 1754 ppfd_possibleProbeFilterDeallocate; 1755 k_wakeUpDependents; 1756 g_popTriggerQueue; 1757 } 1758 1759 transition(NO_DR_B_D, All_acks_and_data_no_sharers, WB_E_W) { 1760 a_assertCacheData; 1761 // 1762 // Note that the DMA consistency model allows us to send the DMA device 1763 // a response as soon as we receive valid data and prior to receiving 1764 // all acks. However, to simplify the protocol we wait for all acks. 1765 // 1766 dt_sendDmaDataFromTbe; 1767 ly_queueMemoryWriteFromTBE; 1768 w_deallocateTBE; 1769 ppfd_possibleProbeFilterDeallocate; 1770 k_wakeUpDependents; 1771 g_popTriggerQueue; 1772 } 1773 1774 transition(NO_DW_B_W, All_acks_and_data_no_sharers, NO_DW_W) { 1775 ld_queueMemoryDmaWrite; 1776 g_popTriggerQueue; 1777 } 1778 1779 transition(NO_DW_W, Memory_Ack, E) { 1780 da_sendDmaAck; 1781 w_deallocateTBE; 1782 ppfd_possibleProbeFilterDeallocate; 1783 k_wakeUpDependents; 1784 l_popMemQueue; 1785 } 1786 1787 transition(O_B_W, Memory_Data, O_B) { 1788 d_sendData; 1789 w_deallocateTBE; 1790 l_popMemQueue; 1791 } 1792 1793 transition(NO_B_W, UnblockM, NO_W) { 1794 uo_updateOwnerIfPf; 1795 j_popIncomingUnblockQueue; 1796 } 1797 1798 transition(NO_B_W, UnblockS, NO_W) { 1799 us_updateSharerIfFBD; 1800 j_popIncomingUnblockQueue; 1801 } 1802 1803 transition(O_B_W, UnblockS, O_W) { 1804 us_updateSharerIfFBD; 1805 j_popIncomingUnblockQueue; 1806 } 1807 1808 transition(NO_W, Memory_Data, NO) { 1809 w_deallocateTBE; 1810 k_wakeUpDependents; 1811 l_popMemQueue; 1812 } 1813 1814 transition(O_W, Memory_Data, O) { 1815 w_deallocateTBE; 1816 k_wakeUpDependents; 1817 l_popMemQueue; 1818 } 1819 1820 // WB State Transistions 1821 transition(WB, Writeback_Dirty, WB_O_W) { 1822 rs_removeSharer; 1823 l_queueMemoryWBRequest; 1824 j_popIncomingUnblockQueue; 1825 } 1826 1827 transition(WB, Writeback_Exclusive_Dirty, WB_E_W) { 1828 rs_removeSharer; 1829 l_queueMemoryWBRequest; 1830 pfd_probeFilterDeallocate; 1831 j_popIncomingUnblockQueue; 1832 } 1833 1834 transition(WB_E_W, Memory_Ack, E) { 1835 k_wakeUpDependents; 1836 l_popMemQueue; 1837 } 1838 1839 transition(WB_O_W, Memory_Ack, O) { 1840 k_wakeUpDependents; 1841 l_popMemQueue; 1842 } 1843 1844 transition(WB, Writeback_Clean, O) { 1845 ll_checkIncomingWriteback; 1846 rs_removeSharer; 1847 k_wakeUpDependents; 1848 j_popIncomingUnblockQueue; 1849 } 1850 1851 transition(WB, Writeback_Exclusive_Clean, E) { 1852 ll_checkIncomingWriteback; 1853 rs_removeSharer; 1854 pfd_probeFilterDeallocate; 1855 k_wakeUpDependents; 1856 j_popIncomingUnblockQueue; 1857 } 1858 1859 transition(WB, Unblock, NX) { 1860 auno_assertUnblockerNotOwner; 1861 k_wakeUpDependents; 1862 j_popIncomingUnblockQueue; 1863 } 1864 1865 transition(NO_F, PUTF, WB) { 1866 a_sendWriteBackAck; 1867 i_popIncomingRequestQueue; 1868 } 1869 1870 //possible race between GETF and UnblockM -- not sure needed any more? 1871 transition(NO_F, UnblockM) { 1872 us_updateSharerIfFBD; 1873 uo_updateOwnerIfPf; 1874 j_popIncomingUnblockQueue; 1875 } 1876} 1877