MOESI_CMP_token-L1cache.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 29/* 30 * $Id: MOESI_CMP_token-L1cache.sm 1.22 05/01/19 15:55:39-06:00 beckmann@s0-28.cs.wisc.edu $ 31 * 32 */ 33 34machine(MachineType:L1Cache, "Token protocol") 35 : Sequencer * sequencer; 36 CacheMemory * L1Icache; 37 CacheMemory * L1Dcache; 38 int l2_select_num_bits; 39 int N_tokens; 40 41 Cycles l1_request_latency := 2; 42 Cycles l1_response_latency := 2; 43 int retry_threshold := 1; 44 Cycles fixed_timeout_latency := 100; 45 Cycles reissue_wakeup_latency := 10; 46 Cycles use_timeout_latency := 50; 47 48 bool dynamic_timeout_enabled := "True"; 49 bool no_mig_atomic := "True"; 50 bool send_evictions; 51 52 // Message Queues 53 // From this node's L1 cache TO the network 54 55 // a local L1 -> this L2 bank 56 MessageBuffer * responseFromL1Cache, network="To", virtual_network="4", 57 vnet_type="response"; 58 MessageBuffer * persistentFromL1Cache, network="To", virtual_network="3", 59 vnet_type="persistent"; 60 // a local L1 -> this L2 bank, currently ordered with directory forwarded requests 61 MessageBuffer * requestFromL1Cache, network="To", virtual_network="1", 62 vnet_type="request"; 63 64 // To this node's L1 cache FROM the network 65 66 // a L2 bank -> this L1 67 MessageBuffer * responseToL1Cache, network="From", virtual_network="4", 68 vnet_type="response"; 69 MessageBuffer * persistentToL1Cache, network="From", virtual_network="3", 70 vnet_type="persistent"; 71 // a L2 bank -> this L1 72 MessageBuffer * requestToL1Cache, network="From", virtual_network="1", 73 vnet_type="request"; 74 75 MessageBuffer * mandatoryQueue; 76{ 77 // STATES 78 state_declaration(State, desc="Cache states", default="L1Cache_State_I") { 79 // Base states 80 NP, AccessPermission:Invalid, "NP", desc="Not Present"; 81 I, AccessPermission:Invalid, "I", desc="Idle"; 82 S, AccessPermission:Read_Only, "S", desc="Shared"; 83 O, AccessPermission:Read_Only, "O", desc="Owned"; 84 M, AccessPermission:Read_Only, "M", desc="Modified (dirty)"; 85 MM, AccessPermission:Read_Write, "MM", desc="Modified (dirty and locally modified)"; 86 M_W, AccessPermission:Read_Only, "M^W", desc="Modified (dirty), waiting"; 87 MM_W, AccessPermission:Read_Write, "MM^W", desc="Modified (dirty and locally modified), waiting"; 88 89 // Transient States 90 IM, AccessPermission:Busy, "IM", desc="Issued GetX"; 91 SM, AccessPermission:Read_Only, "SM", desc="Issued GetX, we still have an old copy of the line"; 92 OM, AccessPermission:Read_Only, "OM", desc="Issued GetX, received data"; 93 IS, AccessPermission:Busy, "IS", desc="Issued GetS"; 94 95 // Locked states 96 I_L, AccessPermission:Busy, "I^L", desc="Invalid, Locked"; 97 S_L, AccessPermission:Busy, "S^L", desc="Shared, Locked"; 98 IM_L, AccessPermission:Busy, "IM^L", desc="Invalid, Locked, trying to go to Modified"; 99 SM_L, AccessPermission:Busy, "SM^L", desc="Shared, Locked, trying to go to Modified"; 100 IS_L, AccessPermission:Busy, "IS^L", desc="Invalid, Locked, trying to go to Shared"; 101 } 102 103 // EVENTS 104 enumeration(Event, desc="Cache events") { 105 Load, desc="Load request from the processor"; 106 Ifetch, desc="I-fetch request from the processor"; 107 Store, desc="Store request from the processor"; 108 Atomic, desc="Atomic request from the processor"; 109 L1_Replacement, desc="L1 Replacement"; 110 111 // Responses 112 Data_Shared, desc="Received a data message, we are now a sharer"; 113 Data_Owner, desc="Received a data message, we are now the owner"; 114 Data_All_Tokens, desc="Received a data message, we are now the owner, we now have all the tokens"; 115 Ack, desc="Received an ack message"; 116 Ack_All_Tokens, desc="Received an ack message, we now have all the tokens"; 117 118 // Requests 119 Transient_GETX, desc="A GetX from another processor"; 120 Transient_Local_GETX, desc="A GetX from another processor"; 121 Transient_GETS, desc="A GetS from another processor"; 122 Transient_Local_GETS, desc="A GetS from another processor"; 123 Transient_GETS_Last_Token, desc="A GetS from another processor"; 124 Transient_Local_GETS_Last_Token, desc="A GetS from another processor"; 125 126 // Lock/Unlock for distributed 127 Persistent_GETX, desc="Another processor has priority to read/write"; 128 Persistent_GETS, desc="Another processor has priority to read"; 129 Persistent_GETS_Last_Token, desc="Another processor has priority to read, no more tokens"; 130 Own_Lock_or_Unlock, desc="This processor now has priority"; 131 132 // Triggers 133 Request_Timeout, desc="Timeout"; 134 Use_TimeoutStarverX, desc="Timeout"; 135 Use_TimeoutStarverS, desc="Timeout"; 136 Use_TimeoutNoStarvers, desc="Timeout"; 137 Use_TimeoutNoStarvers_NoMig, desc="Timeout Don't Migrate"; 138 } 139 140 // TYPES 141 142 // CacheEntry 143 structure(Entry, desc="...", interface="AbstractCacheEntry") { 144 State CacheState, desc="cache state"; 145 bool Dirty, desc="Is the data dirty (different than memory)?"; 146 int Tokens, desc="The number of tokens we're holding for the line"; 147 DataBlock DataBlk, desc="data for the block"; 148 } 149 150 151 // TBE fields 152 structure(TBE, desc="...") { 153 Addr addr, desc="Physical address for this TBE"; 154 State TBEState, desc="Transient state"; 155 int IssueCount, default="0", desc="The number of times we've issued a request for this line."; 156 Addr PC, desc="Program counter of request"; 157 158 bool WentPersistent, default="false", desc="Request went persistent"; 159 bool ExternalResponse, default="false", desc="Response came from an external controller"; 160 bool IsAtomic, default="false", desc="Request was an atomic request"; 161 162 AccessType TypeOfAccess, desc="Type of request (used for profiling)"; 163 Cycles IssueTime, desc="Time the request was issued"; 164 RubyAccessMode AccessMode, desc="user/supervisor access type"; 165 PrefetchBit Prefetch, desc="Is this a prefetch request"; 166 } 167 168 structure(TBETable, external="yes") { 169 TBE lookup(Addr); 170 void allocate(Addr); 171 void deallocate(Addr); 172 bool isPresent(Addr); 173 } 174 175 structure(PersistentTable, external="yes") { 176 void persistentRequestLock(Addr, MachineID, AccessType); 177 void persistentRequestUnlock(Addr, MachineID); 178 bool okToIssueStarving(Addr, MachineID); 179 MachineID findSmallest(Addr); 180 AccessType typeOfSmallest(Addr); 181 void markEntries(Addr); 182 bool isLocked(Addr); 183 int countStarvingForAddress(Addr); 184 int countReadStarvingForAddress(Addr); 185 } 186 187 Tick clockEdge(); 188 Tick cyclesToTicks(Cycles c); 189 void set_cache_entry(AbstractCacheEntry b); 190 void unset_cache_entry(); 191 void set_tbe(TBE b); 192 void unset_tbe(); 193 void wakeUpAllBuffers(); 194 void wakeUpBuffers(Addr a); 195 Cycles curCycle(); 196 MachineID mapAddressToMachine(Addr addr, MachineType mtype); 197 198 TBETable L1_TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs"; 199 200 bool starving, default="false"; 201 int l2_select_low_bit, default="RubySystem::getBlockSizeBits()"; 202 203 PersistentTable persistentTable; 204 TimerTable useTimerTable; 205 TimerTable reissueTimerTable; 206 207 int outstandingRequests, default="0"; 208 int outstandingPersistentRequests, default="0"; 209 210 // Constant that provides hysteresis for calculated the estimated average 211 int averageLatencyHysteresis, default="(8)"; 212 Cycles averageLatencyCounter, 213 default="(Cycles(500) << (*m_averageLatencyHysteresis_ptr))"; 214 215 Cycles averageLatencyEstimate() { 216 DPRINTF(RubySlicc, "%d\n", 217 (averageLatencyCounter >> averageLatencyHysteresis)); 218 return averageLatencyCounter >> averageLatencyHysteresis; 219 } 220 221 void updateAverageLatencyEstimate(Cycles latency) { 222 DPRINTF(RubySlicc, "%d\n", latency); 223 224 // By subtracting the current average and then adding the most 225 // recent sample, we calculate an estimate of the recent average. 226 // If we simply used a running sum and divided by the total number 227 // of entries, the estimate of the average would adapt very slowly 228 // after the execution has run for a long time. 229 // averageLatencyCounter := averageLatencyCounter - averageLatencyEstimate() + latency; 230 231 averageLatencyCounter := averageLatencyCounter - averageLatencyEstimate() + latency; 232 } 233 234 Entry getCacheEntry(Addr addr), return_by_pointer="yes" { 235 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache.lookup(addr)); 236 if(is_valid(L1Dcache_entry)) { 237 return L1Dcache_entry; 238 } 239 240 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache.lookup(addr)); 241 return L1Icache_entry; 242 } 243 244 void functionalRead(Addr addr, Packet *pkt) { 245 testAndRead(addr, getCacheEntry(addr).DataBlk, pkt); 246 } 247 248 int functionalWrite(Addr addr, Packet *pkt) { 249 int num_functional_writes := 0; 250 num_functional_writes := num_functional_writes + 251 testAndWrite(addr, getCacheEntry(addr).DataBlk, pkt); 252 return num_functional_writes; 253 } 254 255 Entry getL1DCacheEntry(Addr addr), return_by_pointer="yes" { 256 Entry L1Dcache_entry := static_cast(Entry, "pointer", L1Dcache.lookup(addr)); 257 return L1Dcache_entry; 258 } 259 260 Entry getL1ICacheEntry(Addr addr), return_by_pointer="yes" { 261 Entry L1Icache_entry := static_cast(Entry, "pointer", L1Icache.lookup(addr)); 262 return L1Icache_entry; 263 } 264 265 int getTokens(Entry cache_entry) { 266 if (is_valid(cache_entry)) { 267 return cache_entry.Tokens; 268 } 269 return 0; 270 } 271 272 State getState(TBE tbe, Entry cache_entry, Addr addr) { 273 274 if (is_valid(tbe)) { 275 return tbe.TBEState; 276 } else if (is_valid(cache_entry)) { 277 return cache_entry.CacheState; 278 } else { 279 if (persistentTable.isLocked(addr) && (persistentTable.findSmallest(addr) != machineID)) { 280 // Not in cache, in persistent table, but this processor isn't highest priority 281 return State:I_L; 282 } else { 283 return State:NP; 284 } 285 } 286 } 287 288 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) { 289 assert((L1Dcache.isTagPresent(addr) && L1Icache.isTagPresent(addr)) == false); 290 291 if (is_valid(tbe)) { 292 assert(state != State:I); 293 assert(state != State:S); 294 assert(state != State:O); 295 assert(state != State:MM); 296 assert(state != State:M); 297 tbe.TBEState := state; 298 } 299 300 if (is_valid(cache_entry)) { 301 // Make sure the token count is in range 302 assert(cache_entry.Tokens >= 0); 303 assert(cache_entry.Tokens <= max_tokens()); 304 assert(cache_entry.Tokens != (max_tokens() / 2)); 305 306 if ((state == State:I_L) || 307 (state == State:IM_L) || 308 (state == State:IS_L)) { 309 // Make sure we have no tokens in the "Invalid, locked" states 310 assert(cache_entry.Tokens == 0); 311 312 // Make sure the line is locked 313 // assert(persistentTable.isLocked(addr)); 314 315 // But we shouldn't have highest priority for it 316 // assert(persistentTable.findSmallest(addr) != id); 317 318 } else if ((state == State:S_L) || 319 (state == State:SM_L)) { 320 assert(cache_entry.Tokens >= 1); 321 assert(cache_entry.Tokens < (max_tokens() / 2)); 322 323 // Make sure the line is locked... 324 // assert(persistentTable.isLocked(addr)); 325 326 // ...But we shouldn't have highest priority for it... 327 // assert(persistentTable.findSmallest(addr) != id); 328 329 // ...And it must be a GETS request 330 // assert(persistentTable.typeOfSmallest(addr) == AccessType:Read); 331 332 } else { 333 334 // If there is an entry in the persistent table of this block, 335 // this processor needs to have an entry in the table for this 336 // block, and that entry better be the smallest (highest 337 // priority). Otherwise, the state should have been one of 338 // locked states 339 340 //if (persistentTable.isLocked(addr)) { 341 // assert(persistentTable.findSmallest(addr) == id); 342 //} 343 } 344 345 // in M and E you have all the tokens 346 if (state == State:MM || state == State:M || state == State:MM_W || state == State:M_W) { 347 assert(cache_entry.Tokens == max_tokens()); 348 } 349 350 // in NP you have no tokens 351 if (state == State:NP) { 352 assert(cache_entry.Tokens == 0); 353 } 354 355 // You have at least one token in S-like states 356 if (state == State:S || state == State:SM) { 357 assert(cache_entry.Tokens > 0); 358 } 359 360 // You have at least half the token in O-like states 361 if (state == State:O && state == State:OM) { 362 assert(cache_entry.Tokens > (max_tokens() / 2)); 363 } 364 365 cache_entry.CacheState := state; 366 } 367 } 368 369 AccessPermission getAccessPermission(Addr addr) { 370 TBE tbe := L1_TBEs[addr]; 371 if(is_valid(tbe)) { 372 return L1Cache_State_to_permission(tbe.TBEState); 373 } 374 375 Entry cache_entry := getCacheEntry(addr); 376 if(is_valid(cache_entry)) { 377 return L1Cache_State_to_permission(cache_entry.CacheState); 378 } 379 380 return AccessPermission:NotPresent; 381 } 382 383 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 384 if (is_valid(cache_entry)) { 385 cache_entry.changePermission(L1Cache_State_to_permission(state)); 386 } 387 } 388 389 Event mandatory_request_type_to_event(RubyRequestType type) { 390 if (type == RubyRequestType:LD) { 391 return Event:Load; 392 } else if (type == RubyRequestType:IFETCH) { 393 return Event:Ifetch; 394 } else if (type == RubyRequestType:ST) { 395 return Event:Store; 396 } else if (type == RubyRequestType:ATOMIC) { 397 if (no_mig_atomic) { 398 return Event:Atomic; 399 } else { 400 return Event:Store; 401 } 402 } else { 403 error("Invalid RubyRequestType"); 404 } 405 } 406 407 AccessType cache_request_type_to_access_type(RubyRequestType type) { 408 if ((type == RubyRequestType:LD) || (type == RubyRequestType:IFETCH)) { 409 return AccessType:Read; 410 } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) { 411 return AccessType:Write; 412 } else { 413 error("Invalid RubyRequestType"); 414 } 415 } 416 417 // NOTE: direct local hits should not call this function 418 bool isExternalHit(Addr addr, MachineID sender) { 419 if (machineIDToMachineType(sender) == MachineType:L1Cache) { 420 return true; 421 } else if (machineIDToMachineType(sender) == MachineType:L2Cache) { 422 423 if (sender == mapAddressToRange(addr, MachineType:L2Cache, 424 l2_select_low_bit, l2_select_num_bits, intToID(0))) { 425 return false; 426 } else { 427 return true; 428 } 429 } 430 431 return true; 432 } 433 434 bool okToIssueStarving(Addr addr, MachineID machineID) { 435 return persistentTable.okToIssueStarving(addr, machineID); 436 } 437 438 void markPersistentEntries(Addr addr) { 439 persistentTable.markEntries(addr); 440 } 441 442 void setExternalResponse(TBE tbe) { 443 assert(is_valid(tbe)); 444 tbe.ExternalResponse := true; 445 } 446 447 bool IsAtomic(TBE tbe) { 448 assert(is_valid(tbe)); 449 return tbe.IsAtomic; 450 } 451 452 // ** OUT_PORTS ** 453 out_port(persistentNetwork_out, PersistentMsg, persistentFromL1Cache); 454 out_port(requestNetwork_out, RequestMsg, requestFromL1Cache); 455 out_port(responseNetwork_out, ResponseMsg, responseFromL1Cache); 456 out_port(requestRecycle_out, RequestMsg, requestToL1Cache); 457 458 // ** IN_PORTS ** 459 460 // Use Timer 461 in_port(useTimerTable_in, Addr, useTimerTable, rank=5) { 462 if (useTimerTable_in.isReady(clockEdge())) { 463 Addr readyAddress := useTimerTable.nextAddress(); 464 TBE tbe := L1_TBEs.lookup(readyAddress); 465 466 if (persistentTable.isLocked(readyAddress) && 467 (persistentTable.findSmallest(readyAddress) != machineID)) { 468 if (persistentTable.typeOfSmallest(readyAddress) == AccessType:Write) { 469 trigger(Event:Use_TimeoutStarverX, readyAddress, 470 getCacheEntry(readyAddress), tbe); 471 } else { 472 trigger(Event:Use_TimeoutStarverS, readyAddress, 473 getCacheEntry(readyAddress), tbe); 474 } 475 } else { 476 if (no_mig_atomic && IsAtomic(tbe)) { 477 trigger(Event:Use_TimeoutNoStarvers_NoMig, readyAddress, 478 getCacheEntry(readyAddress), tbe); 479 } else { 480 trigger(Event:Use_TimeoutNoStarvers, readyAddress, 481 getCacheEntry(readyAddress), tbe); 482 } 483 } 484 } 485 } 486 487 // Reissue Timer 488 in_port(reissueTimerTable_in, Addr, reissueTimerTable, rank=4) { 489 Tick current_time := clockEdge(); 490 if (reissueTimerTable_in.isReady(current_time)) { 491 Addr addr := reissueTimerTable.nextAddress(); 492 trigger(Event:Request_Timeout, addr, getCacheEntry(addr), 493 L1_TBEs.lookup(addr)); 494 } 495 } 496 497 // Persistent Network 498 in_port(persistentNetwork_in, PersistentMsg, persistentToL1Cache, rank=3) { 499 if (persistentNetwork_in.isReady(clockEdge())) { 500 peek(persistentNetwork_in, PersistentMsg, block_on="addr") { 501 assert(in_msg.Destination.isElement(machineID)); 502 503 // Apply the lockdown or unlockdown message to the table 504 if (in_msg.Type == PersistentRequestType:GETX_PERSISTENT) { 505 persistentTable.persistentRequestLock(in_msg.addr, in_msg.Requestor, AccessType:Write); 506 } else if (in_msg.Type == PersistentRequestType:GETS_PERSISTENT) { 507 persistentTable.persistentRequestLock(in_msg.addr, in_msg.Requestor, AccessType:Read); 508 } else if (in_msg.Type == PersistentRequestType:DEACTIVATE_PERSISTENT) { 509 persistentTable.persistentRequestUnlock(in_msg.addr, in_msg.Requestor); 510 } else { 511 error("Unexpected message"); 512 } 513 514 // React to the message based on the current state of the table 515 Entry cache_entry := getCacheEntry(in_msg.addr); 516 TBE tbe := L1_TBEs[in_msg.addr]; 517 518 if (persistentTable.isLocked(in_msg.addr)) { 519 if (persistentTable.findSmallest(in_msg.addr) == machineID) { 520 // Our Own Lock - this processor is highest priority 521 trigger(Event:Own_Lock_or_Unlock, in_msg.addr, 522 cache_entry, tbe); 523 } else { 524 if (persistentTable.typeOfSmallest(in_msg.addr) == AccessType:Read) { 525 if (getTokens(cache_entry) == 1 || 526 getTokens(cache_entry) == (max_tokens() / 2) + 1) { 527 trigger(Event:Persistent_GETS_Last_Token, in_msg.addr, 528 cache_entry, tbe); 529 } else { 530 trigger(Event:Persistent_GETS, in_msg.addr, 531 cache_entry, tbe); 532 } 533 } else { 534 trigger(Event:Persistent_GETX, in_msg.addr, 535 cache_entry, tbe); 536 } 537 } 538 } else { 539 // Unlock case - no entries in the table 540 trigger(Event:Own_Lock_or_Unlock, in_msg.addr, 541 cache_entry, tbe); 542 } 543 } 544 } 545 } 546 547 // Response Network 548 in_port(responseNetwork_in, ResponseMsg, responseToL1Cache, rank=2) { 549 if (responseNetwork_in.isReady(clockEdge())) { 550 peek(responseNetwork_in, ResponseMsg, block_on="addr") { 551 assert(in_msg.Destination.isElement(machineID)); 552 553 Entry cache_entry := getCacheEntry(in_msg.addr); 554 TBE tbe := L1_TBEs[in_msg.addr]; 555 556 // Mark TBE flag if response received off-chip. Use this to update average latency estimate 557 if ( machineIDToMachineType(in_msg.Sender) == MachineType:L2Cache ) { 558 559 if (in_msg.Sender == mapAddressToRange(in_msg.addr, 560 MachineType:L2Cache, l2_select_low_bit, 561 l2_select_num_bits, intToID(0))) { 562 563 // came from an off-chip L2 cache 564 if (is_valid(tbe)) { 565 // L1_TBEs[in_msg.addr].ExternalResponse := true; 566 // profile_offchipL2_response(in_msg.addr); 567 } 568 } 569 else { 570 // profile_onchipL2_response(in_msg.addr ); 571 } 572 } else if ( machineIDToMachineType(in_msg.Sender) == MachineType:Directory ) { 573 if (is_valid(tbe)) { 574 setExternalResponse(tbe); 575 // profile_memory_response( in_msg.addr); 576 } 577 } else if ( machineIDToMachineType(in_msg.Sender) == MachineType:L1Cache) { 578 //if (isLocalProcessor(machineID, in_msg.Sender) == false) { 579 //if (is_valid(tbe)) { 580 // tbe.ExternalResponse := true; 581 // profile_offchipL1_response(in_msg.addr ); 582 //} 583 //} 584 //else { 585 // profile_onchipL1_response(in_msg.addr ); 586 //} 587 } else { 588 error("unexpected SenderMachine"); 589 } 590 591 592 if (getTokens(cache_entry) + in_msg.Tokens != max_tokens()) { 593 if (in_msg.Type == CoherenceResponseType:ACK) { 594 assert(in_msg.Tokens < (max_tokens() / 2)); 595 trigger(Event:Ack, in_msg.addr, cache_entry, tbe); 596 } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER) { 597 trigger(Event:Data_Owner, in_msg.addr, cache_entry, tbe); 598 } else if (in_msg.Type == CoherenceResponseType:DATA_SHARED) { 599 assert(in_msg.Tokens < (max_tokens() / 2)); 600 trigger(Event:Data_Shared, in_msg.addr, cache_entry, tbe); 601 } else { 602 error("Unexpected message"); 603 } 604 } else { 605 if (in_msg.Type == CoherenceResponseType:ACK) { 606 assert(in_msg.Tokens < (max_tokens() / 2)); 607 trigger(Event:Ack_All_Tokens, in_msg.addr, cache_entry, tbe); 608 } else if (in_msg.Type == CoherenceResponseType:DATA_OWNER || in_msg.Type == CoherenceResponseType:DATA_SHARED) { 609 trigger(Event:Data_All_Tokens, in_msg.addr, cache_entry, tbe); 610 } else { 611 error("Unexpected message"); 612 } 613 } 614 } 615 } 616 } 617 618 // Request Network 619 in_port(requestNetwork_in, RequestMsg, requestToL1Cache) { 620 if (requestNetwork_in.isReady(clockEdge())) { 621 peek(requestNetwork_in, RequestMsg, block_on="addr") { 622 assert(in_msg.Destination.isElement(machineID)); 623 624 Entry cache_entry := getCacheEntry(in_msg.addr); 625 TBE tbe := L1_TBEs[in_msg.addr]; 626 627 if (in_msg.Type == CoherenceRequestType:GETX) { 628 if (in_msg.isLocal) { 629 trigger(Event:Transient_Local_GETX, in_msg.addr, 630 cache_entry, tbe); 631 } 632 else { 633 trigger(Event:Transient_GETX, in_msg.addr, 634 cache_entry, tbe); 635 } 636 } else if (in_msg.Type == CoherenceRequestType:GETS) { 637 if (getTokens(cache_entry) == 1 || 638 getTokens(cache_entry) == (max_tokens() / 2) + 1) { 639 if (in_msg.isLocal) { 640 trigger(Event:Transient_Local_GETS_Last_Token, in_msg.addr, 641 cache_entry, tbe); 642 } 643 else { 644 trigger(Event:Transient_GETS_Last_Token, in_msg.addr, 645 cache_entry, tbe); 646 } 647 } 648 else { 649 if (in_msg.isLocal) { 650 trigger(Event:Transient_Local_GETS, in_msg.addr, 651 cache_entry, tbe); 652 } 653 else { 654 trigger(Event:Transient_GETS, in_msg.addr, 655 cache_entry, tbe); 656 } 657 } 658 } else { 659 error("Unexpected message"); 660 } 661 } 662 } 663 } 664 665 // Mandatory Queue 666 in_port(mandatoryQueue_in, RubyRequest, mandatoryQueue, desc="...", rank=0) { 667 if (mandatoryQueue_in.isReady(clockEdge())) { 668 peek(mandatoryQueue_in, RubyRequest, block_on="LineAddress") { 669 // Check for data access to blocks in I-cache and ifetchs to blocks in D-cache 670 671 TBE tbe := L1_TBEs[in_msg.LineAddress]; 672 673 if (in_msg.Type == RubyRequestType:IFETCH) { 674 // ** INSTRUCTION ACCESS *** 675 676 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 677 if (is_valid(L1Icache_entry)) { 678 // The tag matches for the L1, so the L1 fetches the line. 679 // We know it can't be in the L2 due to exclusion. 680 trigger(mandatory_request_type_to_event(in_msg.Type), 681 in_msg.LineAddress, L1Icache_entry, tbe); 682 } else { 683 684 // Check to see if it is in the OTHER L1 685 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 686 if (is_valid(L1Dcache_entry)) { 687 // The block is in the wrong L1, try to write it to the L2 688 trigger(Event:L1_Replacement, in_msg.LineAddress, 689 L1Dcache_entry, tbe); 690 } 691 692 if (L1Icache.cacheAvail(in_msg.LineAddress)) { 693 // L1 does't have the line, but we have space for it in the L1 694 trigger(mandatory_request_type_to_event(in_msg.Type), 695 in_msg.LineAddress, L1Icache_entry, tbe); 696 } else { 697 // No room in the L1, so we need to make room 698 trigger(Event:L1_Replacement, 699 L1Icache.cacheProbe(in_msg.LineAddress), 700 getL1ICacheEntry(L1Icache.cacheProbe(in_msg.LineAddress)), 701 L1_TBEs[L1Icache.cacheProbe(in_msg.LineAddress)]); 702 } 703 } 704 } else { 705 // *** DATA ACCESS *** 706 707 Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress); 708 if (is_valid(L1Dcache_entry)) { 709 // The tag matches for the L1, so the L1 fetches the line. 710 // We know it can't be in the L2 due to exclusion. 711 trigger(mandatory_request_type_to_event(in_msg.Type), 712 in_msg.LineAddress, L1Dcache_entry, tbe); 713 } else { 714 715 // Check to see if it is in the OTHER L1 716 Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress); 717 if (is_valid(L1Icache_entry)) { 718 // The block is in the wrong L1, try to write it to the L2 719 trigger(Event:L1_Replacement, in_msg.LineAddress, 720 L1Icache_entry, tbe); 721 } 722 723 if (L1Dcache.cacheAvail(in_msg.LineAddress)) { 724 // L1 does't have the line, but we have space for it in the L1 725 trigger(mandatory_request_type_to_event(in_msg.Type), 726 in_msg.LineAddress, L1Dcache_entry, tbe); 727 } else { 728 // No room in the L1, so we need to make room 729 trigger(Event:L1_Replacement, 730 L1Dcache.cacheProbe(in_msg.LineAddress), 731 getL1DCacheEntry(L1Dcache.cacheProbe(in_msg.LineAddress)), 732 L1_TBEs[L1Dcache.cacheProbe(in_msg.LineAddress)]); 733 } 734 } 735 } 736 } 737 } 738 } 739 740 // ACTIONS 741 742 action(a_issueReadRequest, "a", desc="Issue GETS") { 743 assert(is_valid(tbe)); 744 if (tbe.IssueCount == 0) { 745 // Update outstanding requests 746 //profile_outstanding_request(outstandingRequests); 747 outstandingRequests := outstandingRequests + 1; 748 } 749 750 if (tbe.IssueCount >= retry_threshold) { 751 // Issue a persistent request if possible 752 if (okToIssueStarving(address, machineID) && (starving == false)) { 753 enqueue(persistentNetwork_out, PersistentMsg, l1_request_latency) { 754 out_msg.addr := address; 755 out_msg.Type := PersistentRequestType:GETS_PERSISTENT; 756 out_msg.Requestor := machineID; 757 out_msg.Destination.broadcast(MachineType:L1Cache); 758 759 // 760 // Currently the configuration system limits the system to only one 761 // chip. Therefore, if we assume one shared L2 cache, then only one 762 // pertinent L2 cache exist. 763 // 764 //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); 765 766 out_msg.Destination.add(mapAddressToRange(address, 767 MachineType:L2Cache, l2_select_low_bit, 768 l2_select_num_bits, intToID(0))); 769 770 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 771 out_msg.MessageSize := MessageSizeType:Persistent_Control; 772 out_msg.Prefetch := tbe.Prefetch; 773 out_msg.AccessMode := tbe.AccessMode; 774 } 775 markPersistentEntries(address); 776 starving := true; 777 778 if (tbe.IssueCount == 0) { 779 //profile_persistent_prediction(address, tbe.TypeOfAccess); 780 } 781 782 // Update outstanding requests 783 //profile_outstanding_persistent_request(outstandingPersistentRequests); 784 outstandingPersistentRequests := outstandingPersistentRequests + 1; 785 786 // Increment IssueCount 787 tbe.IssueCount := tbe.IssueCount + 1; 788 789 tbe.WentPersistent := true; 790 791 // Do not schedule a wakeup, a persistent requests will always complete 792 } 793 else { 794 795 // We'd like to issue a persistent request, but are not allowed 796 // to issue a P.R. right now. This, we do not increment the 797 // IssueCount. 798 799 // Set a wakeup timer 800 reissueTimerTable.set( 801 address, clockEdge() + cyclesToTicks(reissue_wakeup_latency)); 802 803 } 804 } else { 805 // Make a normal request 806 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) { 807 out_msg.addr := address; 808 out_msg.Type := CoherenceRequestType:GETS; 809 out_msg.Requestor := machineID; 810 out_msg.Destination.add(mapAddressToRange(address, 811 MachineType:L2Cache, l2_select_low_bit, 812 l2_select_num_bits, intToID(0))); 813 814 out_msg.RetryNum := tbe.IssueCount; 815 if (tbe.IssueCount == 0) { 816 out_msg.MessageSize := MessageSizeType:Request_Control; 817 } else { 818 out_msg.MessageSize := MessageSizeType:Reissue_Control; 819 } 820 out_msg.Prefetch := tbe.Prefetch; 821 out_msg.AccessMode := tbe.AccessMode; 822 } 823 824 // send to other local L1s, with local bit set 825 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) { 826 out_msg.addr := address; 827 out_msg.Type := CoherenceRequestType:GETS; 828 out_msg.Requestor := machineID; 829 // 830 // Since only one chip, assuming all L1 caches are local 831 // 832 //out_msg.Destination := getOtherLocalL1IDs(machineID); 833 out_msg.Destination.broadcast(MachineType:L1Cache); 834 out_msg.Destination.remove(machineID); 835 836 out_msg.RetryNum := tbe.IssueCount; 837 out_msg.isLocal := true; 838 if (tbe.IssueCount == 0) { 839 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 840 } else { 841 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 842 } 843 out_msg.Prefetch := tbe.Prefetch; 844 out_msg.AccessMode := tbe.AccessMode; 845 } 846 847 // Increment IssueCount 848 tbe.IssueCount := tbe.IssueCount + 1; 849 850 // Set a wakeup timer 851 852 if (dynamic_timeout_enabled) { 853 reissueTimerTable.set( 854 address, clockEdge() + cyclesToTicks(averageLatencyEstimate())); 855 } else { 856 reissueTimerTable.set( 857 address, clockEdge() + cyclesToTicks(fixed_timeout_latency)); 858 } 859 860 } 861 } 862 863 action(b_issueWriteRequest, "b", desc="Issue GETX") { 864 865 assert(is_valid(tbe)); 866 if (tbe.IssueCount == 0) { 867 // Update outstanding requests 868 //profile_outstanding_request(outstandingRequests); 869 outstandingRequests := outstandingRequests + 1; 870 } 871 872 if (tbe.IssueCount >= retry_threshold) { 873 // Issue a persistent request if possible 874 if ( okToIssueStarving(address, machineID) && (starving == false)) { 875 enqueue(persistentNetwork_out, PersistentMsg, l1_request_latency) { 876 out_msg.addr := address; 877 out_msg.Type := PersistentRequestType:GETX_PERSISTENT; 878 out_msg.Requestor := machineID; 879 out_msg.Destination.broadcast(MachineType:L1Cache); 880 881 // 882 // Currently the configuration system limits the system to only one 883 // chip. Therefore, if we assume one shared L2 cache, then only one 884 // pertinent L2 cache exist. 885 // 886 //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); 887 888 out_msg.Destination.add(mapAddressToRange(address, 889 MachineType:L2Cache, l2_select_low_bit, 890 l2_select_num_bits, intToID(0))); 891 892 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 893 out_msg.MessageSize := MessageSizeType:Persistent_Control; 894 out_msg.Prefetch := tbe.Prefetch; 895 out_msg.AccessMode := tbe.AccessMode; 896 } 897 markPersistentEntries(address); 898 starving := true; 899 900 // Update outstanding requests 901 //profile_outstanding_persistent_request(outstandingPersistentRequests); 902 outstandingPersistentRequests := outstandingPersistentRequests + 1; 903 904 if (tbe.IssueCount == 0) { 905 //profile_persistent_prediction(address, tbe.TypeOfAccess); 906 } 907 908 // Increment IssueCount 909 tbe.IssueCount := tbe.IssueCount + 1; 910 911 tbe.WentPersistent := true; 912 913 // Do not schedule a wakeup, a persistent requests will always complete 914 } 915 else { 916 917 // We'd like to issue a persistent request, but are not allowed 918 // to issue a P.R. right now. This, we do not increment the 919 // IssueCount. 920 921 // Set a wakeup timer 922 reissueTimerTable.set( 923 address, clockEdge() + cyclesToTicks(reissue_wakeup_latency)); 924 } 925 926 } else { 927 // Make a normal request 928 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) { 929 out_msg.addr := address; 930 out_msg.Type := CoherenceRequestType:GETX; 931 out_msg.Requestor := machineID; 932 933 out_msg.Destination.add(mapAddressToRange(address, 934 MachineType:L2Cache, l2_select_low_bit, 935 l2_select_num_bits, intToID(0))); 936 937 out_msg.RetryNum := tbe.IssueCount; 938 939 if (tbe.IssueCount == 0) { 940 out_msg.MessageSize := MessageSizeType:Request_Control; 941 } else { 942 out_msg.MessageSize := MessageSizeType:Reissue_Control; 943 } 944 out_msg.Prefetch := tbe.Prefetch; 945 out_msg.AccessMode := tbe.AccessMode; 946 } 947 948 // send to other local L1s too 949 enqueue(requestNetwork_out, RequestMsg, l1_request_latency) { 950 out_msg.addr := address; 951 out_msg.Type := CoherenceRequestType:GETX; 952 out_msg.Requestor := machineID; 953 out_msg.isLocal := true; 954 955 // 956 // Since only one chip, assuming all L1 caches are local 957 // 958 //out_msg.Destination := getOtherLocalL1IDs(machineID); 959 out_msg.Destination.broadcast(MachineType:L1Cache); 960 out_msg.Destination.remove(machineID); 961 962 out_msg.RetryNum := tbe.IssueCount; 963 if (tbe.IssueCount == 0) { 964 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 965 } else { 966 out_msg.MessageSize := MessageSizeType:Broadcast_Control; 967 } 968 out_msg.Prefetch := tbe.Prefetch; 969 out_msg.AccessMode := tbe.AccessMode; 970 } 971 972 // Increment IssueCount 973 tbe.IssueCount := tbe.IssueCount + 1; 974 975 DPRINTF(RubySlicc, "incremented issue count to %d\n", 976 tbe.IssueCount); 977 978 // Set a wakeup timer 979 if (dynamic_timeout_enabled) { 980 reissueTimerTable.set( 981 address, clockEdge() + cyclesToTicks(averageLatencyEstimate())); 982 } else { 983 reissueTimerTable.set( 984 address, clockEdge() + cyclesToTicks(fixed_timeout_latency)); 985 } 986 } 987 } 988 989 action(bb_bounceResponse, "\b", desc="Bounce tokens and data to memory") { 990 peek(responseNetwork_in, ResponseMsg) { 991 // FIXME, should use a 3rd vnet 992 enqueue(responseNetwork_out, ResponseMsg, 1) { 993 out_msg.addr := address; 994 out_msg.Type := in_msg.Type; 995 out_msg.Sender := machineID; 996 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 997 out_msg.Tokens := in_msg.Tokens; 998 out_msg.MessageSize := in_msg.MessageSize; 999 out_msg.DataBlk := in_msg.DataBlk; 1000 out_msg.Dirty := in_msg.Dirty; 1001 } 1002 } 1003 } 1004 1005 action(c_ownedReplacement, "c", desc="Issue writeback") { 1006 assert(is_valid(cache_entry)); 1007 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1008 out_msg.addr := address; 1009 out_msg.Sender := machineID; 1010 1011 out_msg.Destination.add(mapAddressToRange(address, 1012 MachineType:L2Cache, l2_select_low_bit, 1013 l2_select_num_bits, intToID(0))); 1014 1015 out_msg.Tokens := cache_entry.Tokens; 1016 out_msg.DataBlk := cache_entry.DataBlk; 1017 out_msg.Dirty := cache_entry.Dirty; 1018 out_msg.Type := CoherenceResponseType:WB_OWNED; 1019 1020 // always send the data? 1021 out_msg.MessageSize := MessageSizeType:Writeback_Data; 1022 } 1023 cache_entry.Tokens := 0; 1024 } 1025 1026 action(cc_sharedReplacement, "\c", desc="Issue shared writeback") { 1027 1028 // don't send writeback if replacing block with no tokens 1029 assert(is_valid(cache_entry)); 1030 assert (cache_entry.Tokens > 0); 1031 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1032 out_msg.addr := address; 1033 out_msg.Sender := machineID; 1034 1035 out_msg.Destination.add(mapAddressToRange(address, 1036 MachineType:L2Cache, l2_select_low_bit, 1037 l2_select_num_bits, intToID(0))); 1038 1039 out_msg.Tokens := cache_entry.Tokens; 1040 out_msg.DataBlk := cache_entry.DataBlk; 1041 // assert(cache_entry.Dirty == false); 1042 out_msg.Dirty := false; 1043 1044 out_msg.MessageSize := MessageSizeType:Writeback_Data; 1045 out_msg.Type := CoherenceResponseType:WB_SHARED_DATA; 1046 } 1047 cache_entry.Tokens := 0; 1048 } 1049 1050 action(tr_tokenReplacement, "tr", desc="Issue token writeback") { 1051 assert(is_valid(cache_entry)); 1052 if (cache_entry.Tokens > 0) { 1053 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1054 out_msg.addr := address; 1055 out_msg.Sender := machineID; 1056 1057 out_msg.Destination.add(mapAddressToRange(address, 1058 MachineType:L2Cache, l2_select_low_bit, 1059 l2_select_num_bits, intToID(0))); 1060 1061 out_msg.Tokens := cache_entry.Tokens; 1062 out_msg.DataBlk := cache_entry.DataBlk; 1063 // assert(cache_entry.Dirty == false); 1064 out_msg.Dirty := false; 1065 1066 // always send the data? 1067 out_msg.MessageSize := MessageSizeType:Writeback_Control; 1068 out_msg.Type := CoherenceResponseType:WB_TOKENS; 1069 } 1070 } 1071 cache_entry.Tokens := 0; 1072 } 1073 1074 1075 action(d_sendDataWithToken, "d", desc="Send data and a token from cache to requestor") { 1076 assert(is_valid(cache_entry)); 1077 peek(requestNetwork_in, RequestMsg) { 1078 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1079 out_msg.addr := address; 1080 out_msg.Type := CoherenceResponseType:DATA_SHARED; 1081 out_msg.Sender := machineID; 1082 out_msg.Destination.add(in_msg.Requestor); 1083 out_msg.Tokens := 1; 1084 out_msg.DataBlk := cache_entry.DataBlk; 1085 // out_msg.Dirty := cache_entry.Dirty; 1086 out_msg.Dirty := false; 1087 if (in_msg.isLocal) { 1088 out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; 1089 } else { 1090 out_msg.MessageSize := MessageSizeType:Response_Data; 1091 } 1092 } 1093 } 1094 cache_entry.Tokens := cache_entry.Tokens - 1; 1095 assert(cache_entry.Tokens >= 1); 1096 } 1097 1098 action(d_sendDataWithNTokenIfAvail, "\dd", desc="Send data and a token from cache to requestor") { 1099 assert(is_valid(cache_entry)); 1100 peek(requestNetwork_in, RequestMsg) { 1101 if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { 1102 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1103 out_msg.addr := address; 1104 out_msg.Type := CoherenceResponseType:DATA_SHARED; 1105 out_msg.Sender := machineID; 1106 out_msg.Destination.add(in_msg.Requestor); 1107 out_msg.Tokens := N_tokens; 1108 out_msg.DataBlk := cache_entry.DataBlk; 1109 // out_msg.Dirty := cache_entry.Dirty; 1110 out_msg.Dirty := false; 1111 if (in_msg.isLocal) { 1112 out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; 1113 } else { 1114 out_msg.MessageSize := MessageSizeType:Response_Data; 1115 } 1116 } 1117 cache_entry.Tokens := cache_entry.Tokens - N_tokens; 1118 } 1119 else if (cache_entry.Tokens > 1) { 1120 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1121 out_msg.addr := address; 1122 out_msg.Type := CoherenceResponseType:DATA_SHARED; 1123 out_msg.Sender := machineID; 1124 out_msg.Destination.add(in_msg.Requestor); 1125 out_msg.Tokens := 1; 1126 out_msg.DataBlk := cache_entry.DataBlk; 1127 // out_msg.Dirty := cache_entry.Dirty; 1128 out_msg.Dirty := false; 1129 if (in_msg.isLocal) { 1130 out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; 1131 } else { 1132 out_msg.MessageSize := MessageSizeType:Response_Data; 1133 } 1134 } 1135 cache_entry.Tokens := cache_entry.Tokens - 1; 1136 } 1137 } 1138// assert(cache_entry.Tokens >= 1); 1139 } 1140 1141 action(dd_sendDataWithAllTokens, "\d", desc="Send data and all tokens from cache to requestor") { 1142 peek(requestNetwork_in, RequestMsg) { 1143 assert(is_valid(cache_entry)); 1144 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1145 out_msg.addr := address; 1146 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1147 out_msg.Sender := machineID; 1148 out_msg.Destination.add(in_msg.Requestor); 1149 assert(cache_entry.Tokens > (max_tokens() / 2)); 1150 out_msg.Tokens := cache_entry.Tokens; 1151 out_msg.DataBlk := cache_entry.DataBlk; 1152 out_msg.Dirty := cache_entry.Dirty; 1153 if (in_msg.isLocal) { 1154 out_msg.MessageSize := MessageSizeType:ResponseLocal_Data; 1155 } else { 1156 out_msg.MessageSize := MessageSizeType:Response_Data; 1157 } 1158 } 1159 } 1160 cache_entry.Tokens := 0; 1161 } 1162 1163 action(e_sendAckWithCollectedTokens, "e", desc="Send ack with the tokens we've collected thus far.") { 1164 // assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 1165 assert(is_valid(cache_entry)); 1166 if (cache_entry.Tokens > 0) { 1167 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1168 out_msg.addr := address; 1169 if (cache_entry.Tokens > (max_tokens() / 2)) { 1170 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1171 } else { 1172 out_msg.Type := CoherenceResponseType:ACK; 1173 } 1174 out_msg.Sender := machineID; 1175 out_msg.Destination.add(persistentTable.findSmallest(address)); 1176 assert(cache_entry.Tokens >= 1); 1177 out_msg.Tokens := cache_entry.Tokens; 1178 out_msg.DataBlk := cache_entry.DataBlk; 1179 out_msg.MessageSize := MessageSizeType:Response_Control; 1180 } 1181 } 1182 cache_entry.Tokens := 0; 1183 } 1184 1185 action(ee_sendDataWithAllTokens, "\e", desc="Send data and all tokens from cache to starver") { 1186 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 1187 assert(is_valid(cache_entry)); 1188 assert(cache_entry.Tokens > 0); 1189 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1190 out_msg.addr := address; 1191 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1192 out_msg.Sender := machineID; 1193 out_msg.Destination.add(persistentTable.findSmallest(address)); 1194 assert(cache_entry.Tokens > (max_tokens() / 2)); 1195 out_msg.Tokens := cache_entry.Tokens; 1196 out_msg.DataBlk := cache_entry.DataBlk; 1197 out_msg.Dirty := cache_entry.Dirty; 1198 out_msg.MessageSize := MessageSizeType:Response_Data; 1199 } 1200 cache_entry.Tokens := 0; 1201 } 1202 1203 action(f_sendAckWithAllButNorOneTokens, "f", desc="Send ack with all our tokens but one to starver.") { 1204 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 1205 assert(is_valid(cache_entry)); 1206 assert(cache_entry.Tokens > 0); 1207 if (cache_entry.Tokens > 1) { 1208 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1209 out_msg.addr := address; 1210 if (cache_entry.Tokens > (max_tokens() / 2)) { 1211 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1212 } else { 1213 out_msg.Type := CoherenceResponseType:ACK; 1214 } 1215 out_msg.Sender := machineID; 1216 out_msg.Destination.add(persistentTable.findSmallest(address)); 1217 assert(cache_entry.Tokens >= 1); 1218 if (cache_entry.Tokens > N_tokens) { 1219 out_msg.Tokens := cache_entry.Tokens - N_tokens; 1220 } else { 1221 out_msg.Tokens := cache_entry.Tokens - 1; 1222 } 1223 out_msg.DataBlk := cache_entry.DataBlk; 1224 out_msg.MessageSize := MessageSizeType:Response_Control; 1225 } 1226 } 1227 if (cache_entry.Tokens > N_tokens) { 1228 cache_entry.Tokens := N_tokens; 1229 } else { 1230 cache_entry.Tokens := 1; 1231 } 1232 } 1233 1234 action(ff_sendDataWithAllButNorOneTokens, "\f", desc="Send data and out tokens but one to starver") { 1235 //assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 1236 assert(is_valid(cache_entry)); 1237 assert(cache_entry.Tokens > ((max_tokens() / 2) + 1)); 1238 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1239 out_msg.addr := address; 1240 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1241 out_msg.Sender := machineID; 1242 out_msg.Destination.add(persistentTable.findSmallest(address)); 1243 if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { 1244 out_msg.Tokens := cache_entry.Tokens - N_tokens; 1245 } else { 1246 out_msg.Tokens := cache_entry.Tokens - 1; 1247 } 1248 assert(out_msg.Tokens > (max_tokens() / 2)); 1249 out_msg.DataBlk := cache_entry.DataBlk; 1250 out_msg.Dirty := cache_entry.Dirty; 1251 out_msg.MessageSize := MessageSizeType:Response_Data; 1252 } 1253 if (cache_entry.Tokens > (N_tokens + (max_tokens() / 2))) { 1254 cache_entry.Tokens := N_tokens; 1255 } else { 1256 cache_entry.Tokens := 1; 1257 } 1258 } 1259 1260 action(fo_sendDataWithOwnerToken, "fo", desc="Send data and owner tokens") { 1261 assert(is_valid(cache_entry)); 1262 assert(cache_entry.Tokens == ((max_tokens() / 2) + 1)); 1263 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1264 out_msg.addr := address; 1265 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1266 out_msg.Sender := machineID; 1267 out_msg.Destination.add(persistentTable.findSmallest(address)); 1268 out_msg.Tokens := cache_entry.Tokens; 1269 assert(out_msg.Tokens > (max_tokens() / 2)); 1270 out_msg.DataBlk := cache_entry.DataBlk; 1271 out_msg.Dirty := cache_entry.Dirty; 1272 out_msg.MessageSize := MessageSizeType:Response_Data; 1273 } 1274 cache_entry.Tokens := 0; 1275 } 1276 1277 action(g_bounceResponseToStarver, "g", desc="Redirect response to starving processor") { 1278 // assert(persistentTable.isLocked(address)); 1279 1280 peek(responseNetwork_in, ResponseMsg) { 1281 // assert(persistentTable.findSmallest(address) != id); // Make sure we never bounce tokens to ourself 1282 // FIXME, should use a 3rd vnet in some cases 1283 enqueue(responseNetwork_out, ResponseMsg, 1) { 1284 out_msg.addr := address; 1285 out_msg.Type := in_msg.Type; 1286 out_msg.Sender := machineID; 1287 out_msg.Destination.add(persistentTable.findSmallest(address)); 1288 out_msg.Tokens := in_msg.Tokens; 1289 out_msg.DataBlk := in_msg.DataBlk; 1290 out_msg.Dirty := in_msg.Dirty; 1291 out_msg.MessageSize := in_msg.MessageSize; 1292 } 1293 } 1294 } 1295 1296 action(h_load_hit, "hd", desc="Notify sequencer the load completed.") { 1297 assert(is_valid(cache_entry)); 1298 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n", 1299 address, cache_entry.DataBlk); 1300 1301 L1Dcache.setMRU(cache_entry); 1302 sequencer.readCallback(address, cache_entry.DataBlk, false, 1303 MachineType:L1Cache); 1304 } 1305 1306 action(h_ifetch_hit, "hi", desc="Notify sequencer the load completed.") { 1307 assert(is_valid(cache_entry)); 1308 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n", 1309 address, cache_entry.DataBlk); 1310 1311 L1Icache.setMRU(cache_entry); 1312 sequencer.readCallback(address, cache_entry.DataBlk, false, 1313 MachineType:L1Cache); 1314 } 1315 1316 action(x_external_load_hit, "x", desc="Notify sequencer the load completed.") { 1317 assert(is_valid(cache_entry)); 1318 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n", 1319 address, cache_entry.DataBlk); 1320 peek(responseNetwork_in, ResponseMsg) { 1321 L1Icache.setMRU(address); 1322 L1Dcache.setMRU(address); 1323 sequencer.readCallback(address, cache_entry.DataBlk, 1324 isExternalHit(address, in_msg.Sender), 1325 machineIDToMachineType(in_msg.Sender)); 1326 } 1327 } 1328 1329 action(hh_store_hit, "\h", desc="Notify sequencer that store completed.") { 1330 assert(is_valid(cache_entry)); 1331 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n", 1332 address, cache_entry.DataBlk); 1333 1334 L1Dcache.setMRU(cache_entry); 1335 sequencer.writeCallback(address, cache_entry.DataBlk, false, 1336 MachineType:L1Cache); 1337 cache_entry.Dirty := true; 1338 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 1339 } 1340 1341 action(xx_external_store_hit, "\x", desc="Notify sequencer that store completed.") { 1342 assert(is_valid(cache_entry)); 1343 DPRINTF(RubySlicc, "Address: %#x, Data Block: %s\n", 1344 address, cache_entry.DataBlk); 1345 peek(responseNetwork_in, ResponseMsg) { 1346 L1Icache.setMRU(address); 1347 L1Dcache.setMRU(address); 1348 sequencer.writeCallback(address, cache_entry.DataBlk, 1349 isExternalHit(address, in_msg.Sender), 1350 machineIDToMachineType(in_msg.Sender)); 1351 } 1352 cache_entry.Dirty := true; 1353 DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk); 1354 } 1355 1356 action(i_allocateTBE, "i", desc="Allocate TBE") { 1357 check_allocate(L1_TBEs); 1358 L1_TBEs.allocate(address); 1359 set_tbe(L1_TBEs[address]); 1360 tbe.IssueCount := 0; 1361 peek(mandatoryQueue_in, RubyRequest) { 1362 tbe.PC := in_msg.ProgramCounter; 1363 tbe.TypeOfAccess := cache_request_type_to_access_type(in_msg.Type); 1364 if (in_msg.Type == RubyRequestType:ATOMIC) { 1365 tbe.IsAtomic := true; 1366 } 1367 tbe.Prefetch := in_msg.Prefetch; 1368 tbe.AccessMode := in_msg.AccessMode; 1369 } 1370 tbe.IssueTime := curCycle(); 1371 } 1372 1373 action(ta_traceStalledAddress, "ta", desc="Trace Stalled Address") { 1374 peek(mandatoryQueue_in, RubyRequest) { 1375 APPEND_TRANSITION_COMMENT(in_msg.LineAddress); 1376 } 1377 } 1378 1379 action(j_unsetReissueTimer, "j", desc="Unset reissue timer.") { 1380 if (reissueTimerTable.isSet(address)) { 1381 reissueTimerTable.unset(address); 1382 } 1383 } 1384 1385 action(jj_unsetUseTimer, "\j", desc="Unset use timer.") { 1386 useTimerTable.unset(address); 1387 } 1388 1389 action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") { 1390 mandatoryQueue_in.dequeue(clockEdge()); 1391 } 1392 1393 action(l_popPersistentQueue, "l", desc="Pop persistent queue.") { 1394 persistentNetwork_in.dequeue(clockEdge()); 1395 } 1396 1397 action(m_popRequestQueue, "m", desc="Pop request queue.") { 1398 requestNetwork_in.dequeue(clockEdge()); 1399 } 1400 1401 action(n_popResponseQueue, "n", desc="Pop response queue") { 1402 responseNetwork_in.dequeue(clockEdge()); 1403 } 1404 1405 action(o_scheduleUseTimeout, "o", desc="Schedule a use timeout.") { 1406 useTimerTable.set( 1407 address, clockEdge() + cyclesToTicks(use_timeout_latency)); 1408 } 1409 1410 action(p_informL2AboutTokenLoss, "p", desc="Inform L2 about loss of all tokens") { 1411 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1412 out_msg.addr := address; 1413 out_msg.Type := CoherenceResponseType:INV; 1414 out_msg.Tokens := 0; 1415 out_msg.Sender := machineID; 1416 1417 out_msg.Destination.add(mapAddressToRange(address, 1418 MachineType:L2Cache, l2_select_low_bit, 1419 l2_select_num_bits, intToID(0))); 1420 out_msg.MessageSize := MessageSizeType:Response_Control; 1421 } 1422 } 1423 1424 action(q_updateTokensFromResponse, "q", desc="Update the token count based on the incoming response message") { 1425 peek(responseNetwork_in, ResponseMsg) { 1426 assert(is_valid(cache_entry)); 1427 assert(in_msg.Tokens != 0); 1428 DPRINTF(RubySlicc, "L1 received tokens for address: %#x, tokens: %d\n", 1429 in_msg.addr, in_msg.Tokens); 1430 cache_entry.Tokens := cache_entry.Tokens + in_msg.Tokens; 1431 DPRINTF(RubySlicc, "%d\n", cache_entry.Tokens); 1432 1433 if (cache_entry.Dirty == false && in_msg.Dirty) { 1434 cache_entry.Dirty := true; 1435 } 1436 } 1437 } 1438 1439 action(s_deallocateTBE, "s", desc="Deallocate TBE") { 1440 1441 assert(is_valid(tbe)); 1442 if (tbe.WentPersistent) { 1443 // assert(starving); 1444 outstandingRequests := outstandingRequests - 1; 1445 enqueue(persistentNetwork_out, PersistentMsg, l1_request_latency) { 1446 out_msg.addr := address; 1447 out_msg.Type := PersistentRequestType:DEACTIVATE_PERSISTENT; 1448 out_msg.Requestor := machineID; 1449 out_msg.Destination.broadcast(MachineType:L1Cache); 1450 1451 // 1452 // Currently the configuration system limits the system to only one 1453 // chip. Therefore, if we assume one shared L2 cache, then only one 1454 // pertinent L2 cache exist. 1455 // 1456 //out_msg.Destination.addNetDest(getAllPertinentL2Banks(address)); 1457 1458 out_msg.Destination.add(mapAddressToRange(address, 1459 MachineType:L2Cache, l2_select_low_bit, 1460 l2_select_num_bits, intToID(0))); 1461 1462 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 1463 out_msg.MessageSize := MessageSizeType:Persistent_Control; 1464 } 1465 starving := false; 1466 } 1467 1468 // Update average latency 1469 if (tbe.IssueCount <= 1) { 1470 if (tbe.ExternalResponse) { 1471 updateAverageLatencyEstimate(curCycle() - tbe.IssueTime); 1472 } 1473 } 1474 1475 // Profile 1476 //if (tbe.WentPersistent) { 1477 // profile_token_retry(address, tbe.TypeOfAccess, 2); 1478 //} 1479 //else { 1480 // profile_token_retry(address, tbe.TypeOfAccess, 1); 1481 //} 1482 1483 //profile_token_retry(address, tbe.TypeOfAccess, tbe.IssueCount); 1484 L1_TBEs.deallocate(address); 1485 unset_tbe(); 1486 } 1487 1488 action(t_sendAckWithCollectedTokens, "t", desc="Send ack with the tokens we've collected thus far.") { 1489 assert(is_valid(cache_entry)); 1490 if (cache_entry.Tokens > 0) { 1491 peek(requestNetwork_in, RequestMsg) { 1492 enqueue(responseNetwork_out, ResponseMsg, l1_response_latency) { 1493 out_msg.addr := address; 1494 if (cache_entry.Tokens > (max_tokens() / 2)) { 1495 out_msg.Type := CoherenceResponseType:DATA_OWNER; 1496 } else { 1497 out_msg.Type := CoherenceResponseType:ACK; 1498 } 1499 out_msg.Sender := machineID; 1500 out_msg.Destination.add(in_msg.Requestor); 1501 assert(cache_entry.Tokens >= 1); 1502 out_msg.Tokens := cache_entry.Tokens; 1503 out_msg.DataBlk := cache_entry.DataBlk; 1504 out_msg.MessageSize := MessageSizeType:Response_Control; 1505 } 1506 } 1507 } 1508 cache_entry.Tokens := 0; 1509 } 1510 1511 action(u_writeDataToCache, "u", desc="Write data to cache") { 1512 peek(responseNetwork_in, ResponseMsg) { 1513 assert(is_valid(cache_entry)); 1514 cache_entry.DataBlk := in_msg.DataBlk; 1515 if (cache_entry.Dirty == false && in_msg.Dirty) { 1516 cache_entry.Dirty := in_msg.Dirty; 1517 } 1518 1519 } 1520 } 1521 1522 action(gg_deallocateL1CacheBlock, "\g", desc="Deallocate cache block. Sets the cache to invalid, allowing a replacement in parallel with a fetch.") { 1523 assert(getTokens(cache_entry) == 0); 1524 if (L1Dcache.isTagPresent(address)) { 1525 L1Dcache.deallocate(address); 1526 } else { 1527 L1Icache.deallocate(address); 1528 } 1529 unset_cache_entry(); 1530 } 1531 1532 action(ii_allocateL1DCacheBlock, "\i", desc="Set L1 D-cache tag equal to tag of block B.") { 1533 if (is_valid(cache_entry)) { 1534 } else { 1535 set_cache_entry(L1Dcache.allocate(address, new Entry)); 1536 } 1537 } 1538 1539 action(pp_allocateL1ICacheBlock, "\p", desc="Set L1 I-cache tag equal to tag of block B.") { 1540 if (is_valid(cache_entry)) { 1541 } else { 1542 set_cache_entry(L1Icache.allocate(address, new Entry)); 1543 } 1544 } 1545 1546 action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { 1547 if (send_evictions) { 1548 DPRINTF(RubySlicc, "Sending invalidation for %#x to the CPU\n", address); 1549 sequencer.evictionCallback(address); 1550 } 1551 } 1552 1553 action(uu_profileInstMiss, "\uim", desc="Profile the demand miss") { 1554 ++L1Icache.demand_misses; 1555 } 1556 1557 action(uu_profileInstHit, "\uih", desc="Profile the demand hit") { 1558 ++L1Icache.demand_hits; 1559 } 1560 1561 action(uu_profileDataMiss, "\udm", desc="Profile the demand miss") { 1562 ++L1Dcache.demand_misses; 1563 } 1564 1565 action(uu_profileDataHit, "\udh", desc="Profile the demand hit") { 1566 ++L1Dcache.demand_hits; 1567 } 1568 1569 action(w_assertIncomingDataAndCacheDataMatch, "w", desc="Assert that the incoming data and the data in the cache match") { 1570 peek(responseNetwork_in, ResponseMsg) { 1571 assert(is_valid(cache_entry)); 1572 assert(cache_entry.DataBlk == in_msg.DataBlk); 1573 } 1574 } 1575 1576 action(zz_stallAndWaitMandatoryQueue, "\z", desc="Send the head of the mandatory queue to the back of the queue.") { 1577 peek(mandatoryQueue_in, RubyRequest) { 1578 APPEND_TRANSITION_COMMENT(in_msg.LineAddress); 1579 } 1580 stall_and_wait(mandatoryQueue_in, address); 1581 } 1582 1583 action(kd_wakeUpDependents, "kd", desc="wake-up dependents") { 1584 wakeUpBuffers(address); 1585 } 1586 1587 action(ka_wakeUpAllDependents, "ka", desc="wake-up all dependents") { 1588 wakeUpAllBuffers(); 1589 } 1590 1591 //***************************************************** 1592 // TRANSITIONS 1593 //***************************************************** 1594 1595 // Transitions for Load/Store/L2_Replacement from transient states 1596 transition({IM, SM, OM, IS, IM_L, IS_L, I_L, S_L, SM_L, M_W, MM_W}, L1_Replacement) { 1597 ta_traceStalledAddress; 1598 zz_stallAndWaitMandatoryQueue; 1599 } 1600 1601 transition({IM, SM, OM, IS, IM_L, IS_L, SM_L}, {Store, Atomic}) { 1602 zz_stallAndWaitMandatoryQueue; 1603 } 1604 1605 transition({IM, IS, IM_L, IS_L}, {Load, Ifetch}) { 1606 zz_stallAndWaitMandatoryQueue; 1607 } 1608 1609 // Lockdowns 1610 transition({NP, I, S, O, M, MM, M_W, MM_W, IM, SM, OM, IS}, Own_Lock_or_Unlock) { 1611 l_popPersistentQueue; 1612 } 1613 1614 // Transitions from NP 1615 transition(NP, Load, IS) { 1616 ii_allocateL1DCacheBlock; 1617 i_allocateTBE; 1618 a_issueReadRequest; 1619 uu_profileDataMiss; 1620 k_popMandatoryQueue; 1621 } 1622 1623 transition(NP, Ifetch, IS) { 1624 pp_allocateL1ICacheBlock; 1625 i_allocateTBE; 1626 a_issueReadRequest; 1627 uu_profileInstMiss; 1628 k_popMandatoryQueue; 1629 } 1630 1631 transition(NP, {Store, Atomic}, IM) { 1632 ii_allocateL1DCacheBlock; 1633 i_allocateTBE; 1634 b_issueWriteRequest; 1635 uu_profileDataMiss; 1636 k_popMandatoryQueue; 1637 } 1638 1639 transition(NP, {Ack, Data_Shared, Data_Owner, Data_All_Tokens}) { 1640 bb_bounceResponse; 1641 n_popResponseQueue; 1642 } 1643 1644 transition(NP, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_Local_GETS}) { 1645 m_popRequestQueue; 1646 } 1647 1648 transition(NP, {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, I_L) { 1649 l_popPersistentQueue; 1650 } 1651 1652 // Transitions from Idle 1653 transition(I, Load, IS) { 1654 i_allocateTBE; 1655 a_issueReadRequest; 1656 uu_profileDataMiss; 1657 k_popMandatoryQueue; 1658 } 1659 1660 transition(I, Ifetch, IS) { 1661 i_allocateTBE; 1662 a_issueReadRequest; 1663 uu_profileInstMiss; 1664 k_popMandatoryQueue; 1665 } 1666 1667 transition(I, {Store, Atomic}, IM) { 1668 i_allocateTBE; 1669 b_issueWriteRequest; 1670 uu_profileDataMiss; 1671 k_popMandatoryQueue; 1672 } 1673 1674 transition(I, L1_Replacement) { 1675 ta_traceStalledAddress; 1676 tr_tokenReplacement; 1677 gg_deallocateL1CacheBlock; 1678 ka_wakeUpAllDependents; 1679 } 1680 1681 transition(I, {Transient_GETX, Transient_Local_GETX}) { 1682 t_sendAckWithCollectedTokens; 1683 m_popRequestQueue; 1684 } 1685 1686 transition(I, {Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS}) { 1687 m_popRequestQueue; 1688 } 1689 1690 transition(I, {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, I_L) { 1691 e_sendAckWithCollectedTokens; 1692 l_popPersistentQueue; 1693 } 1694 1695 transition(I_L, {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}) { 1696 l_popPersistentQueue; 1697 } 1698 1699 transition(I, Ack) { 1700 q_updateTokensFromResponse; 1701 n_popResponseQueue; 1702 } 1703 1704 transition(I, Data_Shared, S) { 1705 u_writeDataToCache; 1706 q_updateTokensFromResponse; 1707 n_popResponseQueue; 1708 } 1709 1710 transition(I, Data_Owner, O) { 1711 u_writeDataToCache; 1712 q_updateTokensFromResponse; 1713 n_popResponseQueue; 1714 } 1715 1716 transition(I, Data_All_Tokens, M) { 1717 u_writeDataToCache; 1718 q_updateTokensFromResponse; 1719 n_popResponseQueue; 1720 } 1721 1722 // Transitions from Shared 1723 transition({S, SM, S_L, SM_L}, Load) { 1724 h_load_hit; 1725 uu_profileDataHit; 1726 k_popMandatoryQueue; 1727 } 1728 1729 transition({S, SM, S_L, SM_L}, Ifetch) { 1730 h_ifetch_hit; 1731 uu_profileInstHit; 1732 k_popMandatoryQueue; 1733 } 1734 1735 transition(S, {Store, Atomic}, SM) { 1736 i_allocateTBE; 1737 b_issueWriteRequest; 1738 uu_profileDataMiss; 1739 k_popMandatoryQueue; 1740 } 1741 1742 transition(S, L1_Replacement, I) { 1743 ta_traceStalledAddress; 1744 cc_sharedReplacement; // Only needed in some cases 1745 forward_eviction_to_cpu; 1746 gg_deallocateL1CacheBlock; 1747 ka_wakeUpAllDependents; 1748 } 1749 1750 transition(S, {Transient_GETX, Transient_Local_GETX}, I) { 1751 t_sendAckWithCollectedTokens; 1752 p_informL2AboutTokenLoss; 1753 forward_eviction_to_cpu 1754 m_popRequestQueue; 1755 } 1756 1757 // only owner responds to non-local requests 1758 transition(S, Transient_GETS) { 1759 m_popRequestQueue; 1760 } 1761 1762 transition(S, Transient_Local_GETS) { 1763 d_sendDataWithToken; 1764 m_popRequestQueue; 1765 } 1766 1767 transition(S, {Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token}) { 1768 m_popRequestQueue; 1769 } 1770 1771 transition({S, S_L}, Persistent_GETX, I_L) { 1772 e_sendAckWithCollectedTokens; 1773 p_informL2AboutTokenLoss; 1774 forward_eviction_to_cpu 1775 l_popPersistentQueue; 1776 } 1777 1778 transition(S, {Persistent_GETS, Persistent_GETS_Last_Token}, S_L) { 1779 f_sendAckWithAllButNorOneTokens; 1780 l_popPersistentQueue; 1781 } 1782 1783 transition(S_L, {Persistent_GETS, Persistent_GETS_Last_Token}) { 1784 l_popPersistentQueue; 1785 } 1786 1787 transition(S, Ack) { 1788 q_updateTokensFromResponse; 1789 n_popResponseQueue; 1790 } 1791 1792 transition(S, Data_Shared) { 1793 w_assertIncomingDataAndCacheDataMatch; 1794 q_updateTokensFromResponse; 1795 n_popResponseQueue; 1796 } 1797 1798 transition(S, Data_Owner, O) { 1799 w_assertIncomingDataAndCacheDataMatch; 1800 q_updateTokensFromResponse; 1801 n_popResponseQueue; 1802 } 1803 1804 transition(S, Data_All_Tokens, M) { 1805 w_assertIncomingDataAndCacheDataMatch; 1806 q_updateTokensFromResponse; 1807 n_popResponseQueue; 1808 } 1809 1810 // Transitions from Owned 1811 transition({O, OM}, Ifetch) { 1812 h_ifetch_hit; 1813 uu_profileInstHit; 1814 k_popMandatoryQueue; 1815 } 1816 1817 transition({O, OM}, Load) { 1818 h_load_hit; 1819 uu_profileDataHit; 1820 k_popMandatoryQueue; 1821 } 1822 1823 transition(O, {Store, Atomic}, OM) { 1824 i_allocateTBE; 1825 b_issueWriteRequest; 1826 uu_profileDataMiss; 1827 k_popMandatoryQueue; 1828 } 1829 1830 transition(O, L1_Replacement, I) { 1831 ta_traceStalledAddress; 1832 c_ownedReplacement; 1833 forward_eviction_to_cpu 1834 gg_deallocateL1CacheBlock; 1835 ka_wakeUpAllDependents; 1836 } 1837 1838 transition(O, {Transient_GETX, Transient_Local_GETX}, I) { 1839 dd_sendDataWithAllTokens; 1840 p_informL2AboutTokenLoss; 1841 forward_eviction_to_cpu 1842 m_popRequestQueue; 1843 } 1844 1845 transition(O, Persistent_GETX, I_L) { 1846 ee_sendDataWithAllTokens; 1847 p_informL2AboutTokenLoss; 1848 forward_eviction_to_cpu 1849 l_popPersistentQueue; 1850 } 1851 1852 transition(O, Persistent_GETS, S_L) { 1853 ff_sendDataWithAllButNorOneTokens; 1854 l_popPersistentQueue; 1855 } 1856 1857 transition(O, Persistent_GETS_Last_Token, I_L) { 1858 fo_sendDataWithOwnerToken; 1859 forward_eviction_to_cpu 1860 l_popPersistentQueue; 1861 } 1862 1863 transition(O, Transient_GETS) { 1864 d_sendDataWithToken; 1865 m_popRequestQueue; 1866 } 1867 1868 transition(O, Transient_Local_GETS) { 1869 d_sendDataWithToken; 1870 m_popRequestQueue; 1871 } 1872 1873 // ran out of tokens, wait for it to go persistent 1874 transition(O, {Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token}) { 1875 m_popRequestQueue; 1876 } 1877 1878 transition(O, Ack) { 1879 q_updateTokensFromResponse; 1880 n_popResponseQueue; 1881 } 1882 1883 transition(O, Ack_All_Tokens, M) { 1884 q_updateTokensFromResponse; 1885 n_popResponseQueue; 1886 } 1887 1888 transition(O, Data_Shared) { 1889 w_assertIncomingDataAndCacheDataMatch; 1890 q_updateTokensFromResponse; 1891 n_popResponseQueue; 1892 } 1893 1894 transition(O, Data_All_Tokens, M) { 1895 w_assertIncomingDataAndCacheDataMatch; 1896 q_updateTokensFromResponse; 1897 n_popResponseQueue; 1898 } 1899 1900 // Transitions from Modified 1901 transition({MM, MM_W}, Ifetch) { 1902 h_ifetch_hit; 1903 uu_profileInstHit; 1904 k_popMandatoryQueue; 1905 } 1906 1907 transition({MM, MM_W}, Load) { 1908 h_load_hit; 1909 uu_profileDataHit; 1910 k_popMandatoryQueue; 1911 } 1912 1913 transition({MM_W}, {Store, Atomic}) { 1914 hh_store_hit; 1915 uu_profileDataHit; 1916 k_popMandatoryQueue; 1917 } 1918 1919 transition(MM, Store) { 1920 hh_store_hit; 1921 uu_profileDataHit; 1922 k_popMandatoryQueue; 1923 } 1924 1925 transition(MM, Atomic, M) { 1926 hh_store_hit; 1927 uu_profileDataHit; 1928 k_popMandatoryQueue; 1929 } 1930 1931 transition(MM, L1_Replacement, I) { 1932 ta_traceStalledAddress; 1933 c_ownedReplacement; 1934 forward_eviction_to_cpu 1935 gg_deallocateL1CacheBlock; 1936 ka_wakeUpAllDependents; 1937 } 1938 1939 transition(MM, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_Local_GETS}, I) { 1940 dd_sendDataWithAllTokens; 1941 p_informL2AboutTokenLoss; 1942 forward_eviction_to_cpu 1943 m_popRequestQueue; 1944 } 1945 1946 transition({MM_W}, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_Local_GETS}) { // Ignore the request 1947 m_popRequestQueue; 1948 } 1949 1950 // Implement the migratory sharing optimization, even for persistent requests 1951 transition(MM, {Persistent_GETX, Persistent_GETS}, I_L) { 1952 ee_sendDataWithAllTokens; 1953 p_informL2AboutTokenLoss; 1954 forward_eviction_to_cpu 1955 l_popPersistentQueue; 1956 } 1957 1958 // ignore persistent requests in lockout period 1959 transition(MM_W, {Persistent_GETX, Persistent_GETS}) { 1960 l_popPersistentQueue; 1961 } 1962 1963 transition(MM_W, Use_TimeoutNoStarvers, MM) { 1964 s_deallocateTBE; 1965 jj_unsetUseTimer; 1966 kd_wakeUpDependents; 1967 } 1968 1969 transition(MM_W, Use_TimeoutNoStarvers_NoMig, M) { 1970 s_deallocateTBE; 1971 jj_unsetUseTimer; 1972 kd_wakeUpDependents; 1973 } 1974 1975 // Transitions from Dirty Exclusive 1976 transition({M, M_W}, Ifetch) { 1977 h_ifetch_hit; 1978 uu_profileInstHit; 1979 k_popMandatoryQueue; 1980 } 1981 1982 transition({M, M_W}, Load) { 1983 h_load_hit; 1984 uu_profileDataHit; 1985 k_popMandatoryQueue; 1986 } 1987 1988 transition(M, Store, MM) { 1989 hh_store_hit; 1990 uu_profileDataHit; 1991 k_popMandatoryQueue; 1992 } 1993 1994 transition(M, Atomic) { 1995 hh_store_hit; 1996 uu_profileDataHit; 1997 k_popMandatoryQueue; 1998 } 1999 2000 transition(M_W, Store, MM_W) { 2001 hh_store_hit; 2002 uu_profileDataHit; 2003 k_popMandatoryQueue; 2004 } 2005 2006 transition(M_W, Atomic) { 2007 hh_store_hit; 2008 uu_profileDataHit; 2009 k_popMandatoryQueue; 2010 } 2011 2012 transition(M, L1_Replacement, I) { 2013 ta_traceStalledAddress; 2014 c_ownedReplacement; 2015 forward_eviction_to_cpu 2016 gg_deallocateL1CacheBlock; 2017 ka_wakeUpAllDependents; 2018 } 2019 2020 transition(M, {Transient_GETX, Transient_Local_GETX}, I) { 2021 dd_sendDataWithAllTokens; 2022 p_informL2AboutTokenLoss; 2023 forward_eviction_to_cpu 2024 m_popRequestQueue; 2025 } 2026 2027 transition(M, Transient_Local_GETS, O) { 2028 d_sendDataWithToken; 2029 m_popRequestQueue; 2030 } 2031 2032 transition(M, Transient_GETS, O) { 2033 d_sendDataWithNTokenIfAvail; 2034 m_popRequestQueue; 2035 } 2036 2037 transition(M_W, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_Local_GETS}) { // Ignore the request 2038 m_popRequestQueue; 2039 } 2040 2041 transition(M, Persistent_GETX, I_L) { 2042 ee_sendDataWithAllTokens; 2043 p_informL2AboutTokenLoss; 2044 forward_eviction_to_cpu 2045 l_popPersistentQueue; 2046 } 2047 2048 transition(M, Persistent_GETS, S_L) { 2049 ff_sendDataWithAllButNorOneTokens; 2050 l_popPersistentQueue; 2051 } 2052 2053 // ignore persistent requests in lockout period 2054 transition(M_W, {Persistent_GETX, Persistent_GETS}) { 2055 l_popPersistentQueue; 2056 } 2057 2058 transition(M_W, Use_TimeoutStarverS, S_L) { 2059 s_deallocateTBE; 2060 ff_sendDataWithAllButNorOneTokens; 2061 jj_unsetUseTimer; 2062 } 2063 2064 // someone unlocked during timeout 2065 transition(M_W, {Use_TimeoutNoStarvers, Use_TimeoutNoStarvers_NoMig}, M) { 2066 s_deallocateTBE; 2067 jj_unsetUseTimer; 2068 kd_wakeUpDependents; 2069 } 2070 2071 transition(M_W, Use_TimeoutStarverX, I_L) { 2072 s_deallocateTBE; 2073 ee_sendDataWithAllTokens; 2074 forward_eviction_to_cpu; 2075 p_informL2AboutTokenLoss; 2076 jj_unsetUseTimer; 2077 } 2078 2079 // migratory 2080 transition(MM_W, {Use_TimeoutStarverX, Use_TimeoutStarverS}, I_L) { 2081 s_deallocateTBE; 2082 ee_sendDataWithAllTokens; 2083 forward_eviction_to_cpu; 2084 p_informL2AboutTokenLoss; 2085 jj_unsetUseTimer; 2086 2087 } 2088 2089 // Transient_GETX and Transient_GETS in transient states 2090 transition(OM, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS}) { 2091 m_popRequestQueue; // Even if we have the data, we can pretend we don't have it yet. 2092 } 2093 2094 transition(IS, {Transient_GETX, Transient_Local_GETX}) { 2095 t_sendAckWithCollectedTokens; 2096 m_popRequestQueue; 2097 } 2098 2099 transition(IS, {Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS}) { 2100 m_popRequestQueue; 2101 } 2102 2103 transition(IS, {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, IS_L) { 2104 e_sendAckWithCollectedTokens; 2105 l_popPersistentQueue; 2106 } 2107 2108 transition(IS_L, {Persistent_GETX, Persistent_GETS}) { 2109 l_popPersistentQueue; 2110 } 2111 2112 transition(IM, {Persistent_GETX, Persistent_GETS, Persistent_GETS_Last_Token}, IM_L) { 2113 e_sendAckWithCollectedTokens; 2114 l_popPersistentQueue; 2115 } 2116 2117 transition(IM_L, {Persistent_GETX, Persistent_GETS}) { 2118 l_popPersistentQueue; 2119 } 2120 2121 transition({SM, SM_L}, Persistent_GETX, IM_L) { 2122 e_sendAckWithCollectedTokens; 2123 forward_eviction_to_cpu 2124 l_popPersistentQueue; 2125 } 2126 2127 transition(SM, {Persistent_GETS, Persistent_GETS_Last_Token}, SM_L) { 2128 f_sendAckWithAllButNorOneTokens; 2129 l_popPersistentQueue; 2130 } 2131 2132 transition(SM_L, {Persistent_GETS, Persistent_GETS_Last_Token}) { 2133 l_popPersistentQueue; 2134 } 2135 2136 transition(OM, Persistent_GETX, IM_L) { 2137 ee_sendDataWithAllTokens; 2138 forward_eviction_to_cpu 2139 l_popPersistentQueue; 2140 } 2141 2142 transition(OM, Persistent_GETS, SM_L) { 2143 ff_sendDataWithAllButNorOneTokens; 2144 l_popPersistentQueue; 2145 } 2146 2147 transition(OM, Persistent_GETS_Last_Token, IM_L) { 2148 fo_sendDataWithOwnerToken; 2149 l_popPersistentQueue; 2150 } 2151 2152 // Transitions from IM/SM 2153 2154 transition({IM, SM}, Ack) { 2155 q_updateTokensFromResponse; 2156 n_popResponseQueue; 2157 } 2158 2159 transition(IM, Data_Shared, SM) { 2160 u_writeDataToCache; 2161 q_updateTokensFromResponse; 2162 n_popResponseQueue; 2163 } 2164 2165 transition(IM, Data_Owner, OM) { 2166 u_writeDataToCache; 2167 q_updateTokensFromResponse; 2168 n_popResponseQueue; 2169 } 2170 2171 transition(IM, Data_All_Tokens, MM_W) { 2172 u_writeDataToCache; 2173 q_updateTokensFromResponse; 2174 xx_external_store_hit; 2175 o_scheduleUseTimeout; 2176 j_unsetReissueTimer; 2177 n_popResponseQueue; 2178 kd_wakeUpDependents; 2179 } 2180 2181 transition(SM, Data_Shared) { 2182 w_assertIncomingDataAndCacheDataMatch; 2183 q_updateTokensFromResponse; 2184 n_popResponseQueue; 2185 } 2186 2187 transition(SM, Data_Owner, OM) { 2188 w_assertIncomingDataAndCacheDataMatch; 2189 q_updateTokensFromResponse; 2190 n_popResponseQueue; 2191 } 2192 2193 transition(SM, Data_All_Tokens, MM_W) { 2194 w_assertIncomingDataAndCacheDataMatch; 2195 q_updateTokensFromResponse; 2196 xx_external_store_hit; 2197 o_scheduleUseTimeout; 2198 j_unsetReissueTimer; 2199 n_popResponseQueue; 2200 kd_wakeUpDependents; 2201 } 2202 2203 transition({IM, SM}, {Transient_GETX, Transient_Local_GETX}, IM) { // We don't have the data yet, but we might have collected some tokens. We give them up here to avoid livelock 2204 t_sendAckWithCollectedTokens; 2205 forward_eviction_to_cpu; 2206 m_popRequestQueue; 2207 } 2208 2209 transition({IM, SM}, {Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS}) { 2210 m_popRequestQueue; 2211 } 2212 2213 transition({IM, SM}, Request_Timeout) { 2214 j_unsetReissueTimer; 2215 b_issueWriteRequest; 2216 } 2217 2218 // Transitions from OM 2219 2220 transition(OM, Ack) { 2221 q_updateTokensFromResponse; 2222 n_popResponseQueue; 2223 } 2224 2225 transition(OM, Ack_All_Tokens, MM_W) { 2226 q_updateTokensFromResponse; 2227 xx_external_store_hit; 2228 o_scheduleUseTimeout; 2229 j_unsetReissueTimer; 2230 n_popResponseQueue; 2231 kd_wakeUpDependents; 2232 } 2233 2234 transition(OM, Data_Shared) { 2235 w_assertIncomingDataAndCacheDataMatch; 2236 q_updateTokensFromResponse; 2237 n_popResponseQueue; 2238 } 2239 2240 transition(OM, Data_All_Tokens, MM_W) { 2241 w_assertIncomingDataAndCacheDataMatch; 2242 q_updateTokensFromResponse; 2243 xx_external_store_hit; 2244 o_scheduleUseTimeout; 2245 j_unsetReissueTimer; 2246 n_popResponseQueue; 2247 kd_wakeUpDependents; 2248 } 2249 2250 transition(OM, Request_Timeout) { 2251 j_unsetReissueTimer; 2252 b_issueWriteRequest; 2253 } 2254 2255 // Transitions from IS 2256 2257 transition(IS, Ack) { 2258 q_updateTokensFromResponse; 2259 n_popResponseQueue; 2260 } 2261 2262 transition(IS, Data_Shared, S) { 2263 u_writeDataToCache; 2264 q_updateTokensFromResponse; 2265 x_external_load_hit; 2266 s_deallocateTBE; 2267 j_unsetReissueTimer; 2268 n_popResponseQueue; 2269 kd_wakeUpDependents; 2270 } 2271 2272 transition(IS, Data_Owner, O) { 2273 u_writeDataToCache; 2274 q_updateTokensFromResponse; 2275 x_external_load_hit; 2276 s_deallocateTBE; 2277 j_unsetReissueTimer; 2278 n_popResponseQueue; 2279 kd_wakeUpDependents; 2280 } 2281 2282 transition(IS, Data_All_Tokens, M_W) { 2283 u_writeDataToCache; 2284 q_updateTokensFromResponse; 2285 x_external_load_hit; 2286 o_scheduleUseTimeout; 2287 j_unsetReissueTimer; 2288 n_popResponseQueue; 2289 kd_wakeUpDependents; 2290 } 2291 2292 transition(IS, Request_Timeout) { 2293 j_unsetReissueTimer; 2294 a_issueReadRequest; 2295 } 2296 2297 // Transitions from I_L 2298 2299 transition(I_L, Load, IS_L) { 2300 ii_allocateL1DCacheBlock; 2301 i_allocateTBE; 2302 a_issueReadRequest; 2303 uu_profileDataMiss; 2304 k_popMandatoryQueue; 2305 } 2306 2307 transition(I_L, Ifetch, IS_L) { 2308 pp_allocateL1ICacheBlock; 2309 i_allocateTBE; 2310 a_issueReadRequest; 2311 uu_profileInstMiss; 2312 k_popMandatoryQueue; 2313 } 2314 2315 transition(I_L, {Store, Atomic}, IM_L) { 2316 ii_allocateL1DCacheBlock; 2317 i_allocateTBE; 2318 b_issueWriteRequest; 2319 uu_profileDataMiss; 2320 k_popMandatoryQueue; 2321 } 2322 2323 2324 // Transitions from S_L 2325 2326 transition(S_L, {Store, Atomic}, SM_L) { 2327 i_allocateTBE; 2328 b_issueWriteRequest; 2329 uu_profileDataMiss; 2330 k_popMandatoryQueue; 2331 } 2332 2333 // Other transitions from *_L states 2334 2335 transition({I_L, IM_L, IS_L, S_L, SM_L}, {Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS, Transient_GETX, Transient_Local_GETX}) { 2336 m_popRequestQueue; 2337 } 2338 2339 transition({I_L, IM_L, IS_L, S_L, SM_L}, Ack) { 2340 g_bounceResponseToStarver; 2341 n_popResponseQueue; 2342 } 2343 2344 transition({I_L, IM_L, S_L, SM_L}, {Data_Shared, Data_Owner}) { 2345 g_bounceResponseToStarver; 2346 n_popResponseQueue; 2347 } 2348 2349 transition({I_L, S_L}, Data_All_Tokens) { 2350 g_bounceResponseToStarver; 2351 n_popResponseQueue; 2352 } 2353 2354 transition(IS_L, Request_Timeout) { 2355 j_unsetReissueTimer; 2356 a_issueReadRequest; 2357 } 2358 2359 transition({IM_L, SM_L}, Request_Timeout) { 2360 j_unsetReissueTimer; 2361 b_issueWriteRequest; 2362 } 2363 2364 // Opportunisticly Complete the memory operation in the following 2365 // cases. Note: these transitions could just use 2366 // g_bounceResponseToStarver, but if we have the data and tokens, we 2367 // might as well complete the memory request while we have the 2368 // chance (and then immediately forward on the data) 2369 2370 transition(IM_L, Data_All_Tokens, MM_W) { 2371 u_writeDataToCache; 2372 q_updateTokensFromResponse; 2373 xx_external_store_hit; 2374 j_unsetReissueTimer; 2375 o_scheduleUseTimeout; 2376 n_popResponseQueue; 2377 kd_wakeUpDependents; 2378 } 2379 2380 transition(SM_L, Data_All_Tokens, S_L) { 2381 u_writeDataToCache; 2382 q_updateTokensFromResponse; 2383 xx_external_store_hit; 2384 ff_sendDataWithAllButNorOneTokens; 2385 s_deallocateTBE; 2386 j_unsetReissueTimer; 2387 n_popResponseQueue; 2388 } 2389 2390 transition(IS_L, Data_Shared, I_L) { 2391 u_writeDataToCache; 2392 q_updateTokensFromResponse; 2393 x_external_load_hit; 2394 s_deallocateTBE; 2395 e_sendAckWithCollectedTokens; 2396 p_informL2AboutTokenLoss; 2397 j_unsetReissueTimer; 2398 n_popResponseQueue; 2399 } 2400 2401 transition(IS_L, Data_Owner, I_L) { 2402 u_writeDataToCache; 2403 q_updateTokensFromResponse; 2404 x_external_load_hit; 2405 ee_sendDataWithAllTokens; 2406 s_deallocateTBE; 2407 p_informL2AboutTokenLoss; 2408 j_unsetReissueTimer; 2409 n_popResponseQueue; 2410 } 2411 2412 transition(IS_L, Data_All_Tokens, M_W) { 2413 u_writeDataToCache; 2414 q_updateTokensFromResponse; 2415 x_external_load_hit; 2416 j_unsetReissueTimer; 2417 o_scheduleUseTimeout; 2418 n_popResponseQueue; 2419 kd_wakeUpDependents; 2420 } 2421 2422 // Own_Lock_or_Unlock 2423 2424 transition(I_L, Own_Lock_or_Unlock, I) { 2425 l_popPersistentQueue; 2426 kd_wakeUpDependents; 2427 } 2428 2429 transition(S_L, Own_Lock_or_Unlock, S) { 2430 l_popPersistentQueue; 2431 kd_wakeUpDependents; 2432 } 2433 2434 transition(IM_L, Own_Lock_or_Unlock, IM) { 2435 l_popPersistentQueue; 2436 kd_wakeUpDependents; 2437 } 2438 2439 transition(IS_L, Own_Lock_or_Unlock, IS) { 2440 l_popPersistentQueue; 2441 kd_wakeUpDependents; 2442 } 2443 2444 transition(SM_L, Own_Lock_or_Unlock, SM) { 2445 l_popPersistentQueue; 2446 kd_wakeUpDependents; 2447 } 2448} 2449