MOESI_CMP_token-L2cache.sm revision 14184:11ac1337c5e2
1/* 2 * Copyright (c) 1999-2013 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29machine(MachineType:L2Cache, "Token protocol") 30 : CacheMemory * L2cache; 31 int N_tokens; 32 Cycles l2_request_latency := 5; 33 Cycles l2_response_latency := 5; 34 bool filtering_enabled := "True"; 35 36 // L2 BANK QUEUES 37 // From local bank of L2 cache TO the network 38 39 // this L2 bank -> a local L1 || mod-directory 40 MessageBuffer * responseFromL2Cache, network="To", virtual_network="4", 41 vnet_type="response"; 42 // this L2 bank -> mod-directory 43 MessageBuffer * GlobalRequestFromL2Cache, network="To", virtual_network="2", 44 vnet_type="request"; 45 // this L2 bank -> a local L1 46 MessageBuffer * L1RequestFromL2Cache, network="To", virtual_network="1", 47 vnet_type="request"; 48 49 50 // FROM the network to this local bank of L2 cache 51 52 // a local L1 || mod-directory -> this L2 bank 53 MessageBuffer * responseToL2Cache, network="From", virtual_network="4", 54 vnet_type="response"; 55 MessageBuffer * persistentToL2Cache, network="From", virtual_network="3", 56 vnet_type="persistent"; 57 // mod-directory -> this L2 bank 58 MessageBuffer * GlobalRequestToL2Cache, network="From", virtual_network="2", 59 vnet_type="request"; 60 // a local L1 -> this L2 bank 61 MessageBuffer * L1RequestToL2Cache, network="From", virtual_network="1", 62 vnet_type="request"; 63 64{ 65 // STATES 66 state_declaration(State, desc="L2 Cache states", default="L2Cache_State_I") { 67 // Base states 68 NP, AccessPermission:Invalid, desc="Not Present"; 69 I, AccessPermission:Invalid, desc="Idle"; 70 S, AccessPermission:Read_Only, desc="Shared, not present in any local L1s"; 71 O, AccessPermission:Read_Only, desc="Owned, not present in any L1s"; 72 M, AccessPermission:Read_Write, desc="Modified, not present in any L1s"; 73 74 // Locked states 75 I_L, AccessPermission:Busy, "I^L", desc="Invalid, Locked"; 76 S_L, AccessPermission:Busy, "S^L", desc="Shared, Locked"; 77 } 78 79 // EVENTS 80 enumeration(Event, desc="Cache events") { 81 82 // Requests 83 L1_GETS, desc="local L1 GETS request"; 84 L1_GETS_Last_Token, desc="local L1 GETS request"; 85 L1_GETX, desc="local L1 GETX request"; 86 L1_INV, desc="L1 no longer has tokens"; 87 Transient_GETX, desc="A GetX from another processor"; 88 Transient_GETS, desc="A GetS from another processor"; 89 Transient_GETS_Last_Token, desc="A GetS from another processor"; 90 91 // events initiated by this L2 92 L2_Replacement, desc="L2 Replacement", format="!r"; 93 94 // events of external L2 responses 95 96 // Responses 97 Writeback_Tokens, desc="Received a writeback from L1 with only tokens (no data)"; 98 Writeback_Shared_Data, desc="Received a writeback from L1 that includes clean data"; 99 Writeback_All_Tokens, desc="Received a writeback from L1"; 100 Writeback_Owned, desc="Received a writeback from L1"; 101 102 103 Data_Shared, desc="Received a data message, we are now a sharer"; 104 Data_Owner, desc="Received a data message, we are now the owner"; 105 Data_All_Tokens, desc="Received a data message, we are now the owner, we now have all the tokens"; 106 Ack, desc="Received an ack message"; 107 Ack_All_Tokens, desc="Received an ack message, we now have all the tokens"; 108 109 // Lock/Unlock 110 Persistent_GETX, desc="Another processor has priority to read/write"; 111 Persistent_GETS, desc="Another processor has priority to read"; 112 Persistent_GETS_Last_Token, desc="Another processor has priority to read"; 113 Own_Lock_or_Unlock, desc="This processor now has priority"; 114 } 115 116 // TYPES 117 118 // CacheEntry 119 structure(Entry, desc="...", interface="AbstractCacheEntry") { 120 State CacheState, desc="cache state"; 121 bool Dirty, desc="Is the data dirty (different than memory)?"; 122 int Tokens, desc="The number of tokens we're holding for the line"; 123 DataBlock DataBlk, desc="data for the block"; 124 } 125 126 structure(DirEntry, desc="...", interface="AbstractEntry") { 127 Set Sharers, desc="Set of the internal processors that want the block in shared state"; 128 bool exclusive, default="false", desc="if local exclusive is likely"; 129 } 130 131 structure(PerfectCacheMemory, external="yes") { 132 void allocate(Addr); 133 void deallocate(Addr); 134 DirEntry lookup(Addr); 135 bool isTagPresent(Addr); 136 } 137 138 structure(PersistentTable, external="yes") { 139 void persistentRequestLock(Addr, MachineID, AccessType); 140 void persistentRequestUnlock(Addr, MachineID); 141 MachineID findSmallest(Addr); 142 AccessType typeOfSmallest(Addr); 143 void markEntries(Addr); 144 bool isLocked(Addr); 145 int countStarvingForAddress(Addr); 146 int countReadStarvingForAddress(Addr); 147 } 148 149 PersistentTable persistentTable; 150 PerfectCacheMemory localDirectory, template="<L2Cache_DirEntry>"; 151 152 Tick clockEdge(); 153 void set_cache_entry(AbstractCacheEntry b); 154 void unset_cache_entry(); 155 MachineID mapAddressToMachine(Addr addr, MachineType mtype); 156 157 Entry getCacheEntry(Addr address), return_by_pointer="yes" { 158 Entry cache_entry := static_cast(Entry, "pointer", L2cache.lookup(address)); 159 return cache_entry; 160 } 161 162 DirEntry getDirEntry(Addr address), return_by_pointer="yes" { 163 return localDirectory.lookup(address); 164 } 165 166 void functionalRead(Addr addr, Packet *pkt) { 167 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt); 168 } 169 170 int functionalWrite(Addr addr, Packet *pkt) { 171 int num_functional_writes := 0; 172 num_functional_writes := num_functional_writes + 173 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt); 174 return num_functional_writes; 175 } 176 177 int getTokens(Entry cache_entry) { 178 if (is_valid(cache_entry)) { 179 return cache_entry.Tokens; 180 } else { 181 return 0; 182 } 183 } 184 185 State getState(Entry cache_entry, Addr addr) { 186 if (is_valid(cache_entry)) { 187 return cache_entry.CacheState; 188 } else if (persistentTable.isLocked(addr)) { 189 return State:I_L; 190 } else { 191 return State:NP; 192 } 193 } 194 195 void setState(Entry cache_entry, Addr addr, State state) { 196 197 if (is_valid(cache_entry)) { 198 // Make sure the token count is in range 199 assert(cache_entry.Tokens >= 0); 200 assert(cache_entry.Tokens <= max_tokens()); 201 assert(cache_entry.Tokens != (max_tokens() / 2)); 202 203 // Make sure we have no tokens in L 204 if ((state == State:I_L) ) { 205 assert(cache_entry.Tokens == 0); 206 } 207 208 // in M and E you have all the tokens 209 if (state == State:M ) { 210 assert(cache_entry.Tokens == max_tokens()); 211 } 212 213 // in NP you have no tokens 214 if (state == State:NP) { 215 assert(cache_entry.Tokens == 0); 216 } 217 218 // You have at least one token in S-like states 219 if (state == State:S ) { 220 assert(cache_entry.Tokens > 0); 221 } 222 223 // You have at least half the token in O-like states 224 if (state == State:O ) { 225 assert(cache_entry.Tokens > (max_tokens() / 2)); 226 } 227 228 cache_entry.CacheState := state; 229 } 230 } 231 232 AccessPermission getAccessPermission(Addr addr) { 233 Entry cache_entry := getCacheEntry(addr); 234 if(is_valid(cache_entry)) { 235 return L2Cache_State_to_permission(cache_entry.CacheState); 236 } 237 238 return AccessPermission:NotPresent; 239 } 240 241 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 242 if (is_valid(cache_entry)) { 243 cache_entry.changePermission(L2Cache_State_to_permission(state)); 244 } 245 } 246 247 void removeSharer(Addr addr, NodeID id) { 248 249 if (localDirectory.isTagPresent(addr)) { 250 DirEntry dir_entry := getDirEntry(addr); 251 dir_entry.Sharers.remove(id); 252 if (dir_entry.Sharers.count() == 0) { 253 localDirectory.deallocate(addr); 254 } 255 } 256 } 257 258 bool sharersExist(Addr addr) { 259 if (localDirectory.isTagPresent(addr)) { 260 DirEntry dir_entry := getDirEntry(addr); 261 if (dir_entry.Sharers.count() > 0) { 262 return true; 263 } 264 else { 265 return false; 266 } 267 } 268 else { 269 return false; 270 } 271 } 272 273 bool exclusiveExists(Addr addr) { 274 if (localDirectory.isTagPresent(addr)) { 275 DirEntry dir_entry := getDirEntry(addr); 276 if (dir_entry.exclusive) { 277 return true; 278 } 279 else { 280 return false; 281 } 282 } 283 else { 284 return false; 285 } 286 } 287 288 // assumes that caller will check to make sure tag is present 289 Set getSharers(Addr addr) { 290 DirEntry dir_entry := getDirEntry(addr); 291 return dir_entry.Sharers; 292 } 293 294 void setNewWriter(Addr addr, NodeID id) { 295 if (localDirectory.isTagPresent(addr) == false) { 296 localDirectory.allocate(addr); 297 } 298 DirEntry dir_entry := getDirEntry(addr); 299 dir_entry.Sharers.clear(); 300 dir_entry.Sharers.add(id); 301 dir_entry.exclusive := true; 302 } 303 304 void addNewSharer(Addr addr, NodeID id) { 305 if (localDirectory.isTagPresent(addr) == false) { 306 localDirectory.allocate(addr); 307 } 308 DirEntry dir_entry := getDirEntry(addr); 309 dir_entry.Sharers.add(id); 310 // dir_entry.exclusive := false; 311 } 312 313 void clearExclusiveBitIfExists(Addr addr) { 314 if (localDirectory.isTagPresent(addr)) { 315 DirEntry dir_entry := getDirEntry(addr); 316 dir_entry.exclusive := false; 317 } 318 } 319 320 // ** OUT_PORTS ** 321 out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache); 322 out_port(localRequestNetwork_out, RequestMsg, L1RequestFromL2Cache); 323 out_port(responseNetwork_out, ResponseMsg, responseFromL2Cache); 324 325 326 327 // ** IN_PORTS ** 328 329 // Persistent Network 330 in_port(persistentNetwork_in, PersistentMsg, persistentToL2Cache) { 331 if (persistentNetwork_in.isReady(clockEdge())) { 332 peek(persistentNetwork_in, PersistentMsg) { 333 assert(in_msg.Destination.isElement(machineID)); 334 335 if (in_msg.Type == PersistentRequestType:GETX_PERSISTENT) { 336 persistentTable.persistentRequestLock(in_msg.addr, in_msg.Requestor, AccessType:Write); 337 } else if (in_msg.Type == PersistentRequestType:GETS_PERSISTENT) { 338 persistentTable.persistentRequestLock(in_msg.addr, in_msg.Requestor, AccessType:Read); 339 } else if (in_msg.Type == PersistentRequestType:DEACTIVATE_PERSISTENT) { 340 persistentTable.persistentRequestUnlock(in_msg.addr, in_msg.Requestor); 341 } else { 342 error("Unexpected message"); 343 } 344 345 Entry cache_entry := getCacheEntry(in_msg.addr); 346 // React to the message based on the current state of the table 347 if (persistentTable.isLocked(in_msg.addr)) { 348 349 if (persistentTable.typeOfSmallest(in_msg.addr) == AccessType:Read) { 350 if (getTokens(cache_entry) == 1 || 351 getTokens(cache_entry) == (max_tokens() / 2) + 1) { 352 trigger(Event:Persistent_GETS_Last_Token, in_msg.addr, 353 cache_entry); 354 } else { 355 trigger(Event:Persistent_GETS, in_msg.addr, cache_entry); 356 } 357 } else { 358 trigger(Event:Persistent_GETX, in_msg.addr, cache_entry); 359 } 360 } 361 else { 362 trigger(Event:Own_Lock_or_Unlock, in_msg.addr, cache_entry); 363 } 364 } 365 } 366 } 367 368 369 // Request Network 370 in_port(requestNetwork_in, RequestMsg, GlobalRequestToL2Cache) { 371 if (requestNetwork_in.isReady(clockEdge())) { 372 peek(requestNetwork_in, RequestMsg) { 373 assert(in_msg.Destination.isElement(machineID)); 374 375 Entry cache_entry := getCacheEntry(in_msg.addr); 376 if (in_msg.Type == CoherenceRequestType:GETX) { 377 trigger(Event:Transient_GETX, in_msg.addr, cache_entry); 378 } else if (in_msg.Type == CoherenceRequestType:GETS) { 379 if (getTokens(cache_entry) == 1) { 380 trigger(Event:Transient_GETS_Last_Token, in_msg.addr, 381 cache_entry); 382 } 383 else { 384 trigger(Event:Transient_GETS, in_msg.addr, cache_entry); 385 } 386 } else { 387 error("Unexpected message"); 388 } 389 } 390 } 391 } 392 393 in_port(L1requestNetwork_in, RequestMsg, L1RequestToL2Cache) { 394 if (L1requestNetwork_in.isReady(clockEdge())) { 395 peek(L1requestNetwork_in, RequestMsg) { 396 assert(in_msg.Destination.isElement(machineID)); 397 Entry cache_entry := getCacheEntry(in_msg.addr); 398 if (in_msg.Type == CoherenceRequestType:GETX) { 399 trigger(Event:L1_GETX, in_msg.addr, cache_entry); 400 } else if (in_msg.Type == CoherenceRequestType:GETS) { 401 if (getTokens(cache_entry) == 1 || 402 getTokens(cache_entry) == (max_tokens() / 2) + 1) { 403 trigger(Event:L1_GETS_Last_Token, in_msg.addr, cache_entry); 404 } 405 else { 406 trigger(Event:L1_GETS, in_msg.addr, cache_entry); 407 } 408 } else { 409 error("Unexpected message"); 410 } 411 } 412 } 413 } 414 415 416 // Response Network 417 in_port(responseNetwork_in, ResponseMsg, responseToL2Cache) { 418 if (responseNetwork_in.isReady(clockEdge())) { 419 peek(responseNetwork_in, ResponseMsg) { 420 assert(in_msg.Destination.isElement(machineID)); 421 Entry cache_entry := getCacheEntry(in_msg.addr); 422 423 if (getTokens(cache_entry) + in_msg.Tokens != max_tokens()) { 424 if (in_msg.Type == CoherenceResponseType:ACK) { 425 assert(in_msg.Tokens < (max_tokens() / 2)); 426 trigger(Event:Ack, in_msg.addr, cache_entry); 427 } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { 428 trigger(Event:Data_Owner, in_msg.addr, cache_entry); 429 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { 430 trigger(Event:Data_Shared, in_msg.addr, cache_entry); 431 } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || 432 in_msg.Type == CoherenceResponseType:WB_OWNED || 433 in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { 434 435 if (L2cache.cacheAvail(in_msg.addr) || is_valid(cache_entry)) { 436 437 // either room is available or the block is already present 438 439 if (in_msg.Type == CoherenceResponseType:WB_TOKENS) { 440 assert(in_msg.Dirty == false); 441 trigger(Event:Writeback_Tokens, in_msg.addr, cache_entry); 442 } else if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { 443 assert(in_msg.Dirty == false); 444 trigger(Event:Writeback_Shared_Data, in_msg.addr, cache_entry); 445 } 446 else if (in_msg.Type == CoherenceResponseType:WB_OWNED) { 447 //assert(in_msg.Dirty == false); 448 trigger(Event:Writeback_Owned, in_msg.addr, cache_entry); 449 } 450 } 451 else { 452 trigger(Event:L2_Replacement, 453 L2cache.cacheProbe(in_msg.addr), 454 getCacheEntry(L2cache.cacheProbe(in_msg.addr))); 455 } 456 } else if (in_msg.Type == CoherenceResponseType:INV) { 457 trigger(Event:L1_INV, in_msg.addr, cache_entry); 458 } else { 459 error("Unexpected message"); 460 } 461 } else { 462 if (in_msg.Type == CoherenceResponseType:ACK) { 463 assert(in_msg.Tokens < (max_tokens() / 2)); 464 trigger(Event:Ack_All_Tokens, in_msg.addr, cache_entry); 465 } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || 466 in_msg.Type == CoherenceResponseType:DATA_SHARED) { 467 trigger(Event:Data_All_Tokens, in_msg.addr, cache_entry); 468 } else if (in_msg.Type == CoherenceResponseType:WB_TOKENS || 469 in_msg.Type == CoherenceResponseType:WB_OWNED || 470 in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { 471 if (L2cache.cacheAvail(in_msg.addr) || is_valid(cache_entry)) { 472 473 // either room is available or the block is already present 474 475 if (in_msg.Type == CoherenceResponseType:WB_TOKENS) { 476 assert(in_msg.Dirty == false); 477 assert( (getState(cache_entry, in_msg.addr) != State:NP) 478 && (getState(cache_entry, in_msg.addr) != State:I) ); 479 trigger(Event:Writeback_All_Tokens, in_msg.addr, cache_entry); 480 } else if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { 481 assert(in_msg.Dirty == false); 482 trigger(Event:Writeback_All_Tokens, in_msg.addr, cache_entry); 483 } 484 else if (in_msg.Type == CoherenceResponseType:WB_OWNED) { 485 trigger(Event:Writeback_All_Tokens, in_msg.addr, cache_entry); 486 } 487 } 488 else { 489 trigger(Event:L2_Replacement, 490 L2cache.cacheProbe(in_msg.addr), 491 getCacheEntry(L2cache.cacheProbe(in_msg.addr))); 492 } 493 } else if (in_msg.Type == CoherenceResponseType:INV) { 494 trigger(Event:L1_INV, in_msg.addr, cache_entry); 495 } else { 496 DPRINTF(RubySlicc, "%s\n", in_msg.Type); 497 error("Unexpected message"); 498 } 499 } 500 } 501 } 502 } 503 504 505 // ACTIONS 506 507 action(a_broadcastLocalRequest, "a", desc="broadcast local request globally") { 508 509 peek(L1requestNetwork_in, RequestMsg) { 510 511 // if this is a retry or no local sharers, broadcast normally 512 enqueue(globalRequestNetwork_out, RequestMsg, l2_request_latency) { 513 out_msg.addr := in_msg.addr; 514 out_msg.Type := in_msg.Type; 515 out_msg.Requestor := in_msg.Requestor; 516 out_msg.RetryNum := in_msg.RetryNum; 517 518 // 519 // If a statically shared L2 cache, then no other L2 caches can 520 // store the block 521 // 522 //out_msg.Destination.broadcast(MachineType:L2Cache); 523 //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); 524 //out_msg.Destination.remove(map_L1CacheMachId_to_L2Cache(address, in_msg.Requestor)); 525 526 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 527 out_msg.MessageSize := MessageSizeType:Request_Control; 528 out_msg.AccessMode := in_msg.AccessMode; 529 out_msg.Prefetch := in_msg.Prefetch; 530 } //enqueue 531 // } // if 532 533 //profile_filter_action(0); 534 } // peek 535 } //action 536 537 538 action(bb_bounceResponse, "\b", desc="Bounce tokens and data to memory") { 539 peek(responseNetwork_in, ResponseMsg) { 540 // FIXME, should use a 3rd vnet 541 enqueue(responseNetwork_out, ResponseMsg, 1) { 542 out_msg.addr := address; 543 out_msg.Type := in_msg.Type; 544 out_msg.Sender := machineID; 545 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 546 out_msg.Tokens := in_msg.Tokens; 547 out_msg.MessageSize := in_msg.MessageSize; 548 out_msg.DataBlk := in_msg.DataBlk; 549 out_msg.Dirty := in_msg.Dirty; 550 } 551 } 552 } 553 554 action(c_cleanReplacement, "c", desc="Issue clean writeback") { 555 assert(is_valid(cache_entry)); 556 if (cache_entry.Tokens > 0) { 557 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 558 out_msg.addr := address; 559 out_msg.Type := CoherenceResponseType:ACK; 560 out_msg.Sender := machineID; 561 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 562 out_msg.Tokens := cache_entry.Tokens; 563 out_msg.MessageSize := MessageSizeType:Writeback_Control; 564 } 565 cache_entry.Tokens := 0; 566 } 567 } 568 569 action(cc_dirtyReplacement, "\c", desc="Issue dirty writeback") { 570 assert(is_valid(cache_entry)); 571 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 572 out_msg.addr := address; 573 out_msg.Sender := machineID; 574 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 575 out_msg.Tokens := cache_entry.Tokens; 576 out_msg.DataBlk := cache_entry.DataBlk; 577 out_msg.Dirty := cache_entry.Dirty; 578 579 if (cache_entry.Dirty) { 580 out_msg.MessageSize := MessageSizeType:Writeback_Data; 581 out_msg.Type := CoherenceResponseType:DATA_OWNER; 582 } else { 583 out_msg.MessageSize := MessageSizeType:Writeback_Control; 584 out_msg.Type := CoherenceResponseType:ACK_OWNER; 585 } 586 } 587 cache_entry.Tokens := 0; 588 } 589 590 action(d_sendDataWithTokens, "d", desc="Send data and a token from cache to requestor") { 591 peek(requestNetwork_in, RequestMsg) { 592 assert(is_valid(cache_entry)); 593 if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { 594 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 595 out_msg.addr := address; 596 out_msg.Type := CoherenceResponseType:DATA_SHARED; 597 out_msg.Sender := machineID; 598 out_msg.Destination.add(in_msg.Requestor); 599 out_msg.Tokens := N_tokens; 600 out_msg.DataBlk := cache_entry.DataBlk; 601 out_msg.Dirty := false; 602 out_msg.MessageSize := MessageSizeType:Response_Data; 603 } 604 cache_entry.Tokens := cache_entry.Tokens - N_tokens; 605 } 606 else { 607 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 608 out_msg.addr := address; 609 out_msg.Type := CoherenceResponseType:DATA_SHARED; 610 out_msg.Sender := machineID; 611 out_msg.Destination.add(in_msg.Requestor); 612 out_msg.Tokens := 1; 613 out_msg.DataBlk := cache_entry.DataBlk; 614 out_msg.Dirty := false; 615 out_msg.MessageSize := MessageSizeType:Response_Data; 616 } 617 cache_entry.Tokens := cache_entry.Tokens - 1; 618 } 619 } 620 } 621 622 action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { 623 assert(is_valid(cache_entry)); 624 peek(requestNetwork_in, RequestMsg) { 625 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 626 out_msg.addr := address; 627 out_msg.Type := CoherenceResponseType:DATA_OWNER; 628 out_msg.Sender := machineID; 629 out_msg.Destination.add(in_msg.Requestor); 630 assert(cache_entry.Tokens >= 1); 631 out_msg.Tokens := cache_entry.Tokens; 632 out_msg.DataBlk := cache_entry.DataBlk; 633 out_msg.Dirty := cache_entry.Dirty; 634 out_msg.MessageSize := MessageSizeType:Response_Data; 635 } 636 } 637 cache_entry.Tokens := 0; 638 } 639 640 action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { 641 assert(is_valid(cache_entry)); 642 if (cache_entry.Tokens > 0) { 643 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 644 out_msg.addr := address; 645 out_msg.Type := CoherenceResponseType:ACK; 646 out_msg.Sender := machineID; 647 out_msg.Destination.add(persistentTable.findSmallest(address)); 648 assert(cache_entry.Tokens >= 1); 649 out_msg.Tokens := cache_entry.Tokens; 650 out_msg.MessageSize := MessageSizeType:Response_Control; 651 } 652 } 653 cache_entry.Tokens := 0; 654 } 655 656 action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { 657 assert(is_valid(cache_entry)); 658 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 659 out_msg.addr := address; 660 out_msg.Type := CoherenceResponseType:DATA_OWNER; 661 out_msg.Sender := machineID; 662 out_msg.Destination.add(persistentTable.findSmallest(address)); 663 assert(cache_entry.Tokens >= 1); 664 out_msg.Tokens := cache_entry.Tokens; 665 out_msg.DataBlk := cache_entry.DataBlk; 666 out_msg.Dirty := cache_entry.Dirty; 667 out_msg.MessageSize := MessageSizeType:Response_Data; 668 } 669 cache_entry.Tokens := 0; 670 } 671 672 action(f_sendAckWithAllButOneTokens, "f", desc="Send ack with all our tokens but one to starver.") { 673 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 674 assert(is_valid(cache_entry)); 675 assert(cache_entry.Tokens > 0); 676 if (cache_entry.Tokens > 1) { 677 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 678 out_msg.addr := address; 679 out_msg.Type := CoherenceResponseType:ACK; 680 out_msg.Sender := machineID; 681 out_msg.Destination.add(persistentTable.findSmallest(address)); 682 assert(cache_entry.Tokens >= 1); 683 out_msg.Tokens := cache_entry.Tokens - 1; 684 out_msg.MessageSize := MessageSizeType:Response_Control; 685 } 686 } 687 cache_entry.Tokens := 1; 688 } 689 690 action(ff_sendDataWithAllButOneTokens, "\f", desc="Send data and out tokens but one to starver") { 691 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 692 assert(is_valid(cache_entry)); 693 assert(cache_entry.Tokens > (max_tokens() / 2) + 1); 694 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 695 out_msg.addr := address; 696 out_msg.Type := CoherenceResponseType:DATA_OWNER; 697 out_msg.Sender := machineID; 698 out_msg.Destination.add(persistentTable.findSmallest(address)); 699 out_msg.Tokens := cache_entry.Tokens - 1; 700 out_msg.DataBlk := cache_entry.DataBlk; 701 out_msg.Dirty := cache_entry.Dirty; 702 out_msg.MessageSize := MessageSizeType:Response_Data; 703 } 704 cache_entry.Tokens := 1; 705 } 706 707 action(fa_sendDataWithAllTokens, "fa", desc="Send data and out tokens but one to starver") { 708 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 709 assert(is_valid(cache_entry)); 710 assert(cache_entry.Tokens == (max_tokens() / 2) + 1); 711 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 712 out_msg.addr := address; 713 out_msg.Type := CoherenceResponseType:DATA_OWNER; 714 out_msg.Sender := machineID; 715 out_msg.Destination.add(persistentTable.findSmallest(address)); 716 out_msg.Tokens := cache_entry.Tokens; 717 out_msg.DataBlk := cache_entry.DataBlk; 718 out_msg.Dirty := cache_entry.Dirty; 719 out_msg.MessageSize := MessageSizeType:Response_Data; 720 } 721 cache_entry.Tokens := 0; 722 } 723 724 725 726 action(gg_bounceResponseToStarver, "\g", desc="Redirect response to starving processor") { 727 // assert(persistentTable.isLocked(address)); 728 peek(responseNetwork_in, ResponseMsg) { 729 // FIXME, should use a 3rd vnet in some cases 730 enqueue(responseNetwork_out, ResponseMsg, 1) { 731 out_msg.addr := address; 732 out_msg.Type := in_msg.Type; 733 out_msg.Sender := machineID; 734 out_msg.Destination.add(persistentTable.findSmallest(address)); 735 out_msg.Tokens := in_msg.Tokens; 736 out_msg.DataBlk := in_msg.DataBlk; 737 out_msg.Dirty := in_msg.Dirty; 738 out_msg.MessageSize := in_msg.MessageSize; 739 } 740 } 741 } 742 743 action(gg_bounceWBSharedToStarver, "\gg", desc="Redirect response to starving processor") { 744 //assert(persistentTable.isLocked(address)); 745 peek(responseNetwork_in, ResponseMsg) { 746 // FIXME, should use a 3rd vnet in some cases 747 enqueue(responseNetwork_out, ResponseMsg, 1) { 748 out_msg.addr := address; 749 if (in_msg.Type == CoherenceResponseType:WB_SHARED_DATA) { 750 out_msg.Type := CoherenceResponseType:DATA_SHARED; 751 } else { 752 assert(in_msg.Tokens < (max_tokens() / 2)); 753 out_msg.Type := CoherenceResponseType:ACK; 754 } 755 out_msg.Sender := machineID; 756 out_msg.Destination.add(persistentTable.findSmallest(address)); 757 out_msg.Tokens := in_msg.Tokens; 758 out_msg.DataBlk := in_msg.DataBlk; 759 out_msg.Dirty := in_msg.Dirty; 760 out_msg.MessageSize := in_msg.MessageSize; 761 } 762 } 763 } 764 765 action(gg_bounceWBOwnedToStarver, "\ggg", desc="Redirect response to starving processor") { 766 // assert(persistentTable.isLocked(address)); 767 peek(responseNetwork_in, ResponseMsg) { 768 // FIXME, should use a 3rd vnet in some cases 769 enqueue(responseNetwork_out, ResponseMsg, 1) { 770 out_msg.addr := address; 771 out_msg.Type := CoherenceResponseType:DATA_OWNER; 772 out_msg.Sender := machineID; 773 out_msg.Destination.add(persistentTable.findSmallest(address)); 774 out_msg.Tokens := in_msg.Tokens; 775 out_msg.DataBlk := in_msg.DataBlk; 776 out_msg.Dirty := in_msg.Dirty; 777 out_msg.MessageSize := in_msg.MessageSize; 778 } 779 } 780 } 781 782 783 action(h_updateFilterFromL1HintOrWB, "h", desc="update filter from received writeback") { 784 peek(responseNetwork_in, ResponseMsg) { 785 removeSharer(in_msg.addr, machineIDToNodeID(in_msg.Sender)); 786 } 787 } 788 789 action(j_forwardTransientRequestToLocalSharers, "j", desc="Forward external transient request to local sharers") { 790 peek(requestNetwork_in, RequestMsg) { 791 if (filtering_enabled && in_msg.RetryNum == 0 && sharersExist(in_msg.addr) == false) { 792 //profile_filter_action(1); 793 DPRINTF(RubySlicc, "filtered message, Retry Num: %d\n", 794 in_msg.RetryNum); 795 } 796 else { 797 enqueue(localRequestNetwork_out, RequestMsg, l2_response_latency ) { 798 out_msg.addr := in_msg.addr; 799 out_msg.Requestor := in_msg.Requestor; 800 801 // 802 // Currently assuming only one chip so all L1s are local 803 // 804 //out_msg.Destination := getLocalL1IDs(machineID); 805 out_msg.Destination.broadcast(MachineType:L1Cache); 806 out_msg.Destination.remove(in_msg.Requestor); 807 808 out_msg.Type := in_msg.Type; 809 out_msg.isLocal := false; 810 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 811 out_msg.AccessMode := in_msg.AccessMode; 812 out_msg.Prefetch := in_msg.Prefetch; 813 } 814 //profile_filter_action(0); 815 } 816 } 817 } 818 819 action(k_dataFromL2CacheToL1Requestor, "k", desc="Send data and a token from cache to L1 requestor") { 820 peek(L1requestNetwork_in, RequestMsg) { 821 assert(is_valid(cache_entry)); 822 assert(cache_entry.Tokens > 0); 823 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 824 out_msg.addr := address; 825 out_msg.Type := CoherenceResponseType:DATA_SHARED; 826 out_msg.Sender := machineID; 827 out_msg.Destination.add(in_msg.Requestor); 828 out_msg.DataBlk := cache_entry.DataBlk; 829 out_msg.Dirty := false; 830 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; 831 out_msg.Tokens := 1; 832 } 833 cache_entry.Tokens := cache_entry.Tokens - 1; 834 } 835 } 836 837 action(k_dataOwnerFromL2CacheToL1Requestor, "\k", desc="Send data and a token from cache to L1 requestor") { 838 peek(L1requestNetwork_in, RequestMsg) { 839 assert(is_valid(cache_entry)); 840 assert(cache_entry.Tokens == (max_tokens() / 2) + 1); 841 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 842 out_msg.addr := address; 843 out_msg.Type := CoherenceResponseType:DATA_OWNER; 844 out_msg.Sender := machineID; 845 out_msg.Destination.add(in_msg.Requestor); 846 out_msg.DataBlk := cache_entry.DataBlk; 847 out_msg.Dirty := cache_entry.Dirty; 848 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; 849 out_msg.Tokens := cache_entry.Tokens; 850 } 851 cache_entry.Tokens := 0; 852 } 853 } 854 855 action(k_dataAndAllTokensFromL2CacheToL1Requestor, "\kk", desc="Send data and a token from cache to L1 requestor") { 856 peek(L1requestNetwork_in, RequestMsg) { 857 assert(is_valid(cache_entry)); 858// assert(cache_entry.Tokens == max_tokens()); 859 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 860 out_msg.addr := address; 861 out_msg.Type := CoherenceResponseType:DATA_OWNER; 862 out_msg.Sender := machineID; 863 out_msg.Destination.add(in_msg.Requestor); 864 out_msg.DataBlk := cache_entry.DataBlk; 865 out_msg.Dirty := cache_entry.Dirty; 866 out_msg.MessageSize := MessageSizeType:ResponseL2hit_Data; 867 //out_msg.Tokens := max_tokens(); 868 out_msg.Tokens := cache_entry.Tokens; 869 } 870 cache_entry.Tokens := 0; 871 } 872 } 873 874 action(l_popPersistentQueue, "l", desc="Pop persistent queue.") { 875 persistentNetwork_in.dequeue(clockEdge()); 876 } 877 878 action(m_popRequestQueue, "m", desc="Pop request queue.") { 879 requestNetwork_in.dequeue(clockEdge()); 880 } 881 882 action(n_popResponseQueue, "n", desc="Pop response queue") { 883 responseNetwork_in.dequeue(clockEdge()); 884 } 885 886 action(o_popL1RequestQueue, "o", desc="Pop L1 request queue.") { 887 L1requestNetwork_in.dequeue(clockEdge()); 888 } 889 890 891 action(q_updateTokensFromResponse, "q", desc="Update the token count based on the incoming response message") { 892 peek(responseNetwork_in, ResponseMsg) { 893 assert(is_valid(cache_entry)); 894 assert(in_msg.Tokens != 0); 895 cache_entry.Tokens := cache_entry.Tokens + in_msg.Tokens; 896 897 // this should ideally be in u_writeDataToCache, but Writeback_All_Tokens 898 // may not trigger this action. 899 if ( (in_msg.Type == CoherenceResponseType:DATA_OWNER || in_msg.Type == CoherenceResponseType:WB_OWNED) && in_msg.Dirty) { 900 cache_entry.Dirty := true; 901 } 902 } 903 } 904 905 action(r_markNewSharer, "r", desc="Mark the new local sharer from local request message") { 906 peek(L1requestNetwork_in, RequestMsg) { 907 if (machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache) { 908 if (in_msg.Type == CoherenceRequestType:GETX) { 909 setNewWriter(in_msg.addr, machineIDToNodeID(in_msg.Requestor)); 910 } else if (in_msg.Type == CoherenceRequestType:GETS) { 911 addNewSharer(in_msg.addr, machineIDToNodeID(in_msg.Requestor)); 912 } 913 } 914 } 915 } 916 917 action(r_clearExclusive, "\rrr", desc="clear exclusive bit") { 918 clearExclusiveBitIfExists(address); 919 } 920 921 action(r_setMRU, "\rr", desc="manually set the MRU bit for cache line" ) { 922 peek(L1requestNetwork_in, RequestMsg) { 923 if ((machineIDToMachineType(in_msg.Requestor) == MachineType:L1Cache) && 924 (is_valid(cache_entry))) { 925 L2cache.setMRU(address); 926 } 927 } 928 } 929 930 action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { 931 assert(is_valid(cache_entry)); 932 if (cache_entry.Tokens > 0) { 933 peek(requestNetwork_in, RequestMsg) { 934 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 935 out_msg.addr := address; 936 out_msg.Type := CoherenceResponseType:ACK; 937 out_msg.Sender := machineID; 938 out_msg.Destination.add(in_msg.Requestor); 939 assert(cache_entry.Tokens >= 1); 940 out_msg.Tokens := cache_entry.Tokens; 941 out_msg.MessageSize := MessageSizeType:Response_Control; 942 } 943 } 944 } 945 cache_entry.Tokens := 0; 946 } 947 948 action(tt_sendLocalAckWithCollectedTokens, "tt", desc="Send ack with the tokens we've collected thus far.") { 949 assert(is_valid(cache_entry)); 950 if (cache_entry.Tokens > 0) { 951 peek(L1requestNetwork_in, RequestMsg) { 952 enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) { 953 out_msg.addr := address; 954 out_msg.Type := CoherenceResponseType:ACK; 955 out_msg.Sender := machineID; 956 out_msg.Destination.add(in_msg.Requestor); 957 assert(cache_entry.Tokens >= 1); 958 out_msg.Tokens := cache_entry.Tokens; 959 out_msg.MessageSize := MessageSizeType:Response_Control; 960 } 961 } 962 } 963 cache_entry.Tokens := 0; 964 } 965 966 action(u_writeDataToCache, "u", desc="Write data to cache") { 967 peek(responseNetwork_in, ResponseMsg) { 968 assert(is_valid(cache_entry)); 969 cache_entry.DataBlk := in_msg.DataBlk; 970 if ((cache_entry.Dirty == false) && in_msg.Dirty) { 971 cache_entry.Dirty := in_msg.Dirty; 972 } 973 } 974 } 975 976 action(vv_allocateL2CacheBlock, "\v", desc="Set L2 cache tag equal to tag of block B.") { 977 set_cache_entry(L2cache.allocate(address, new Entry)); 978 } 979 980 action(rr_deallocateL2CacheBlock, "\r", desc="Deallocate L2 cache block. Sets the cache to not present, allowing a replacement in parallel with a fetch.") { 981 L2cache.deallocate(address); 982 unset_cache_entry(); 983 } 984 985 action(uu_profileMiss, "\um", desc="Profile the demand miss") { 986 ++L2cache.demand_misses; 987 } 988 989 action(uu_profileHit, "\uh", desc="Profile the demand hit") { 990 ++L2cache.demand_hits; 991 } 992 993 action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") { 994 peek(responseNetwork_in, ResponseMsg) { 995 if (in_msg.Type != CoherenceResponseType:ACK && 996 in_msg.Type != CoherenceResponseType:WB_TOKENS) { 997 assert(is_valid(cache_entry)); 998 assert(cache_entry.DataBlk == in_msg.DataBlk); 999 } 1000 } 1001 } 1002 1003 1004 //***************************************************** 1005 // TRANSITIONS 1006 //***************************************************** 1007 1008 transition({NP, I, S, O, M, I_L, S_L}, L1_INV) { 1009 1010 h_updateFilterFromL1HintOrWB; 1011 n_popResponseQueue; 1012 } 1013 1014 transition({NP, I, S, O, M}, Own_Lock_or_Unlock) { 1015 l_popPersistentQueue; 1016 } 1017 1018 1019 // Transitions from NP 1020 1021 transition(NP, {Transient_GETX, Transient_GETS}) { 1022 // forward message to local sharers 1023 r_clearExclusive; 1024 j_forwardTransientRequestToLocalSharers; 1025 m_popRequestQueue; 1026 } 1027 1028 1029 transition(NP, {L1_GETS, L1_GETX}) { 1030 a_broadcastLocalRequest; 1031 r_markNewSharer; 1032 uu_profileMiss; 1033 o_popL1RequestQueue; 1034 } 1035 1036 transition(NP, {Ack, Data_Shared, Data_Owner, Data_All_Tokens}) { 1037 bb_bounceResponse; 1038 n_popResponseQueue; 1039 } 1040 1041 transition(NP, Writeback_Shared_Data, S) { 1042 vv_allocateL2CacheBlock; 1043 u_writeDataToCache; 1044 q_updateTokensFromResponse; 1045 h_updateFilterFromL1HintOrWB; 1046 n_popResponseQueue; 1047 } 1048 1049 transition(NP, Writeback_Tokens, I) { 1050 vv_allocateL2CacheBlock; 1051 q_updateTokensFromResponse; 1052 h_updateFilterFromL1HintOrWB; 1053 n_popResponseQueue; 1054 } 1055 1056 transition(NP, Writeback_All_Tokens, M) { 1057 vv_allocateL2CacheBlock; 1058 u_writeDataToCache; 1059 q_updateTokensFromResponse; 1060 h_updateFilterFromL1HintOrWB; 1061 n_popResponseQueue; 1062 } 1063 1064 transition(NP, Writeback_Owned, O) { 1065 vv_allocateL2CacheBlock; 1066 u_writeDataToCache; 1067 q_updateTokensFromResponse; 1068 h_updateFilterFromL1HintOrWB; 1069 n_popResponseQueue; 1070 } 1071 1072 1073 transition(NP, 1074 {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, 1075 I_L) { 1076 l_popPersistentQueue; 1077 } 1078 1079 // Transitions from Idle 1080 1081 transition(I, {L1_GETS, L1_GETS_Last_Token}) { 1082 a_broadcastLocalRequest; 1083 tt_sendLocalAckWithCollectedTokens; // send any tokens we have collected 1084 r_markNewSharer; 1085 uu_profileMiss; 1086 o_popL1RequestQueue; 1087 } 1088 1089 transition(I, L1_GETX) { 1090 a_broadcastLocalRequest; 1091 tt_sendLocalAckWithCollectedTokens; // send any tokens we have collected 1092 r_markNewSharer; 1093 uu_profileMiss; 1094 o_popL1RequestQueue; 1095 } 1096 1097 transition(I, L2_Replacement) { 1098 c_cleanReplacement; // Only needed in some cases 1099 rr_deallocateL2CacheBlock; 1100 } 1101 1102 transition(I, {Transient_GETX, Transient_GETS, Transient_GETS_Last_Token}) { 1103 r_clearExclusive; 1104 t_sendAckWithCollectedTokens; 1105 j_forwardTransientRequestToLocalSharers; 1106 m_popRequestQueue; 1107 } 1108 1109 transition(I, 1110 {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, 1111 I_L) { 1112 e_sendAckWithCollectedTokens; 1113 l_popPersistentQueue; 1114 } 1115 1116 1117 transition(I, Ack) { 1118 q_updateTokensFromResponse; 1119 n_popResponseQueue; 1120 } 1121 1122 transition(I, Data_Shared, S) { 1123 u_writeDataToCache; 1124 q_updateTokensFromResponse; 1125 n_popResponseQueue; 1126 } 1127 1128 transition(I, Writeback_Shared_Data, S) { 1129 u_writeDataToCache; 1130 q_updateTokensFromResponse; 1131 h_updateFilterFromL1HintOrWB; 1132 n_popResponseQueue; 1133 } 1134 1135 transition(I, Writeback_Tokens) { 1136 q_updateTokensFromResponse; 1137 h_updateFilterFromL1HintOrWB; 1138 n_popResponseQueue; 1139 } 1140 1141 transition(I, Data_Owner, O) { 1142 u_writeDataToCache; 1143 q_updateTokensFromResponse; 1144 n_popResponseQueue; 1145 } 1146 1147 transition(I, Writeback_Owned, O) { 1148 u_writeDataToCache; 1149 q_updateTokensFromResponse; 1150 h_updateFilterFromL1HintOrWB; 1151 n_popResponseQueue; 1152 } 1153 1154 transition(I, Data_All_Tokens, M) { 1155 u_writeDataToCache; 1156 q_updateTokensFromResponse; 1157 n_popResponseQueue; 1158 } 1159 1160 1161 transition(I, Writeback_All_Tokens, M) { 1162 u_writeDataToCache; 1163 q_updateTokensFromResponse; 1164 h_updateFilterFromL1HintOrWB; 1165 n_popResponseQueue; 1166 } 1167 1168 // Transitions from Shared 1169 1170 transition(S, L2_Replacement, I) { 1171 c_cleanReplacement; 1172 rr_deallocateL2CacheBlock; 1173 } 1174 1175 transition(S, Transient_GETX, I) { 1176 r_clearExclusive; 1177 t_sendAckWithCollectedTokens; 1178 j_forwardTransientRequestToLocalSharers; 1179 m_popRequestQueue; 1180 } 1181 1182 transition(S, {Transient_GETS, Transient_GETS_Last_Token}) { 1183 j_forwardTransientRequestToLocalSharers; 1184 r_clearExclusive; 1185 m_popRequestQueue; 1186 } 1187 1188 transition(S, Persistent_GETX, I_L) { 1189 e_sendAckWithCollectedTokens; 1190 l_popPersistentQueue; 1191 } 1192 1193 1194 transition(S, {Persistent_GETS, Persistent_GETS_Last_Token}, S_L) { 1195 f_sendAckWithAllButOneTokens; 1196 l_popPersistentQueue; 1197 } 1198 1199 1200 transition(S, Ack) { 1201 q_updateTokensFromResponse; 1202 n_popResponseQueue; 1203 } 1204 1205 transition(S, Data_Shared) { 1206 w_assertIncomingDataAndCacheDataMatch; 1207 q_updateTokensFromResponse; 1208 n_popResponseQueue; 1209 } 1210 1211 transition(S, Writeback_Tokens) { 1212 q_updateTokensFromResponse; 1213 h_updateFilterFromL1HintOrWB; 1214 n_popResponseQueue; 1215 } 1216 1217 transition(S, Writeback_Shared_Data) { 1218 w_assertIncomingDataAndCacheDataMatch; 1219 q_updateTokensFromResponse; 1220 h_updateFilterFromL1HintOrWB; 1221 n_popResponseQueue; 1222 } 1223 1224 1225 transition(S, Data_Owner, O) { 1226 w_assertIncomingDataAndCacheDataMatch; 1227 q_updateTokensFromResponse; 1228 n_popResponseQueue; 1229 } 1230 1231 transition(S, Writeback_Owned, O) { 1232 w_assertIncomingDataAndCacheDataMatch; 1233 q_updateTokensFromResponse; 1234 h_updateFilterFromL1HintOrWB; 1235 n_popResponseQueue; 1236 } 1237 1238 transition(S, Data_All_Tokens, M) { 1239 w_assertIncomingDataAndCacheDataMatch; 1240 q_updateTokensFromResponse; 1241 n_popResponseQueue; 1242 } 1243 1244 transition(S, Writeback_All_Tokens, M) { 1245 w_assertIncomingDataAndCacheDataMatch; 1246 q_updateTokensFromResponse; 1247 h_updateFilterFromL1HintOrWB; 1248 n_popResponseQueue; 1249 } 1250 1251 transition(S, L1_GETX, I) { 1252 a_broadcastLocalRequest; 1253 tt_sendLocalAckWithCollectedTokens; 1254 r_markNewSharer; 1255 r_setMRU; 1256 uu_profileMiss; 1257 o_popL1RequestQueue; 1258 } 1259 1260 1261 transition(S, L1_GETS) { 1262 k_dataFromL2CacheToL1Requestor; 1263 r_markNewSharer; 1264 r_setMRU; 1265 uu_profileHit; 1266 o_popL1RequestQueue; 1267 } 1268 1269 transition(S, L1_GETS_Last_Token, I) { 1270 1271 k_dataFromL2CacheToL1Requestor; 1272 r_markNewSharer; 1273 r_setMRU; 1274 uu_profileHit; 1275 o_popL1RequestQueue; 1276 } 1277 1278 // Transitions from Owned 1279 1280 transition(O, L2_Replacement, I) { 1281 cc_dirtyReplacement; 1282 rr_deallocateL2CacheBlock; 1283 } 1284 1285 transition(O, Transient_GETX, I) { 1286 r_clearExclusive; 1287 dd_sendDataWithAllTokens; 1288 j_forwardTransientRequestToLocalSharers; 1289 m_popRequestQueue; 1290 } 1291 1292 transition(O, Persistent_GETX, I_L) { 1293 ee_sendDataWithAllTokens; 1294 l_popPersistentQueue; 1295 } 1296 1297 transition(O, Persistent_GETS, S_L) { 1298 ff_sendDataWithAllButOneTokens; 1299 l_popPersistentQueue; 1300 } 1301 1302 transition(O, Persistent_GETS_Last_Token, I_L) { 1303 fa_sendDataWithAllTokens; 1304 l_popPersistentQueue; 1305 } 1306 1307 transition(O, Transient_GETS) { 1308 // send multiple tokens 1309 r_clearExclusive; 1310 d_sendDataWithTokens; 1311 m_popRequestQueue; 1312 } 1313 1314 transition(O, Transient_GETS_Last_Token) { 1315 // WAIT FOR IT TO GO PERSISTENT 1316 r_clearExclusive; 1317 m_popRequestQueue; 1318 } 1319 1320 transition(O, Ack) { 1321 q_updateTokensFromResponse; 1322 n_popResponseQueue; 1323 } 1324 1325 transition(O, Ack_All_Tokens, M) { 1326 q_updateTokensFromResponse; 1327 n_popResponseQueue; 1328 } 1329 1330 transition(O, Data_Shared) { 1331 w_assertIncomingDataAndCacheDataMatch; 1332 q_updateTokensFromResponse; 1333 n_popResponseQueue; 1334 } 1335 1336 1337 transition(O, {Writeback_Tokens, Writeback_Shared_Data}) { 1338 w_assertIncomingDataAndCacheDataMatch; 1339 q_updateTokensFromResponse; 1340 h_updateFilterFromL1HintOrWB; 1341 n_popResponseQueue; 1342 } 1343 1344 transition(O, Data_All_Tokens, M) { 1345 w_assertIncomingDataAndCacheDataMatch; 1346 q_updateTokensFromResponse; 1347 n_popResponseQueue; 1348 } 1349 1350 transition(O, Writeback_All_Tokens, M) { 1351 w_assertIncomingDataAndCacheDataMatch; 1352 q_updateTokensFromResponse; 1353 h_updateFilterFromL1HintOrWB; 1354 n_popResponseQueue; 1355 } 1356 1357 transition(O, L1_GETS) { 1358 k_dataFromL2CacheToL1Requestor; 1359 r_markNewSharer; 1360 r_setMRU; 1361 uu_profileHit; 1362 o_popL1RequestQueue; 1363 } 1364 1365 transition(O, L1_GETS_Last_Token, I) { 1366 k_dataOwnerFromL2CacheToL1Requestor; 1367 r_markNewSharer; 1368 r_setMRU; 1369 uu_profileHit; 1370 o_popL1RequestQueue; 1371 } 1372 1373 transition(O, L1_GETX, I) { 1374 a_broadcastLocalRequest; 1375 k_dataAndAllTokensFromL2CacheToL1Requestor; 1376 r_markNewSharer; 1377 r_setMRU; 1378 uu_profileMiss; 1379 o_popL1RequestQueue; 1380 } 1381 1382 // Transitions from M 1383 1384 transition(M, L2_Replacement, I) { 1385 cc_dirtyReplacement; 1386 rr_deallocateL2CacheBlock; 1387 } 1388 1389 // MRM_DEBUG: Give up all tokens even for GETS? ??? 1390 transition(M, {Transient_GETX, Transient_GETS}, I) { 1391 r_clearExclusive; 1392 dd_sendDataWithAllTokens; 1393 m_popRequestQueue; 1394 } 1395 1396 transition(M, {Persistent_GETS, Persistent_GETX}, I_L) { 1397 ee_sendDataWithAllTokens; 1398 l_popPersistentQueue; 1399 } 1400 1401 1402 transition(M, L1_GETS, O) { 1403 k_dataFromL2CacheToL1Requestor; 1404 r_markNewSharer; 1405 r_setMRU; 1406 uu_profileHit; 1407 o_popL1RequestQueue; 1408 } 1409 1410 transition(M, L1_GETX, I) { 1411 k_dataAndAllTokensFromL2CacheToL1Requestor; 1412 r_markNewSharer; 1413 r_setMRU; 1414 uu_profileHit; 1415 o_popL1RequestQueue; 1416 } 1417 1418 1419 //Transitions from locked states 1420 1421 transition({I_L, S_L}, Ack) { 1422 gg_bounceResponseToStarver; 1423 n_popResponseQueue; 1424 } 1425 1426 transition({I_L, S_L}, {Data_Shared, Data_Owner, Data_All_Tokens}) { 1427 gg_bounceResponseToStarver; 1428 n_popResponseQueue; 1429 } 1430 1431 transition({I_L, S_L}, {Writeback_Tokens, Writeback_Shared_Data}) { 1432 gg_bounceWBSharedToStarver; 1433 h_updateFilterFromL1HintOrWB; 1434 n_popResponseQueue; 1435 } 1436 1437 transition({I_L, S_L}, {Writeback_Owned, Writeback_All_Tokens}) { 1438 gg_bounceWBOwnedToStarver; 1439 h_updateFilterFromL1HintOrWB; 1440 n_popResponseQueue; 1441 } 1442 1443 transition(S_L, L2_Replacement, I) { 1444 c_cleanReplacement; 1445 rr_deallocateL2CacheBlock; 1446 } 1447 1448 transition(I_L, L2_Replacement, I) { 1449 rr_deallocateL2CacheBlock; 1450 } 1451 1452 transition(I_L, Own_Lock_or_Unlock, I) { 1453 l_popPersistentQueue; 1454 } 1455 1456 transition(S_L, Own_Lock_or_Unlock, S) { 1457 l_popPersistentQueue; 1458 } 1459 1460 transition({I_L, S_L}, {Transient_GETS_Last_Token, Transient_GETS, Transient_GETX}) { 1461 r_clearExclusive; 1462 m_popRequestQueue; 1463 } 1464 1465 transition(I_L, {L1_GETX, L1_GETS}) { 1466 a_broadcastLocalRequest; 1467 r_markNewSharer; 1468 uu_profileMiss; 1469 o_popL1RequestQueue; 1470 } 1471 1472 transition(S_L, L1_GETX, I_L) { 1473 a_broadcastLocalRequest; 1474 tt_sendLocalAckWithCollectedTokens; 1475 r_markNewSharer; 1476 r_setMRU; 1477 uu_profileMiss; 1478 o_popL1RequestQueue; 1479 } 1480 1481 transition(S_L, L1_GETS) { 1482 k_dataFromL2CacheToL1Requestor; 1483 r_markNewSharer; 1484 r_setMRU; 1485 uu_profileHit; 1486 o_popL1RequestQueue; 1487 } 1488 1489 transition(S_L, L1_GETS_Last_Token, I_L) { 1490 k_dataFromL2CacheToL1Requestor; 1491 r_markNewSharer; 1492 r_setMRU; 1493 uu_profileHit; 1494 o_popL1RequestQueue; 1495 } 1496 1497 transition(S_L, Persistent_GETX, I_L) { 1498 e_sendAckWithCollectedTokens; 1499 l_popPersistentQueue; 1500 } 1501 1502 transition(S_L, {Persistent_GETS, Persistent_GETS_Last_Token}) { 1503 l_popPersistentQueue; 1504 } 1505 1506 transition(I_L, {Persistent_GETX, Persistent_GETS}) { 1507 l_popPersistentQueue; 1508 } 1509} 1510