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 * Authors: Lisa Hsu 34 */ 35 36machine(MachineType:L3Cache, "L3") 37 : CacheMemory * L3cache; 38 WireBuffer * reqToDir; 39 WireBuffer * respToDir; 40 WireBuffer * l3UnblockToDir; 41 WireBuffer * reqToL3; 42 WireBuffer * probeToL3; 43 WireBuffer * respToL3; 44 Cycles l3_request_latency := 1; 45 Cycles l3_response_latency := 35; 46 47 // To the general response network 48 MessageBuffer * responseFromL3, network="To", virtual_network="2", ordered="false", vnet_type="response"; 49 50 // From the general response network 51 MessageBuffer * responseToL3, network="From", virtual_network="2", ordered="false", vnet_type="response"; 52 53{ 54 // EVENTS 55 enumeration(Event, desc="L3 Events") { 56 // Requests coming from the Cores 57 RdBlk, desc="CPU RdBlk event"; 58 RdBlkM, desc="CPU RdBlkM event"; 59 RdBlkS, desc="CPU RdBlkS event"; 60 CtoD, desc="Change to Dirty request"; 61 WrVicBlk, desc="L2 Victim (dirty)"; 62 WrVicBlkShared, desc="L2 Victim (dirty)"; 63 ClVicBlk, desc="L2 Victim (clean)"; 64 ClVicBlkShared, desc="L2 Victim (clean)"; 65 66 CPUData, desc="WB data from CPU"; 67 CPUDataShared, desc="WB data from CPU, NBReqShared 1"; 68 StaleWB, desc="WB stale; no data"; 69 70 L3_Repl, desc="L3 Replacement"; 71 72 // Probes 73 PrbInvData, desc="Invalidating probe, return dirty data"; 74 PrbInv, desc="Invalidating probe, no need to return data"; 75 PrbShrData, desc="Downgrading probe, return data"; 76 77 // Coming from Memory Controller 78 WBAck, desc="ack from memory"; 79 80 CancelWB, desc="Cancel WB from L2"; 81 } 82 83 // STATES 84 // Base States: 85 state_declaration(State, desc="L3 State", default="L3Cache_State_I") { 86 M, AccessPermission:Read_Write, desc="Modified"; // No other cache has copy, memory stale 87 O, AccessPermission:Read_Only, desc="Owned"; // Correct most recent copy, others may exist in S 88 E, AccessPermission:Read_Write, desc="Exclusive"; // Correct, most recent, and only copy (and == Memory) 89 S, AccessPermission:Read_Only, desc="Shared"; // Correct, most recent. If no one in O, then == Memory 90 I, AccessPermission:Invalid, desc="Invalid"; 91 92 I_M, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data"; 93 I_O, AccessPermission:Busy, desc="Invalid, received WrVicBlk, sent Ack, waiting for Data"; 94 I_E, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data"; 95 I_S, AccessPermission:Busy, desc="Invalid, receive ClVicBlk, sent Ack, waiting for Data"; 96 S_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to M"; 97 S_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O"; 98 S_E, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to E"; 99 S_S, AccessPermission:Busy, desc="Shared, received ClVicBlk, sent Ack, waiting for Data, then go to S"; 100 E_M, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O"; 101 E_O, AccessPermission:Busy, desc="received WrVicBlkShared, sent Ack, waiting for Data, then go to O"; 102 E_E, AccessPermission:Busy, desc="received WrVicBlk, sent Ack, waiting for Data, then go to O"; 103 E_S, AccessPermission:Busy, desc="Shared, received WrVicBlk, sent Ack, waiting for Data"; 104 O_M, AccessPermission:Busy, desc="..."; 105 O_O, AccessPermission:Busy, desc="..."; 106 O_E, AccessPermission:Busy, desc="..."; 107 O_S, AccessPermission:Busy, desc="..."; 108 M_M, AccessPermission:Busy, desc="..."; 109 M_O, AccessPermission:Busy, desc="..."; 110 M_E, AccessPermission:Busy, desc="..."; 111 M_S, AccessPermission:Busy, desc="..."; 112 D_I, AccessPermission:Invalid, desc="drop WB data on the floor when receive"; 113 MOD_I, AccessPermission:Busy, desc="drop WB data on the floor, waiting for WBAck from Mem"; 114 MO_I, AccessPermission:Busy, desc="M or O, received L3_Repl, waiting for WBAck from Mem"; 115 I_I, AccessPermission:Busy, desc="I_MO received L3_Repl"; 116 I_CD, AccessPermission:Busy, desc="I_I received WBAck, now just waiting for CPUData"; 117 I_C, AccessPermission:Invalid, desc="sent cancel, just waiting to receive mem wb ack so nothing gets confused"; 118 } 119 120 enumeration(RequestType, desc="To communicate stats from transitions to recordStats") { 121 DataArrayRead, desc="Read the data array"; 122 DataArrayWrite, desc="Write the data array"; 123 TagArrayRead, desc="Read the data array"; 124 TagArrayWrite, desc="Write the data array"; 125 } 126 127 // STRUCTURES 128 129 structure(Entry, desc="...", interface="AbstractCacheEntry") { 130 State CacheState, desc="cache state"; 131 bool Dirty, desc="Is the data dirty (diff from memory?)"; 132 DataBlock DataBlk, desc="Data for the block"; 133 } 134 135 structure(TBE, desc="...") { 136 State TBEState, desc="Transient state"; 137 DataBlock DataBlk, desc="data for the block"; 138 bool Dirty, desc="Is the data dirty?"; 139 bool Shared, desc="Victim hit by shared probe"; 140 MachineID From, desc="Waiting for writeback from..."; 141 } 142 143 structure(TBETable, external="yes") { 144 TBE lookup(Addr); 145 void allocate(Addr); 146 void deallocate(Addr); 147 bool isPresent(Addr); 148 } 149 150 TBETable TBEs, template="<L3Cache_TBE>", constructor="m_number_of_TBEs"; 151 152 void set_cache_entry(AbstractCacheEntry b); 153 void unset_cache_entry(); 154 void set_tbe(TBE b); 155 void unset_tbe(); 156 void wakeUpAllBuffers(); 157 void wakeUpBuffers(Addr a); 158 MachineID mapAddressToMachine(Addr addr, MachineType mtype); 159 160 // FUNCTION DEFINITIONS 161 Tick clockEdge(); 162 Tick cyclesToTicks(Cycles c); 163 164 Entry getCacheEntry(Addr addr), return_by_pointer="yes" { 165 return static_cast(Entry, "pointer", L3cache.lookup(addr)); 166 } 167 168 DataBlock getDataBlock(Addr addr), return_by_ref="yes" { 169 return getCacheEntry(addr).DataBlk; 170 } 171 172 bool presentOrAvail(Addr addr) { 173 return L3cache.isTagPresent(addr) || L3cache.cacheAvail(addr); 174 } 175 176 State getState(TBE tbe, Entry cache_entry, Addr addr) { 177 if (is_valid(tbe)) { 178 return tbe.TBEState; 179 } else if (is_valid(cache_entry)) { 180 return cache_entry.CacheState; 181 } 182 return State:I; 183 } 184 185 void setState(TBE tbe, Entry cache_entry, Addr addr, State state) { 186 if (is_valid(tbe)) { 187 tbe.TBEState := state; 188 } 189 190 if (is_valid(cache_entry)) { 191 cache_entry.CacheState := state; 192 } 193 } 194 195 void functionalRead(Addr addr, Packet *pkt) { 196 TBE tbe := TBEs.lookup(addr); 197 if(is_valid(tbe)) { 198 testAndRead(addr, tbe.DataBlk, pkt); 199 } else { 200 functionalMemoryRead(pkt); 201 } 202 } 203 204 int functionalWrite(Addr addr, Packet *pkt) { 205 int num_functional_writes := 0; 206 207 TBE tbe := TBEs.lookup(addr); 208 if(is_valid(tbe)) { 209 num_functional_writes := num_functional_writes + 210 testAndWrite(addr, tbe.DataBlk, pkt); 211 } 212 213 num_functional_writes := num_functional_writes + 214 functionalMemoryWrite(pkt); 215 return num_functional_writes; 216 } 217 218 AccessPermission getAccessPermission(Addr addr) { 219 TBE tbe := TBEs.lookup(addr); 220 if(is_valid(tbe)) { 221 return L3Cache_State_to_permission(tbe.TBEState); 222 } 223 224 Entry cache_entry := getCacheEntry(addr); 225 if(is_valid(cache_entry)) { 226 return L3Cache_State_to_permission(cache_entry.CacheState); 227 } 228 229 return AccessPermission:NotPresent; 230 } 231 232 void setAccessPermission(Entry cache_entry, Addr addr, State state) { 233 if (is_valid(cache_entry)) { 234 cache_entry.changePermission(L3Cache_State_to_permission(state)); 235 } 236 } 237 238 void recordRequestType(RequestType request_type, Addr addr) { 239 240 } 241 242 bool checkResourceAvailable(RequestType request_type, Addr addr) { 243 return true; 244 } 245 246 247 // OUT PORTS 248 out_port(requestNetwork_out, CPURequestMsg, reqToDir); 249 out_port(L3Resp_out, ResponseMsg, respToDir); 250 out_port(responseNetwork_out, ResponseMsg, responseFromL3); 251 out_port(unblockNetwork_out, UnblockMsg, l3UnblockToDir); 252 253 // IN PORTS 254 in_port(NBResponse_in, ResponseMsg, respToL3) { 255 if (NBResponse_in.isReady(clockEdge())) { 256 peek(NBResponse_in, ResponseMsg) { 257 Entry cache_entry := getCacheEntry(in_msg.addr); 258 TBE tbe := TBEs.lookup(in_msg.addr); 259 if (in_msg.Type == CoherenceResponseType:NBSysWBAck) { 260 trigger(Event:WBAck, in_msg.addr, cache_entry, tbe); 261 } else { 262 DPRINTF(RubySlicc, "%s\n", in_msg); 263 error("Error on NBResponse Type"); 264 } 265 } 266 } 267 } 268 269 // Response Network 270 in_port(responseNetwork_in, ResponseMsg, responseToL3) { 271 if (responseNetwork_in.isReady(clockEdge())) { 272 peek(responseNetwork_in, ResponseMsg) { 273 Entry cache_entry := getCacheEntry(in_msg.addr); 274 TBE tbe := TBEs.lookup(in_msg.addr); 275 if (in_msg.Type == CoherenceResponseType:CPUData) { 276 if (in_msg.NbReqShared) { 277 trigger(Event:CPUDataShared, in_msg.addr, cache_entry, tbe); 278 } else { 279 trigger(Event:CPUData, in_msg.addr, cache_entry, tbe); 280 } 281 } else if (in_msg.Type == CoherenceResponseType:StaleNotif) { 282 trigger(Event:StaleWB, in_msg.addr, cache_entry, tbe); 283 } else { 284 DPRINTF(RubySlicc, "%s\n", in_msg); 285 error("Error on NBResponse Type"); 286 } 287 } 288 } 289 } 290 291 // probe network 292 in_port(probeNetwork_in, NBProbeRequestMsg, probeToL3) { 293 if (probeNetwork_in.isReady(clockEdge())) { 294 peek(probeNetwork_in, NBProbeRequestMsg) { 295 Entry cache_entry := getCacheEntry(in_msg.addr); 296 TBE tbe := TBEs.lookup(in_msg.addr); 297 if (in_msg.Type == ProbeRequestType:PrbInv) { 298 if (in_msg.ReturnData) { 299 trigger(Event:PrbInvData, in_msg.addr, cache_entry, tbe); 300 } else { 301 trigger(Event:PrbInv, in_msg.addr, cache_entry, tbe); 302 } 303 } else if (in_msg.Type == ProbeRequestType:PrbDowngrade) { 304 if (in_msg.ReturnData) { 305 trigger(Event:PrbShrData, in_msg.addr, cache_entry, tbe); 306 } else { 307 error("Don't think I should get any of these"); 308 } 309 } 310 } 311 } 312 } 313 314 // Request Network 315 in_port(requestNetwork_in, CPURequestMsg, reqToL3) { 316 if (requestNetwork_in.isReady(clockEdge())) { 317 peek(requestNetwork_in, CPURequestMsg) { 318 assert(in_msg.Destination.isElement(machineID)); 319 Entry cache_entry := getCacheEntry(in_msg.addr); 320 TBE tbe := TBEs.lookup(in_msg.addr); 321 if (in_msg.Type == CoherenceRequestType:RdBlk) { 322 trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe); 323 } else if (in_msg.Type == CoherenceRequestType:RdBlkS) { 324 trigger(Event:RdBlkS, in_msg.addr, cache_entry, tbe); 325 } else if (in_msg.Type == CoherenceRequestType:RdBlkM) { 326 trigger(Event:RdBlkM, in_msg.addr, cache_entry, tbe); 327 } else if (in_msg.Type == CoherenceRequestType:VicClean) { 328 if (presentOrAvail(in_msg.addr)) { 329 if (in_msg.Shared) { 330 trigger(Event:ClVicBlkShared, in_msg.addr, cache_entry, tbe); 331 } else { 332 trigger(Event:ClVicBlk, in_msg.addr, cache_entry, tbe); 333 } 334 } else { 335 Addr victim := L3cache.cacheProbe(in_msg.addr); 336 trigger(Event:L3_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); 337 } 338 } else if (in_msg.Type == CoherenceRequestType:VicDirty) { 339 if (presentOrAvail(in_msg.addr)) { 340 if (in_msg.Shared) { 341 trigger(Event:WrVicBlkShared, in_msg.addr, cache_entry, tbe); 342 } else { 343 trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe); 344 } 345 } else { 346 Addr victim := L3cache.cacheProbe(in_msg.addr); 347 trigger(Event:L3_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); 348 } 349 } else if (in_msg.Type == CoherenceRequestType:WrCancel) { 350 if (is_valid(tbe) && tbe.From == in_msg.Requestor) { 351 trigger(Event:CancelWB, in_msg.addr, cache_entry, tbe); 352 } else { 353 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency)); 354 } 355 } 356 } 357 } 358 } 359 360 // BEGIN ACTIONS 361 362 action(i_invL3, "i", desc="invalidate L3 cache block") { 363 if (is_valid(cache_entry)) { 364 L3cache.deallocate(address); 365 } 366 unset_cache_entry(); 367 } 368 369 action(rm_sendResponseM, "rm", desc="send Modified response") { 370 peek(requestNetwork_in, CPURequestMsg) { 371 enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) { 372 out_msg.addr := address; 373 out_msg.Type := CoherenceResponseType:NBSysResp; 374 out_msg.Sender := machineID; 375 out_msg.Destination.add(in_msg.Requestor); 376 out_msg.DataBlk := cache_entry.DataBlk; 377 out_msg.MessageSize := MessageSizeType:Response_Data; 378 out_msg.Dirty := cache_entry.Dirty; 379 out_msg.State := CoherenceState:Modified; 380 DPRINTF(RubySlicc, "%s\n", out_msg); 381 } 382 } 383 } 384 385 action(rs_sendResponseS, "rs", desc="send Shared response") { 386 peek(requestNetwork_in, CPURequestMsg) { 387 enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) { 388 out_msg.addr := address; 389 out_msg.Type := CoherenceResponseType:NBSysResp; 390 out_msg.Sender := machineID; 391 out_msg.Destination.add(in_msg.Requestor); 392 out_msg.DataBlk := cache_entry.DataBlk; 393 out_msg.MessageSize := MessageSizeType:Response_Data; 394 out_msg.Dirty := cache_entry.Dirty; 395 out_msg.State := CoherenceState:Shared; 396 DPRINTF(RubySlicc, "%s\n", out_msg); 397 } 398 } 399 } 400 401 402 action(r_requestToMem, "r", desc="Miss in L3, pass on") { 403 peek(requestNetwork_in, CPURequestMsg) { 404 enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) { 405 out_msg.addr := address; 406 out_msg.Type := in_msg.Type; 407 out_msg.Requestor := in_msg.Requestor; 408 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 409 out_msg.Shared := false; // unneeded for this request 410 out_msg.MessageSize := in_msg.MessageSize; 411 DPRINTF(RubySlicc, "%s\n", out_msg); 412 } 413 } 414 } 415 416 action(t_allocateTBE, "t", desc="allocate TBE Entry") { 417 TBEs.allocate(address); 418 set_tbe(TBEs.lookup(address)); 419 if (is_valid(cache_entry)) { 420 tbe.DataBlk := cache_entry.DataBlk; // Data only for WBs 421 tbe.Dirty := cache_entry.Dirty; 422 } 423 tbe.From := machineID; 424 } 425 426 action(dt_deallocateTBE, "dt", desc="deallocate TBE Entry") { 427 TBEs.deallocate(address); 428 unset_tbe(); 429 } 430 431 action(vd_vicDirty, "vd", desc="Victimize dirty L3 data") { 432 enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) { 433 out_msg.addr := address; 434 out_msg.Type := CoherenceRequestType:VicDirty; 435 out_msg.Requestor := machineID; 436 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 437 out_msg.MessageSize := MessageSizeType:Request_Control; 438 } 439 } 440 441 action(w_sendResponseWBAck, "w", desc="send WB Ack") { 442 peek(requestNetwork_in, CPURequestMsg) { 443 enqueue(responseNetwork_out, ResponseMsg, l3_response_latency) { 444 out_msg.addr := address; 445 out_msg.Type := CoherenceResponseType:NBSysWBAck; 446 out_msg.Destination.add(in_msg.Requestor); 447 out_msg.Sender := machineID; 448 out_msg.MessageSize := MessageSizeType:Writeback_Control; 449 } 450 } 451 } 452 453 action(pi_sendProbeResponseInv, "pi", desc="send probe ack inv, no data") { 454 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 455 out_msg.addr := address; 456 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes 457 out_msg.Sender := machineID; 458 // will this always be ok? probably not for multisocket 459 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 460 out_msg.Dirty := false; 461 out_msg.Hit := false; 462 out_msg.Ntsl := true; 463 out_msg.State := CoherenceState:NA; 464 out_msg.MessageSize := MessageSizeType:Response_Control; 465 } 466 } 467 468 action(ph_sendProbeResponseHit, "ph", desc="send probe ack, no data") { 469 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 470 out_msg.addr := address; 471 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes 472 out_msg.Sender := machineID; 473 // will this always be ok? probably not for multisocket 474 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 475 out_msg.Dirty := false; 476 out_msg.Hit := true; 477 out_msg.Ntsl := false; 478 out_msg.State := CoherenceState:NA; 479 out_msg.MessageSize := MessageSizeType:Response_Control; 480 } 481 } 482 483 action(pm_sendProbeResponseMiss, "pm", desc="send probe ack, no data") { 484 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 485 out_msg.addr := address; 486 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes 487 out_msg.Sender := machineID; 488 // will this always be ok? probably not for multisocket 489 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 490 out_msg.Dirty := false; 491 out_msg.Hit := false; 492 out_msg.Ntsl := false; 493 out_msg.State := CoherenceState:NA; 494 out_msg.MessageSize := MessageSizeType:Response_Control; 495 } 496 } 497 498 action(pd_sendProbeResponseData, "pd", desc="send probe ack, with data") { 499 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 500 out_msg.addr := address; 501 out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes 502 out_msg.Sender := machineID; 503 // will this always be ok? probably not for multisocket 504 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 505 out_msg.DataBlk := cache_entry.DataBlk; 506 assert(cache_entry.Dirty); 507 out_msg.Dirty := true; 508 out_msg.Hit := true; 509 out_msg.State := CoherenceState:NA; 510 out_msg.MessageSize := MessageSizeType:Response_Data; 511 } 512 } 513 514 action(pdt_sendProbeResponseDataFromTBE, "pdt", desc="send probe ack with data") { 515 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 516 out_msg.addr := address; 517 out_msg.Type := CoherenceResponseType:CPUPrbResp; 518 out_msg.Sender := machineID; 519 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 520 out_msg.DataBlk := tbe.DataBlk; 521 assert(tbe.Dirty); 522 out_msg.Dirty := true; 523 out_msg.Hit := true; 524 out_msg.MessageSize := MessageSizeType:Response_Data; 525 out_msg.State := CoherenceState:NA; 526 DPRINTF(RubySlicc, "%s\n", out_msg); 527 } 528 } 529 530 action(mc_cancelMemWriteback, "mc", desc="send writeback cancel to memory") { 531 enqueue(requestNetwork_out, CPURequestMsg, l3_request_latency) { 532 out_msg.addr := address; 533 out_msg.Type := CoherenceRequestType:WrCancel; 534 out_msg.Requestor := machineID; 535 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 536 out_msg.MessageSize := MessageSizeType:Request_Control; 537 } 538 } 539 540 action(a_allocateBlock, "a", desc="allocate L3 block") { 541 if (is_invalid(cache_entry)) { 542 set_cache_entry(L3cache.allocate(address, new Entry)); 543 } 544 } 545 546 action(d_writeData, "d", desc="write data to L3") { 547 peek(responseNetwork_in, ResponseMsg) { 548 if (in_msg.Dirty) { 549 cache_entry.Dirty := in_msg.Dirty; 550 } 551 cache_entry.DataBlk := in_msg.DataBlk; 552 DPRINTF(RubySlicc, "Writing to L3: %s\n", in_msg); 553 } 554 } 555 556 action(rd_copyDataFromRequest, "rd", desc="write data to L3") { 557 peek(requestNetwork_in, CPURequestMsg) { 558 cache_entry.DataBlk := in_msg.DataBlk; 559 cache_entry.Dirty := true; 560 } 561 } 562 563 action(f_setFrom, "f", desc="set who WB is expected to come from") { 564 peek(requestNetwork_in, CPURequestMsg) { 565 tbe.From := in_msg.Requestor; 566 } 567 } 568 569 action(rf_resetFrom, "rf", desc="reset From") { 570 tbe.From := machineID; 571 } 572 573 action(wb_data, "wb", desc="write back data") { 574 enqueue(L3Resp_out, ResponseMsg, l3_request_latency) { 575 out_msg.addr := address; 576 out_msg.Type := CoherenceResponseType:CPUData; 577 out_msg.Sender := machineID; 578 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 579 out_msg.DataBlk := tbe.DataBlk; 580 out_msg.Dirty := tbe.Dirty; 581 if (tbe.Shared) { 582 out_msg.NbReqShared := true; 583 } else { 584 out_msg.NbReqShared := false; 585 } 586 out_msg.State := CoherenceState:Shared; // faux info 587 out_msg.MessageSize := MessageSizeType:Writeback_Data; 588 DPRINTF(RubySlicc, "%s\n", out_msg); 589 } 590 } 591 592 action(wt_writeDataToTBE, "wt", desc="write WB data to TBE") { 593 peek(responseNetwork_in, ResponseMsg) { 594 tbe.DataBlk := in_msg.DataBlk; 595 tbe.Dirty := in_msg.Dirty; 596 } 597 } 598 599 action(uu_sendUnblock, "uu", desc="state changed, unblock") { 600 enqueue(unblockNetwork_out, UnblockMsg, l3_request_latency) { 601 out_msg.addr := address; 602 out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); 603 out_msg.MessageSize := MessageSizeType:Unblock_Control; 604 DPRINTF(RubySlicc, "%s\n", out_msg); 605 } 606 } 607 608 action(ut_updateTag, "ut", desc="update Tag (i.e. set MRU)") { 609 L3cache.setMRU(address); 610 } 611 612 action(p_popRequestQueue, "p", desc="pop request queue") { 613 requestNetwork_in.dequeue(clockEdge()); 614 } 615 616 action(pr_popResponseQueue, "pr", desc="pop response queue") { 617 responseNetwork_in.dequeue(clockEdge()); 618 } 619 620 action(pn_popNBResponseQueue, "pn", desc="pop NB response queue") { 621 NBResponse_in.dequeue(clockEdge()); 622 } 623 624 action(pp_popProbeQueue, "pp", desc="pop probe queue") { 625 probeNetwork_in.dequeue(clockEdge()); 626 } 627 628 action(zz_recycleRequestQueue, "\z", desc="recycle request queue") { 629 requestNetwork_in.recycle(clockEdge(), cyclesToTicks(recycle_latency)); 630 } 631 632 633 // END ACTIONS 634 635 // BEGIN TRANSITIONS 636 637 // transitions from base 638 639 transition({I, I_C}, {RdBlk, RdBlkS, RdBlkM, CtoD}) {TagArrayRead} { 640 r_requestToMem; 641 p_popRequestQueue; 642 } 643 644 transition(O, RdBlk ) {TagArrayRead, DataArrayRead} { 645 rs_sendResponseS; 646 ut_updateTag; 647 p_popRequestQueue; 648 } 649 transition(M, RdBlk, O) {TagArrayRead, DataArrayRead, TagArrayWrite} { 650 rs_sendResponseS; 651 ut_updateTag; 652 p_popRequestQueue; 653 } 654 655 transition(S, RdBlk) {TagArrayRead, DataArrayRead} { 656 rs_sendResponseS; 657 ut_updateTag; 658 p_popRequestQueue; 659 } 660 transition(E, RdBlk, S) {TagArrayRead, DataArrayRead, TagArrayWrite} { 661 rs_sendResponseS; 662 ut_updateTag; 663 p_popRequestQueue; 664 } 665 666 transition({M, O}, RdBlkS, O) {TagArrayRead, DataArrayRead, TagArrayWrite} { 667 rs_sendResponseS; 668 ut_updateTag; 669 p_popRequestQueue; 670 } 671 672 transition({E, S}, RdBlkS, S) {TagArrayRead, DataArrayRead, TagArrayWrite} { 673 rs_sendResponseS; 674 ut_updateTag; 675 p_popRequestQueue; 676 } 677 678 transition(M, RdBlkM, I) {TagArrayRead, TagArrayWrite, DataArrayRead} { 679 rm_sendResponseM; 680 i_invL3; 681 p_popRequestQueue; 682 } 683 684 transition({O, S}, {RdBlkM, CtoD}) {TagArrayRead} { 685 r_requestToMem; // can't handle this, just forward 686 p_popRequestQueue; 687 } 688 689 transition(E, RdBlkM, I) {TagArrayRead, TagArrayWrite, DataArrayRead} { 690 rm_sendResponseM; 691 i_invL3; 692 p_popRequestQueue; 693 } 694 695 transition({I}, WrVicBlk, I_M) {TagArrayRead, TagArrayWrite} { 696 a_allocateBlock; 697 t_allocateTBE; 698 f_setFrom; 699// rd_copyDataFromRequest; 700 w_sendResponseWBAck; 701 p_popRequestQueue; 702 } 703 704 transition(I_C, {WrVicBlk, WrVicBlkShared, ClVicBlk, ClVicBlkShared}) {} { 705 zz_recycleRequestQueue; 706 } 707 708 transition({I}, WrVicBlkShared, I_O) {TagArrayRead, TagArrayWrite} { 709 a_allocateBlock; 710 t_allocateTBE; 711 f_setFrom; 712// rd_copyDataFromRequest; 713 w_sendResponseWBAck; 714 p_popRequestQueue; 715 } 716 717 transition(S, WrVicBlkShared, S_O) {TagArrayRead, TagArrayWrite} { 718// rd_copyDataFromRequest; 719 t_allocateTBE; 720 f_setFrom; 721 w_sendResponseWBAck; 722 p_popRequestQueue; 723 } 724 725 transition(S, WrVicBlk, S_M) {TagArrayRead, TagArrayWrite} { // should be technically not possible, but assume the data comes back with shared bit flipped 726// rd_copyDataFromRequest; 727 t_allocateTBE; 728 f_setFrom; 729 w_sendResponseWBAck; 730 p_popRequestQueue; 731 } 732 733 transition(E, WrVicBlk, E_M) {TagArrayRead, TagArrayWrite} { 734 t_allocateTBE; 735 f_setFrom; 736 w_sendResponseWBAck; 737 p_popRequestQueue; 738 } 739 740 transition(E, WrVicBlkShared, E_O) {TagArrayRead, TagArrayWrite} { 741 t_allocateTBE; 742 f_setFrom; 743 w_sendResponseWBAck; 744 p_popRequestQueue; 745 } 746 747 transition(O, WrVicBlk, O_M) {TagArrayRead, TagArrayWrite} { 748 t_allocateTBE; 749 f_setFrom; 750 w_sendResponseWBAck; 751 p_popRequestQueue; 752 } 753 754 transition(O, WrVicBlkShared, O_O) {TagArrayRead, TagArrayWrite} { 755 t_allocateTBE; 756 f_setFrom; 757 w_sendResponseWBAck; 758 p_popRequestQueue; 759 } 760 761 transition(M, WrVicBlk, M_M) {TagArrayRead, TagArrayWrite} { 762 t_allocateTBE; 763 f_setFrom; 764 w_sendResponseWBAck; 765 p_popRequestQueue; 766 } 767 768 transition(M, WrVicBlkShared, M_O) {TagArrayRead, TagArrayWrite} { 769 t_allocateTBE; 770 f_setFrom; 771 w_sendResponseWBAck; 772 p_popRequestQueue; 773 } 774 775 transition({I}, ClVicBlk, I_E) {TagArrayRead, TagArrayWrite} { 776 t_allocateTBE; 777 f_setFrom; 778 a_allocateBlock; 779 w_sendResponseWBAck; 780 p_popRequestQueue; 781 } 782 783 transition({I}, ClVicBlkShared, I_S) {TagArrayRead, TagArrayWrite} { 784 t_allocateTBE; 785 f_setFrom; 786 a_allocateBlock; 787 w_sendResponseWBAck; 788 p_popRequestQueue; 789 } 790 791 transition(S, ClVicBlk, S_E) {TagArrayRead, TagArrayWrite} { // technically impossible, assume data comes back with shared bit flipped 792 t_allocateTBE; 793 f_setFrom; 794 w_sendResponseWBAck; 795 p_popRequestQueue; 796 } 797 798 transition(S, ClVicBlkShared, S_S) {TagArrayRead, TagArrayWrite} { 799 t_allocateTBE; 800 f_setFrom; 801 w_sendResponseWBAck; 802 p_popRequestQueue; 803 } 804 805 transition(E, ClVicBlk, E_E) {TagArrayRead, TagArrayWrite} { 806 t_allocateTBE; 807 f_setFrom; 808 w_sendResponseWBAck; 809 p_popRequestQueue; 810 } 811 812 transition(E, ClVicBlkShared, E_S) {TagArrayRead, TagArrayWrite} { 813 t_allocateTBE; 814 f_setFrom; 815 w_sendResponseWBAck; 816 p_popRequestQueue; 817 } 818 819 transition(O, ClVicBlk, O_E) {TagArrayRead, TagArrayWrite} { // technically impossible, but assume data comes back with shared bit flipped 820 t_allocateTBE; 821 f_setFrom; 822 w_sendResponseWBAck; 823 p_popRequestQueue; 824 } 825 826 transition(O, ClVicBlkShared, O_S) {TagArrayRead, TagArrayWrite} { 827 t_allocateTBE; 828 f_setFrom; 829 w_sendResponseWBAck; 830 p_popRequestQueue; 831 } 832 833 transition(M, ClVicBlk, M_E) {TagArrayRead, TagArrayWrite} { 834 t_allocateTBE; 835 f_setFrom; 836 w_sendResponseWBAck; 837 p_popRequestQueue; 838 } 839 840 transition(M, ClVicBlkShared, M_S) {TagArrayRead, TagArrayWrite} { 841 t_allocateTBE; 842 f_setFrom; 843 w_sendResponseWBAck; 844 p_popRequestQueue; 845 } 846 847 transition({MO_I}, {RdBlk, RdBlkS, RdBlkM, CtoD}) {} { 848 r_requestToMem; 849 p_popRequestQueue; 850 } 851 852 transition(MO_I, {WrVicBlkShared, WrVicBlk, ClVicBlk, ClVicBlkShared}, MOD_I) {TagArrayWrite} { 853 f_setFrom; 854 w_sendResponseWBAck; 855 p_popRequestQueue; 856 } 857 858 transition(I_M, CPUData, M) {DataArrayWrite, TagArrayWrite} { 859 uu_sendUnblock; 860 dt_deallocateTBE; 861 d_writeData; 862 pr_popResponseQueue; 863 } 864 865 transition(I_M, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} { 866 uu_sendUnblock; 867 dt_deallocateTBE; 868 d_writeData; 869 pr_popResponseQueue; 870 } 871 872 transition(I_O, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} { 873 uu_sendUnblock; 874 dt_deallocateTBE; 875 d_writeData; 876 pr_popResponseQueue; 877 } 878 879 transition(I_E, CPUData, E) {DataArrayWrite, TagArrayWrite} { 880 uu_sendUnblock; 881 dt_deallocateTBE; 882 d_writeData; 883 pr_popResponseQueue; 884 } 885 886 transition(I_E, CPUDataShared, S) {DataArrayWrite, TagArrayWrite} { 887 uu_sendUnblock; 888 dt_deallocateTBE; 889 d_writeData; 890 pr_popResponseQueue; 891 } 892 893 transition(I_S, {CPUData, CPUDataShared}, S) {DataArrayWrite, TagArrayWrite} { 894 uu_sendUnblock; 895 dt_deallocateTBE; 896 d_writeData; 897 pr_popResponseQueue; 898 } 899 900 transition(S_M, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} { 901 uu_sendUnblock; 902 dt_deallocateTBE; 903 d_writeData; 904 ut_updateTag; // update tag on writeback hits. 905 pr_popResponseQueue; 906 } 907 908 transition(S_O, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} { 909 uu_sendUnblock; 910 dt_deallocateTBE; 911 d_writeData; 912 ut_updateTag; // update tag on writeback hits. 913 pr_popResponseQueue; 914 } 915 916 transition(S_E, CPUDataShared, S) {DataArrayWrite, TagArrayWrite} { 917 uu_sendUnblock; 918 dt_deallocateTBE; 919 d_writeData; 920 ut_updateTag; // update tag on writeback hits. 921 pr_popResponseQueue; 922 } 923 924 transition(S_S, {CPUData, CPUDataShared}, S) {DataArrayWrite, TagArrayWrite} { 925 uu_sendUnblock; 926 dt_deallocateTBE; 927 d_writeData; 928 ut_updateTag; // update tag on writeback hits. 929 pr_popResponseQueue; 930 } 931 932 transition(O_E, CPUDataShared, O) {DataArrayWrite, TagArrayWrite} { 933 uu_sendUnblock; 934 dt_deallocateTBE; 935 d_writeData; 936 ut_updateTag; // update tag on writeback hits. 937 pr_popResponseQueue; 938 } 939 940 transition(O_S, {CPUData, CPUDataShared}, O) {DataArrayWrite, TagArrayWrite} { 941 uu_sendUnblock; 942 dt_deallocateTBE; 943 d_writeData; 944 ut_updateTag; // update tag on writeback hits. 945 pr_popResponseQueue; 946 } 947 948 transition({D_I}, {CPUData, CPUDataShared}, I) {TagArrayWrite} { 949 uu_sendUnblock; 950 dt_deallocateTBE; 951 pr_popResponseQueue; 952 } 953 954 transition(MOD_I, {CPUData, CPUDataShared}, MO_I) {TagArrayWrite} { 955 uu_sendUnblock; 956 rf_resetFrom; 957 pr_popResponseQueue; 958 } 959 960 transition(I_I, {CPUData, CPUDataShared}, MO_I) {TagArrayWrite, DataArrayRead} { 961 uu_sendUnblock; 962 wt_writeDataToTBE; 963 rf_resetFrom; 964 pr_popResponseQueue; 965 } 966 967 transition(I_CD, {CPUData, CPUDataShared}, I) {DataArrayRead, TagArrayWrite} { 968 uu_sendUnblock; 969 wt_writeDataToTBE; 970 wb_data; 971 dt_deallocateTBE; 972 pr_popResponseQueue; 973 } 974 975 transition({M, O}, L3_Repl, MO_I) {TagArrayRead, TagArrayWrite} { 976 t_allocateTBE; 977 vd_vicDirty; 978 i_invL3; 979 } 980 981 transition({E, S,}, L3_Repl, I) {TagArrayRead, TagArrayWrite} { 982 i_invL3; 983 } 984 985 transition({I_M, I_O, S_M, S_O, E_M, E_O}, L3_Repl) {} { 986 zz_recycleRequestQueue; 987 } 988 989 transition({O_M, O_O, O_E, O_S, M_M, M_O, M_E, M_S}, L3_Repl) {} { 990 zz_recycleRequestQueue; 991 } 992 993 transition({I_E, I_S, S_E, S_S, E_E, E_S}, L3_Repl) {} { 994 zz_recycleRequestQueue; 995 } 996 997 transition({M, O}, PrbInvData, I) {TagArrayRead, TagArrayWrite, DataArrayRead} { 998 pd_sendProbeResponseData; 999 i_invL3; 1000 pp_popProbeQueue; 1001 } 1002 1003 transition({E, S, I}, PrbInvData, I) {TagArrayRead, TagArrayWrite} { 1004 pi_sendProbeResponseInv; 1005 i_invL3; // nothing will happen in I 1006 pp_popProbeQueue; 1007 } 1008 1009 transition({M, O, E, S, I}, PrbInv, I) {TagArrayRead, TagArrayWrite} { 1010 pi_sendProbeResponseInv; 1011 i_invL3; // nothing will happen in I 1012 pp_popProbeQueue; 1013 } 1014 1015 transition({M, O}, PrbShrData, O) {TagArrayRead, DataArrayRead, TagArrayWrite} { 1016 pd_sendProbeResponseData; 1017 pp_popProbeQueue; 1018 } 1019 1020 transition({E, S}, PrbShrData, S) {TagArrayRead, TagArrayWrite} { 1021 ph_sendProbeResponseHit; 1022 pp_popProbeQueue; 1023 } 1024 1025 transition(I, PrbShrData) {TagArrayRead} { 1026 pm_sendProbeResponseMiss; 1027 pp_popProbeQueue; 1028 } 1029 1030 transition(MO_I, PrbInvData, I_C) {TagArrayWrite, DataArrayRead} { 1031 pdt_sendProbeResponseDataFromTBE; 1032 mc_cancelMemWriteback; 1033 pp_popProbeQueue; 1034 } 1035 1036 transition(MO_I, PrbInv, I_C) {TagArrayWrite} { 1037 pi_sendProbeResponseInv; 1038 mc_cancelMemWriteback; 1039 pp_popProbeQueue; 1040 } 1041 1042 transition(MO_I, PrbShrData) {DataArrayRead} { 1043 pdt_sendProbeResponseDataFromTBE; 1044 pp_popProbeQueue; 1045 } 1046 1047 transition(I_C, {PrbInvData, PrbInv}) {} { 1048 pi_sendProbeResponseInv; 1049 pp_popProbeQueue; 1050 } 1051 1052 transition(I_C, PrbShrData) {} { 1053 pm_sendProbeResponseMiss; 1054 pp_popProbeQueue; 1055 } 1056 1057 transition(I_I, {WBAck}, I_CD) {TagArrayWrite} { 1058 pn_popNBResponseQueue; 1059 } 1060 1061 transition(MOD_I, WBAck, D_I) {DataArrayRead} { 1062 wb_data; 1063 pn_popNBResponseQueue; 1064 } 1065 1066 transition(MO_I, WBAck, I) {DataArrayRead, TagArrayWrite} { 1067 wb_data; 1068 dt_deallocateTBE; 1069 pn_popNBResponseQueue; 1070 } 1071 1072 transition(I_C, {WBAck}, I) {TagArrayWrite} { 1073 dt_deallocateTBE; 1074 pn_popNBResponseQueue; 1075 } 1076 1077 transition({I_M, I_O, I_E, I_S}, CancelWB, I) {TagArrayWrite} { 1078 uu_sendUnblock; 1079 dt_deallocateTBE; 1080 i_invL3; 1081 p_popRequestQueue; 1082 } 1083 1084 transition({S_S, S_O, S_M, S_E}, CancelWB, S) {TagArrayWrite} { 1085 uu_sendUnblock; 1086 dt_deallocateTBE; 1087 p_popRequestQueue; 1088 } 1089 1090 transition({E_M, E_O, E_E, E_S}, CancelWB, E) {TagArrayWrite} { 1091 uu_sendUnblock; 1092 dt_deallocateTBE; 1093 p_popRequestQueue; 1094 } 1095 1096 transition({O_M, O_O, O_E, O_S}, CancelWB, O) {TagArrayWrite} { 1097 uu_sendUnblock; 1098 dt_deallocateTBE; 1099 p_popRequestQueue; 1100 } 1101 1102 transition({M_M, M_O, M_E, M_S}, CancelWB, M) {TagArrayWrite} { 1103 uu_sendUnblock; 1104 dt_deallocateTBE; 1105 p_popRequestQueue; 1106 } 1107 1108 transition(D_I, CancelWB, I) {TagArrayWrite} { 1109 uu_sendUnblock; 1110 dt_deallocateTBE; 1111 p_popRequestQueue; 1112 } 1113 1114 transition(MOD_I, CancelWB, MO_I) {TagArrayWrite} { 1115 uu_sendUnblock; 1116 rf_resetFrom; 1117 p_popRequestQueue; 1118 } 1119 1120 transition(I_I, CancelWB, I_C) {TagArrayWrite} { 1121 uu_sendUnblock; 1122 rf_resetFrom; 1123 mc_cancelMemWriteback; 1124 p_popRequestQueue; 1125 } 1126 1127 transition(I_CD, CancelWB, I) {TagArrayWrite} { 1128 uu_sendUnblock; 1129 dt_deallocateTBE; 1130 mc_cancelMemWriteback; 1131 p_popRequestQueue; 1132 } 1133 1134} 1135