1/* 2 * Copyright (c) 2010-2015 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * For use for simulation and test purposes only 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Author: Blake Hechtman 34 */ 35 36machine(MachineType:TCC, "TCC Cache") 37 : CacheMemory * L2cache; 38 bool WB; /*is this cache Writeback?*/ 39 Cycles l2_request_latency := 50; 40 Cycles l2_response_latency := 20; 41 42 // From the TCPs or SQCs 43 MessageBuffer * requestFromTCP, network="From", virtual_network="1", vnet_type="request"; 44 // To the Cores. TCC deals only with TCPs/SQCs. 45 MessageBuffer * responseToCore, network="To", virtual_network="3", vnet_type="response"; 46 // From the NB 47 MessageBuffer * probeFromNB, network="From", virtual_network="0", vnet_type="request"; 48 MessageBuffer * responseFromNB, network="From", virtual_network="2", vnet_type="response"; 49 // To the NB 50 MessageBuffer * requestToNB, network="To", virtual_network="0", vnet_type="request"; 51 MessageBuffer * responseToNB, network="To", virtual_network="2", vnet_type="response"; 52 MessageBuffer * unblockToNB, network="To", virtual_network="4", vnet_type="unblock"; 53 54 MessageBuffer * triggerQueue; 55 56{ 57 // EVENTS 58 enumeration(Event, desc="TCC Events") { 59 // Requests coming from the Cores 60 RdBlk, desc="RdBlk event"; 61 WrVicBlk, desc="L1 Write Through"; 62 WrVicBlkBack, desc="L1 Write Through(dirty cache)"; 63 Atomic, desc="Atomic Op"; 64 AtomicDone, desc="AtomicOps Complete"; 65 AtomicNotDone, desc="AtomicOps not Complete"; 66 Data, desc="data messgae"; 67 // Coming from this TCC 68 L2_Repl, desc="L2 Replacement"; 69 // Probes 70 PrbInv, desc="Invalidating probe"; 71 // Coming from Memory Controller 72 WBAck, desc="writethrough ack from memory"; 73 } 74 75 // STATES 76 state_declaration(State, desc="TCC State", default="TCC_State_I") { 77 M, AccessPermission:Read_Write, desc="Modified(dirty cache only)"; 78 W, AccessPermission:Read_Write, desc="Written(dirty cache only)"; 79 V, AccessPermission:Read_Only, desc="Valid"; 80 I, AccessPermission:Invalid, desc="Invalid"; 81 IV, AccessPermission:Busy, desc="Waiting for Data"; 82 WI, AccessPermission:Busy, desc="Waiting on Writethrough Ack"; 83 A, AccessPermission:Busy, desc="Invalid waiting on atomici Data"; 84 } 85 86 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") { 87 DataArrayRead, desc="Read the data array"; 88 DataArrayWrite, desc="Write the data array"; 89 TagArrayRead, desc="Read the data array"; 90 TagArrayWrite, desc="Write the data array"; 91 } 92 93 94 // STRUCTURES 95 96 structure(Entry, desc="...", interface="AbstractCacheEntry") { 97 State CacheState, desc="cache state"; 98 bool Dirty, desc="Is the data dirty (diff from memory?)"; 99 DataBlock DataBlk, desc="Data for the block"; 100 WriteMask writeMask, desc="Dirty byte mask"; 101 } 102 103 structure(TBE, desc="...") { 104 State TBEState, desc="Transient state"; 105 DataBlock DataBlk, desc="data for the block"; 106 bool Dirty, desc="Is the data dirty?"; 107 bool Shared, desc="Victim hit by shared probe"; 108 MachineID From, desc="Waiting for writeback from..."; 109 NetDest Destination, desc="Data destination"; 110 int numAtomics, desc="number remaining atomics"; 111 } 112 113 structure(TBETable, external="yes") { 114 TBE lookup(Addr); 115 void allocate(Addr); 116 void deallocate(Addr); 117 bool isPresent(Addr); 118 } 119 120 TBETable TBEs, template="<TCC_TBE>", constructor="m_number_of_TBEs"; 121 122 void set_cache_entry(AbstractCacheEntry b); 123 void unset_cache_entry(); 124 void set_tbe(TBE b); 125 void unset_tbe(); 126 void wakeUpAllBuffers(); 127 void wakeUpBuffers(Addr a); 128 129 MachineID mapAddressToMachine(Addr addr, MachineType mtype); 130 131 // FUNCTION DEFINITIONS 132 Tick clockEdge(); 133 134 Entry getCacheEntry(Addr addr), return_by_pointer="yes" { 135 return static_cast(Entry, "pointer", L2cache.lookup(addr)); 136 } 137 138 DataBlock getDataBlock(Addr addr), return_by_ref="yes" { 139 return getCacheEntry(addr).DataBlk; 140 } 141 142 bool presentOrAvail(Addr addr) { 143 return L2cache.isTagPresent(addr) || L2cache.cacheAvail(addr); 144 } 145 146 State getState(TBE tbe, Entry cache_entry, Addr addr) { 147 if (is_valid(tbe)) { 148 return tbe.TBEState; 149 } else if (is_valid(cache_entry)) { 150 return cache_entry.CacheState; 151 } 152 return State:I; 153 } 154 155 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) { 156 if (is_valid(tbe)) { 157 tbe.TBEState := state; 158 } 159 160 if (is_valid(cache_entry)) { 161 cache_entry.CacheState := state; 162 } 163 } 164 165 void functionalRead(Addr addr, Packet *pkt) { 166 TBE tbe := TBEs.lookup(addr); 167 if(is_valid(tbe)) { 168 testAndRead(addr, tbe.DataBlk, pkt); 169 } else { 170 functionalMemoryRead(pkt); 171 } 172 } 173 174 int functionalWrite(Addr addr, Packet *pkt) { 175 int num_functional_writes := 0; 176 177 TBE tbe := TBEs.lookup(addr); 178 if(is_valid(tbe)) { 179 num_functional_writes := num_functional_writes + 180 testAndWrite(addr, tbe.DataBlk, pkt); 181 } 182 183 num_functional_writes := num_functional_writes + 184 functionalMemoryWrite(pkt); 185 return num_functional_writes; 186 } 187 188 AccessPermission getAccessPermission(Addr addr) { 189 TBE tbe := TBEs.lookup(addr); 190 if(is_valid(tbe)) { 191 return TCC_State_to_permission(tbe.TBEState); 192 } 193 194 Entry cache_entry := getCacheEntry(addr); 195 if(is_valid(cache_entry)) { 196 return TCC_State_to_permission(cache_entry.CacheState); 197 } 198 199 return AccessPermission:NotPresent; 200 } 201 202 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 203 if (is_valid(cache_entry)) { 204 cache_entry.changePermission(TCC_State_to_permission(state)); 205 } 206 } 207 208 void recordRequestType(RequestType request_type, Addr addr) { 209 if (request_type == RequestType:DataArrayRead) { 210 L2cache.recordRequestType(CacheRequestType:DataArrayRead, addr); 211 } else if (request_type == RequestType:DataArrayWrite) { 212 L2cache.recordRequestType(CacheRequestType:DataArrayWrite, addr); 213 } else if (request_type == RequestType:TagArrayRead) { 214 L2cache.recordRequestType(CacheRequestType:TagArrayRead, addr); 215 } else if (request_type == RequestType:TagArrayWrite) { 216 L2cache.recordRequestType(CacheRequestType:TagArrayWrite, addr); 217 } 218 } 219 220 bool checkResourceAvailable(RequestType request_type, Addr addr) { 221 if (request_type == RequestType:DataArrayRead) { 222 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr); 223 } else if (request_type == RequestType:DataArrayWrite) { 224 return L2cache.checkResourceAvailable(CacheResourceType:DataArray, addr); 225 } else if (request_type == RequestType:TagArrayRead) { 226 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr); 227 } else if (request_type == RequestType:TagArrayWrite) { 228 return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr); 229 } else { 230 error("Invalid RequestType type in checkResourceAvailable"); 231 return true; 232 } 233 } 234 235 236 // ** OUT_PORTS ** 237 238 // Three classes of ports 239 // Class 1: downward facing network links to NB 240 out_port(requestToNB_out, CPURequestMsg, requestToNB); 241 out_port(responseToNB_out, ResponseMsg, responseToNB); 242 out_port(unblockToNB_out, UnblockMsg, unblockToNB); 243 244 // Class 2: upward facing ports to GPU cores 245 out_port(responseToCore_out, ResponseMsg, responseToCore); 246 247 out_port(triggerQueue_out, TriggerMsg, triggerQueue); 248 // 249 // request queue going to NB 250 // 251 252 253// ** IN_PORTS ** 254 in_port(triggerQueue_in, TiggerMsg, triggerQueue) { 255 if (triggerQueue_in.isReady(clockEdge())) { 256 peek(triggerQueue_in, TriggerMsg) { 257 TBE tbe := TBEs.lookup(in_msg.addr); 258 Entry cache_entry := getCacheEntry(in_msg.addr); 259 if (tbe.numAtomics == 0) { 260 trigger(Event:AtomicDone, in_msg.addr, cache_entry, tbe); 261 } else { 262 trigger(Event:AtomicNotDone, in_msg.addr, cache_entry, tbe); 263 } 264 } 265 } 266 } 267 268 269 270 in_port(responseFromNB_in, ResponseMsg, responseFromNB) { 271 if (responseFromNB_in.isReady(clockEdge())) { 272 peek(responseFromNB_in, ResponseMsg, block_on="addr") { 273 TBE tbe := TBEs.lookup(in_msg.addr); 274 Entry cache_entry := getCacheEntry(in_msg.addr); 275 if (in_msg.Type == CoherenceResponseType:NBSysResp) { 276 if(presentOrAvail(in_msg.addr)) { 277 trigger(Event:Data, in_msg.addr, cache_entry, tbe); 278 } else { 279 Addr victim := L2cache.cacheProbe(in_msg.addr); 280 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); 281 } 282 } else if (in_msg.Type == CoherenceResponseType:NBSysWBAck) { 283 trigger(Event:WBAck, in_msg.addr, cache_entry, tbe); 284 } else { 285 error("Unexpected Response Message to Core"); 286 } 287 } 288 } 289 } 290 291 // Finally handling incoming requests (from TCP) and probes (from NB). 292 in_port(probeNetwork_in, NBProbeRequestMsg, probeFromNB) { 293 if (probeNetwork_in.isReady(clockEdge())) { 294 peek(probeNetwork_in, NBProbeRequestMsg) { 295 DPRINTF(RubySlicc, "%s\n", in_msg); 296 Entry cache_entry := getCacheEntry(in_msg.addr); 297 TBE tbe := TBEs.lookup(in_msg.addr); 298 trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe); 299 } 300 } 301 } 302 303 in_port(coreRequestNetwork_in, CPURequestMsg, requestFromTCP, rank=0) { 304 if (coreRequestNetwork_in.isReady(clockEdge())) { 305 peek(coreRequestNetwork_in, CPURequestMsg) { 306 TBE tbe := TBEs.lookup(in_msg.addr); 307 Entry cache_entry := getCacheEntry(in_msg.addr); 308 if (in_msg.Type == CoherenceRequestType:WriteThrough) { 309 if(WB) { 310 if(presentOrAvail(in_msg.addr)) { 311 trigger(Event:WrVicBlkBack, in_msg.addr, cache_entry, tbe); 312 } else { 313 Addr victim := L2cache.cacheProbe(in_msg.addr); 314 trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); 315 } 316 } else { 317 trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe); 318 } 319 } else if (in_msg.Type == CoherenceRequestType:Atomic) { 320 trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); 321 } else if (in_msg.Type == CoherenceRequestType:RdBlk) { 322 trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe); 323 } else { 324 DPRINTF(RubySlicc, "%s\n", in_msg); 325 error("Unexpected Response Message to Core"); 326 } 327 } 328 } 329 } 330 // BEGIN ACTIONS 331 332 action(i_invL2, "i", desc="invalidate TCC cache block") { 333 if (is_valid(cache_entry)) { 334 L2cache.deallocate(address); 335 } 336 unset_cache_entry(); 337 } 338 339 action(sd_sendData, "sd", desc="send Shared response") { 340 peek(coreRequestNetwork_in, CPURequestMsg) { 341 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { 342 out_msg.addr := address; 343 out_msg.Type := CoherenceResponseType:TDSysResp; 344 out_msg.Sender := machineID; 345 out_msg.Destination.add(in_msg.Requestor); 346 out_msg.DataBlk := cache_entry.DataBlk; 347 out_msg.MessageSize := MessageSizeType:Response_Data; 348 out_msg.Dirty := false; 349 out_msg.State := CoherenceState:Shared; 350 DPRINTF(RubySlicc, "%s\n", out_msg); 351 } 352 } 353 } 354 355 356 action(sdr_sendDataResponse, "sdr", desc="send Shared response") { 357 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { 358 out_msg.addr := address; 359 out_msg.Type := CoherenceResponseType:TDSysResp; 360 out_msg.Sender := machineID; 361 out_msg.Destination := tbe.Destination; 362 out_msg.DataBlk := cache_entry.DataBlk; 363 out_msg.MessageSize := MessageSizeType:Response_Data; 364 out_msg.Dirty := false; 365 out_msg.State := CoherenceState:Shared; 366 DPRINTF(RubySlicc, "%s\n", out_msg); 367 } 368 enqueue(unblockToNB_out, UnblockMsg, 1) { 369 out_msg.addr := address; 370 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 371 out_msg.MessageSize := MessageSizeType:Unblock_Control; 372 DPRINTF(RubySlicc, "%s\n", out_msg); 373 } 374 } 375 376 377 action(rd_requestData, "r", desc="Miss in L2, pass on") { 378 if(tbe.Destination.count()==1){ 379 peek(coreRequestNetwork_in, CPURequestMsg) { 380 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { 381 out_msg.addr := address; 382 out_msg.Type := in_msg.Type; 383 out_msg.Requestor := machineID; 384 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 385 out_msg.Shared := false; // unneeded for this request 386 out_msg.MessageSize := in_msg.MessageSize; 387 DPRINTF(RubySlicc, "%s\n", out_msg); 388 } 389 } 390 } 391 } 392 393 action(w_sendResponseWBAck, "w", desc="send WB Ack") { 394 peek(responseFromNB_in, ResponseMsg) { 395 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { 396 out_msg.addr := address; 397 out_msg.Type := CoherenceResponseType:TDSysWBAck; 398 out_msg.Destination.clear(); 399 out_msg.Destination.add(in_msg.WTRequestor); 400 out_msg.Sender := machineID; 401 out_msg.MessageSize := MessageSizeType:Writeback_Control; 402 } 403 } 404 } 405 406 action(swb_sendWBAck, "swb", desc="send WB Ack") { 407 peek(coreRequestNetwork_in, CPURequestMsg) { 408 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { 409 out_msg.addr := address; 410 out_msg.Type := CoherenceResponseType:TDSysWBAck; 411 out_msg.Destination.clear(); 412 out_msg.Destination.add(in_msg.Requestor); 413 out_msg.Sender := machineID; 414 out_msg.MessageSize := MessageSizeType:Writeback_Control; 415 } 416 } 417 } 418 419 action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") { 420 peek(responseFromNB_in, ResponseMsg) { 421 enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { 422 out_msg.addr := address; 423 out_msg.Type := CoherenceResponseType:TDSysResp; 424 out_msg.Destination.add(in_msg.WTRequestor); 425 out_msg.Sender := machineID; 426 out_msg.MessageSize := in_msg.MessageSize; 427 out_msg.DataBlk := in_msg.DataBlk; 428 } 429 } 430 } 431 432 action(a_allocateBlock, "a", desc="allocate TCC block") { 433 if (is_invalid(cache_entry)) { 434 set_cache_entry(L2cache.allocate(address, new Entry)); 435 cache_entry.writeMask.clear(); 436 } 437 } 438 439 action(t_allocateTBE, "t", desc="allocate TBE Entry") { 440 if (is_invalid(tbe)) { 441 check_allocate(TBEs); 442 TBEs.allocate(address); 443 set_tbe(TBEs.lookup(address)); 444 tbe.Destination.clear(); 445 tbe.numAtomics := 0; 446 } 447 if (coreRequestNetwork_in.isReady(clockEdge())) { 448 peek(coreRequestNetwork_in, CPURequestMsg) { 449 if(in_msg.Type == CoherenceRequestType:RdBlk || in_msg.Type == CoherenceRequestType:Atomic){ 450 tbe.Destination.add(in_msg.Requestor); 451 } 452 } 453 } 454 } 455 456 action(dt_deallocateTBE, "dt", desc="Deallocate TBE entry") { 457 tbe.Destination.clear(); 458 TBEs.deallocate(address); 459 unset_tbe(); 460 } 461 462 action(wcb_writeCacheBlock, "wcb", desc="write data to TCC") { 463 peek(responseFromNB_in, ResponseMsg) { 464 cache_entry.DataBlk := in_msg.DataBlk; 465 DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg); 466 } 467 } 468 469 action(wdb_writeDirtyBytes, "wdb", desc="write data to TCC") { 470 peek(coreRequestNetwork_in, CPURequestMsg) { 471 cache_entry.DataBlk.copyPartial(in_msg.DataBlk,in_msg.writeMask); 472 cache_entry.writeMask.orMask(in_msg.writeMask); 473 DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg); 474 } 475 } 476 477 action(wt_writeThrough, "wt", desc="write back data") { 478 peek(coreRequestNetwork_in, CPURequestMsg) { 479 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { 480 out_msg.addr := address; 481 out_msg.Requestor := machineID; 482 out_msg.WTRequestor := in_msg.Requestor; 483 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 484 out_msg.MessageSize := MessageSizeType:Data; 485 out_msg.Type := CoherenceRequestType:WriteThrough; 486 out_msg.Dirty := true; 487 out_msg.DataBlk := in_msg.DataBlk; 488 out_msg.writeMask.orMask(in_msg.writeMask); 489 } 490 } 491 } 492 493 action(wb_writeBack, "wb", desc="write back data") { 494 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { 495 out_msg.addr := address; 496 out_msg.Requestor := machineID; 497 out_msg.WTRequestor := machineID; 498 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 499 out_msg.MessageSize := MessageSizeType:Data; 500 out_msg.Type := CoherenceRequestType:WriteThrough; 501 out_msg.Dirty := true; 502 out_msg.DataBlk := cache_entry.DataBlk; 503 out_msg.writeMask.orMask(cache_entry.writeMask); 504 } 505 } 506 507 action(at_atomicThrough, "at", desc="write back data") { 508 peek(coreRequestNetwork_in, CPURequestMsg) { 509 enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { 510 out_msg.addr := address; 511 out_msg.Requestor := machineID; 512 out_msg.WTRequestor := in_msg.Requestor; 513 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 514 out_msg.MessageSize := MessageSizeType:Data; 515 out_msg.Type := CoherenceRequestType:Atomic; 516 out_msg.Dirty := true; 517 out_msg.writeMask.orMask(in_msg.writeMask); 518 } 519 } 520 } 521 522 action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") { 523 enqueue(responseToNB_out, ResponseMsg, 1) { 524 out_msg.addr := address; 525 out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes 526 out_msg.Sender := machineID; 527 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 528 out_msg.Dirty := false; 529 out_msg.Hit := false; 530 out_msg.Ntsl := true; 531 out_msg.State := CoherenceState:NA; 532 out_msg.MessageSize := MessageSizeType:Response_Control; 533 } 534 } 535 action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") { 536 L2cache.setMRU(address); 537 } 538 539 action(p_popRequestQueue, "p", desc="pop request queue") { 540 coreRequestNetwork_in.dequeue(clockEdge()); 541 } 542 543 action(pr_popResponseQueue, "pr", desc="pop response queue") { 544 responseFromNB_in.dequeue(clockEdge()); 545 } 546 547 action(pp_popProbeQueue, "pp", desc="pop probe queue") { 548 probeNetwork_in.dequeue(clockEdge()); 549 } 550 551 action(z_stall, "z", desc="stall") { 552 // built-in 553 } 554 555 556 action(ina_incrementNumAtomics, "ina", desc="inc num atomics") { 557 tbe.numAtomics := tbe.numAtomics + 1; 558 } 559 560 561 action(dna_decrementNumAtomics, "dna", desc="inc num atomics") { 562 tbe.numAtomics := tbe.numAtomics - 1; 563 if (tbe.numAtomics==0) { 564 enqueue(triggerQueue_out, TriggerMsg, 1) { 565 out_msg.addr := address; 566 out_msg.Type := TriggerType:AtomicDone; 567 } 568 } 569 } 570 571 action(ptr_popTriggerQueue, "ptr", desc="pop Trigger") { 572 triggerQueue_in.dequeue(clockEdge()); 573 } 574 575 // END ACTIONS 576 577 // BEGIN TRANSITIONS 578 // transitions from base 579 // Assumptions for ArrayRead/Write 580 // TBE checked before tags 581 // Data Read/Write requires Tag Read 582 583 // Stalling transitions do NOT check the tag array...and if they do, 584 // they can cause a resource stall deadlock! 585 586 transition(WI, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { 587 z_stall; 588 } 589 transition(A, {RdBlk, WrVicBlk, WrVicBlkBack}) { //TagArrayRead} { 590 z_stall; 591 } 592 transition(IV, {WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { 593 z_stall; 594 } 595 transition({M, V}, RdBlk) {TagArrayRead, DataArrayRead} { 596 sd_sendData; 597 ut_updateTag; 598 p_popRequestQueue; 599 } 600 transition(W, RdBlk, WI) {TagArrayRead, DataArrayRead} { 601 t_allocateTBE; 602 wb_writeBack; 603 } 604 605 transition(I, RdBlk, IV) {TagArrayRead} { 606 t_allocateTBE; 607 rd_requestData; 608 p_popRequestQueue; 609 } 610 611 transition(IV, RdBlk) { 612 t_allocateTBE; 613 rd_requestData; 614 p_popRequestQueue; 615 } 616 617 transition({V, I},Atomic, A) {TagArrayRead} { 618 i_invL2; 619 t_allocateTBE; 620 at_atomicThrough; 621 ina_incrementNumAtomics; 622 p_popRequestQueue; 623 } 624 625 transition(A, Atomic) { 626 at_atomicThrough; 627 ina_incrementNumAtomics; 628 p_popRequestQueue; 629 } 630 631 transition({M, W}, Atomic, WI) {TagArrayRead} { 632 t_allocateTBE; 633 wb_writeBack; 634 } 635 636 transition(I, WrVicBlk) {TagArrayRead} { 637 wt_writeThrough; 638 p_popRequestQueue; 639 } 640 641 transition(V, WrVicBlk) {TagArrayRead, DataArrayWrite} { 642 ut_updateTag; 643 wdb_writeDirtyBytes; 644 wt_writeThrough; 645 p_popRequestQueue; 646 } 647 648 transition({V, M}, WrVicBlkBack, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { 649 ut_updateTag; 650 swb_sendWBAck; 651 wdb_writeDirtyBytes; 652 p_popRequestQueue; 653 } 654 655 transition(W, WrVicBlkBack) {TagArrayRead, TagArrayWrite, DataArrayWrite} { 656 ut_updateTag; 657 swb_sendWBAck; 658 wdb_writeDirtyBytes; 659 p_popRequestQueue; 660 } 661 662 transition(I, WrVicBlkBack, W) {TagArrayRead, TagArrayWrite, DataArrayWrite} { 663 a_allocateBlock; 664 ut_updateTag; 665 swb_sendWBAck; 666 wdb_writeDirtyBytes; 667 p_popRequestQueue; 668 } 669 670 transition({W, M}, L2_Repl, WI) {TagArrayRead, DataArrayRead} { 671 t_allocateTBE; 672 wb_writeBack; 673 i_invL2; 674 } 675 676 transition({I, V}, L2_Repl, I) {TagArrayRead, TagArrayWrite} { 677 i_invL2; 678 } 679 680 transition({A, IV, WI}, L2_Repl) { 681 i_invL2; 682 } 683 684 transition({I, V}, PrbInv, I) {TagArrayRead, TagArrayWrite} { 685 pi_sendProbeResponseInv; 686 pp_popProbeQueue; 687 } 688 689 transition(M, PrbInv, W) {TagArrayRead, TagArrayWrite} { 690 pi_sendProbeResponseInv; 691 pp_popProbeQueue; 692 } 693 694 transition(W, PrbInv) {TagArrayRead} { 695 pi_sendProbeResponseInv; 696 pp_popProbeQueue; 697 } 698 699 transition({A, IV, WI}, PrbInv) { 700 pi_sendProbeResponseInv; 701 pp_popProbeQueue; 702 } 703 704 transition(IV, Data, V) {TagArrayRead, TagArrayWrite, DataArrayWrite} { 705 a_allocateBlock; 706 ut_updateTag; 707 wcb_writeCacheBlock; 708 sdr_sendDataResponse; 709 pr_popResponseQueue; 710 dt_deallocateTBE; 711 } 712 713 transition(A, Data) {TagArrayRead, TagArrayWrite, DataArrayWrite} { 714 a_allocateBlock; 715 ar_sendAtomicResponse; 716 dna_decrementNumAtomics; 717 pr_popResponseQueue; 718 } 719 720 transition(A, AtomicDone, I) {TagArrayRead, TagArrayWrite} { 721 dt_deallocateTBE; 722 ptr_popTriggerQueue; 723 } 724 725 transition(A, AtomicNotDone) {TagArrayRead} { 726 ptr_popTriggerQueue; 727 } 728 729 //M,W should not see WBAck as the cache is in WB mode 730 //WBAcks do not need to check tags 731 transition({I, V, IV, A}, WBAck) { 732 w_sendResponseWBAck; 733 pr_popResponseQueue; 734 } 735 736 transition(WI, WBAck,I) { 737 dt_deallocateTBE; 738 pr_popResponseQueue; 739 } 740} 741