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