Sequencer.cc revision 6151:bc6b84108443
1 2/* 3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/* 31 * $Id: Sequencer.C 1.131 2006/11/06 17:41:01-06:00 bobba@gratiano.cs.wisc.edu $ 32 * 33 */ 34 35#include "Global.hh" 36#include "Sequencer.hh" 37#include "System.hh" 38#include "Protocol.hh" 39#include "Profiler.hh" 40#include "CacheMemory.hh" 41#include "RubyConfig.hh" 42//#include "Tracer.hh" 43#include "AbstractChip.hh" 44#include "Chip.hh" 45#include "Tester.hh" 46#include "SubBlock.hh" 47#include "Protocol.hh" 48#include "Map.hh" 49#include "interface.hh" 50//#include "XactCommitArbiter.hh" 51// #include "TransactionInterfaceManager.hh" 52//#include "TransactionVersionManager.hh" 53//#include "LazyTransactionVersionManager.hh" 54 55//#define XACT_MGR g_system_ptr->getChip(m_chip_ptr->getID())->getTransactionInterfaceManager(m_version) 56 57Sequencer::Sequencer(AbstractChip* chip_ptr, int version) { 58 m_chip_ptr = chip_ptr; 59 m_version = version; 60 61 m_deadlock_check_scheduled = false; 62 m_outstanding_count = 0; 63 64 int smt_threads = RubyConfig::numberofSMTThreads(); 65 m_writeRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads]; 66 m_readRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads]; 67 68 for(int p=0; p < smt_threads; ++p){ 69 m_writeRequestTable_ptr[p] = new Map<Address, CacheMsg>; 70 m_readRequestTable_ptr[p] = new Map<Address, CacheMsg>; 71 } 72 73} 74 75Sequencer::~Sequencer() { 76 int smt_threads = RubyConfig::numberofSMTThreads(); 77 for(int i=0; i < smt_threads; ++i){ 78 if(m_writeRequestTable_ptr[i]){ 79 delete m_writeRequestTable_ptr[i]; 80 } 81 if(m_readRequestTable_ptr[i]){ 82 delete m_readRequestTable_ptr[i]; 83 } 84 } 85 if(m_writeRequestTable_ptr){ 86 delete [] m_writeRequestTable_ptr; 87 } 88 if(m_readRequestTable_ptr){ 89 delete [] m_readRequestTable_ptr; 90 } 91} 92 93void Sequencer::wakeup() { 94 // Check for deadlock of any of the requests 95 Time current_time = g_eventQueue_ptr->getTime(); 96 bool deadlock = false; 97 98 // Check across all outstanding requests 99 int smt_threads = RubyConfig::numberofSMTThreads(); 100 int total_outstanding = 0; 101 for(int p=0; p < smt_threads; ++p){ 102 Vector<Address> keys = m_readRequestTable_ptr[p]->keys(); 103 for (int i=0; i<keys.size(); i++) { 104 CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]); 105 if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) { 106 WARN_MSG("Possible Deadlock detected"); 107 WARN_EXPR(request); 108 WARN_EXPR(m_chip_ptr->getID()); 109 WARN_EXPR(m_version); 110 WARN_EXPR(keys.size()); 111 WARN_EXPR(current_time); 112 WARN_EXPR(request.getTime()); 113 WARN_EXPR(current_time - request.getTime()); 114 WARN_EXPR(*m_readRequestTable_ptr[p]); 115 ERROR_MSG("Aborting"); 116 deadlock = true; 117 } 118 } 119 120 keys = m_writeRequestTable_ptr[p]->keys(); 121 for (int i=0; i<keys.size(); i++) { 122 CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]); 123 if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) { 124 WARN_MSG("Possible Deadlock detected"); 125 WARN_EXPR(request); 126 WARN_EXPR(m_chip_ptr->getID()); 127 WARN_EXPR(m_version); 128 WARN_EXPR(current_time); 129 WARN_EXPR(request.getTime()); 130 WARN_EXPR(current_time - request.getTime()); 131 WARN_EXPR(keys.size()); 132 WARN_EXPR(*m_writeRequestTable_ptr[p]); 133 ERROR_MSG("Aborting"); 134 deadlock = true; 135 } 136 } 137 total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size(); 138 } // across all request tables 139 assert(m_outstanding_count == total_outstanding); 140 141 if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking 142 g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD); 143 } else { 144 m_deadlock_check_scheduled = false; 145 } 146} 147 148//returns the total number of requests 149int Sequencer::getNumberOutstanding(){ 150 return m_outstanding_count; 151} 152 153// returns the total number of demand requests 154int Sequencer::getNumberOutstandingDemand(){ 155 int smt_threads = RubyConfig::numberofSMTThreads(); 156 int total_demand = 0; 157 for(int p=0; p < smt_threads; ++p){ 158 Vector<Address> keys = m_readRequestTable_ptr[p]->keys(); 159 for (int i=0; i< keys.size(); i++) { 160 CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]); 161 // don't count transactional begin/commit requests 162 if(request.getType() != CacheRequestType_BEGIN_XACT && request.getType() != CacheRequestType_COMMIT_XACT){ 163 if(request.getPrefetch() == PrefetchBit_No){ 164 total_demand++; 165 } 166 } 167 } 168 169 keys = m_writeRequestTable_ptr[p]->keys(); 170 for (int i=0; i< keys.size(); i++) { 171 CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]); 172 if(request.getPrefetch() == PrefetchBit_No){ 173 total_demand++; 174 } 175 } 176 } 177 178 return total_demand; 179} 180 181int Sequencer::getNumberOutstandingPrefetch(){ 182 int smt_threads = RubyConfig::numberofSMTThreads(); 183 int total_prefetch = 0; 184 for(int p=0; p < smt_threads; ++p){ 185 Vector<Address> keys = m_readRequestTable_ptr[p]->keys(); 186 for (int i=0; i< keys.size(); i++) { 187 CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]); 188 if(request.getPrefetch() == PrefetchBit_Yes){ 189 total_prefetch++; 190 } 191 } 192 193 keys = m_writeRequestTable_ptr[p]->keys(); 194 for (int i=0; i< keys.size(); i++) { 195 CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]); 196 if(request.getPrefetch() == PrefetchBit_Yes){ 197 total_prefetch++; 198 } 199 } 200 } 201 202 return total_prefetch; 203} 204 205bool Sequencer::isPrefetchRequest(const Address & lineaddr){ 206 int smt_threads = RubyConfig::numberofSMTThreads(); 207 for(int p=0; p < smt_threads; ++p){ 208 // check load requests 209 Vector<Address> keys = m_readRequestTable_ptr[p]->keys(); 210 for (int i=0; i< keys.size(); i++) { 211 CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]); 212 if(line_address(request.getAddress()) == lineaddr){ 213 if(request.getPrefetch() == PrefetchBit_Yes){ 214 return true; 215 } 216 else{ 217 return false; 218 } 219 } 220 } 221 222 // check store requests 223 keys = m_writeRequestTable_ptr[p]->keys(); 224 for (int i=0; i< keys.size(); i++) { 225 CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]); 226 if(line_address(request.getAddress()) == lineaddr){ 227 if(request.getPrefetch() == PrefetchBit_Yes){ 228 return true; 229 } 230 else{ 231 return false; 232 } 233 } 234 } 235 } 236 // we should've found a matching request 237 cout << "isRequestPrefetch() ERROR request NOT FOUND : " << lineaddr << endl; 238 printProgress(cout); 239 assert(0); 240} 241 242AccessModeType Sequencer::getAccessModeOfRequest(Address addr, int thread){ 243 if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){ 244 CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr); 245 return request.getAccessMode(); 246 } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){ 247 CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr); 248 return request.getAccessMode(); 249 } else { 250 printProgress(cout); 251 ERROR_MSG("Request not found in RequestTables"); 252 } 253} 254 255Address Sequencer::getLogicalAddressOfRequest(Address addr, int thread){ 256 assert(thread >= 0); 257 if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){ 258 CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr); 259 return request.getLogicalAddress(); 260 } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){ 261 CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr); 262 return request.getLogicalAddress(); 263 } else { 264 printProgress(cout); 265 WARN_MSG("Request not found in RequestTables"); 266 WARN_MSG(addr); 267 WARN_MSG(thread); 268 ASSERT(0); 269 } 270} 271 272// returns the ThreadID of the request 273int Sequencer::getRequestThreadID(const Address & addr){ 274 int smt_threads = RubyConfig::numberofSMTThreads(); 275 int thread = -1; 276 int num_found = 0; 277 for(int p=0; p < smt_threads; ++p){ 278 if(m_readRequestTable_ptr[p]->exist(addr)){ 279 num_found++; 280 thread = p; 281 } 282 if(m_writeRequestTable_ptr[p]->exist(addr)){ 283 num_found++; 284 thread = p; 285 } 286 } 287 if(num_found != 1){ 288 cout << "getRequestThreadID ERROR too many matching requests addr = " << addr << endl; 289 printProgress(cout); 290 } 291 ASSERT(num_found == 1); 292 ASSERT(thread != -1); 293 294 return thread; 295} 296 297// given a line address, return the request's physical address 298Address Sequencer::getRequestPhysicalAddress(const Address & lineaddr){ 299 int smt_threads = RubyConfig::numberofSMTThreads(); 300 Address physaddr; 301 int num_found = 0; 302 for(int p=0; p < smt_threads; ++p){ 303 if(m_readRequestTable_ptr[p]->exist(lineaddr)){ 304 num_found++; 305 physaddr = (m_readRequestTable_ptr[p]->lookup(lineaddr)).getAddress(); 306 } 307 if(m_writeRequestTable_ptr[p]->exist(lineaddr)){ 308 num_found++; 309 physaddr = (m_writeRequestTable_ptr[p]->lookup(lineaddr)).getAddress(); 310 } 311 } 312 if(num_found != 1){ 313 cout << "getRequestPhysicalAddress ERROR too many matching requests addr = " << lineaddr << endl; 314 printProgress(cout); 315 } 316 ASSERT(num_found == 1); 317 318 return physaddr; 319} 320 321void Sequencer::printProgress(ostream& out) const{ 322 323 int total_demand = 0; 324 out << "Sequencer Stats Version " << m_version << endl; 325 out << "Current time = " << g_eventQueue_ptr->getTime() << endl; 326 out << "---------------" << endl; 327 out << "outstanding requests" << endl; 328 329 int smt_threads = RubyConfig::numberofSMTThreads(); 330 for(int p=0; p < smt_threads; ++p){ 331 Vector<Address> rkeys = m_readRequestTable_ptr[p]->keys(); 332 int read_size = rkeys.size(); 333 out << "proc " << m_chip_ptr->getID() << " thread " << p << " Read Requests = " << read_size << endl; 334 // print the request table 335 for(int i=0; i < read_size; ++i){ 336 CacheMsg & request = m_readRequestTable_ptr[p]->lookup(rkeys[i]); 337 out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << rkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; 338 if( request.getPrefetch() == PrefetchBit_No ){ 339 total_demand++; 340 } 341 } 342 343 Vector<Address> wkeys = m_writeRequestTable_ptr[p]->keys(); 344 int write_size = wkeys.size(); 345 out << "proc " << m_chip_ptr->getID() << " thread " << p << " Write Requests = " << write_size << endl; 346 // print the request table 347 for(int i=0; i < write_size; ++i){ 348 CacheMsg & request = m_writeRequestTable_ptr[p]->lookup(wkeys[i]); 349 out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; 350 if( request.getPrefetch() == PrefetchBit_No ){ 351 total_demand++; 352 } 353 } 354 355 out << endl; 356 } 357 out << "Total Number Outstanding: " << m_outstanding_count << endl; 358 out << "Total Number Demand : " << total_demand << endl; 359 out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl; 360 out << endl; 361 out << endl; 362 363} 364 365void Sequencer::printConfig(ostream& out) { 366 if (TSO) { 367 out << "sequencer: Sequencer - TSO" << endl; 368 } else { 369 out << "sequencer: Sequencer - SC" << endl; 370 } 371 out << " max_outstanding_requests: " << g_SEQUENCER_OUTSTANDING_REQUESTS << endl; 372} 373 374bool Sequencer::empty() const { 375 return m_outstanding_count == 0; 376} 377 378// Insert the request on the correct request table. Return true if 379// the entry was already present. 380bool Sequencer::insertRequest(const CacheMsg& request) { 381 int thread = request.getThreadID(); 382 assert(thread >= 0); 383 int total_outstanding = 0; 384 int smt_threads = RubyConfig::numberofSMTThreads(); 385 for(int p=0; p < smt_threads; ++p){ 386 total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size(); 387 } 388 assert(m_outstanding_count == total_outstanding); 389 390 // See if we should schedule a deadlock check 391 if (m_deadlock_check_scheduled == false) { 392 g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD); 393 m_deadlock_check_scheduled = true; 394 } 395 396 if ((request.getType() == CacheRequestType_ST) || 397 (request.getType() == CacheRequestType_ST_XACT) || 398 (request.getType() == CacheRequestType_LDX_XACT) || 399 (request.getType() == CacheRequestType_ATOMIC)) { 400 if (m_writeRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) { 401 m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request; 402 return true; 403 } 404 m_writeRequestTable_ptr[thread]->allocate(line_address(request.getAddress())); 405 m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request; 406 m_outstanding_count++; 407 } else { 408 if (m_readRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) { 409 m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request; 410 return true; 411 } 412 m_readRequestTable_ptr[thread]->allocate(line_address(request.getAddress())); 413 m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request; 414 m_outstanding_count++; 415 } 416 417 g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count); 418 419 total_outstanding = 0; 420 for(int p=0; p < smt_threads; ++p){ 421 total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size(); 422 } 423 424 assert(m_outstanding_count == total_outstanding); 425 return false; 426} 427 428void Sequencer::removeRequest(const CacheMsg& request) { 429 int thread = request.getThreadID(); 430 assert(thread >= 0); 431 int total_outstanding = 0; 432 int smt_threads = RubyConfig::numberofSMTThreads(); 433 for(int p=0; p < smt_threads; ++p){ 434 total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size(); 435 } 436 assert(m_outstanding_count == total_outstanding); 437 438 if ((request.getType() == CacheRequestType_ST) || 439 (request.getType() == CacheRequestType_ST_XACT) || 440 (request.getType() == CacheRequestType_LDX_XACT) || 441 (request.getType() == CacheRequestType_ATOMIC)) { 442 m_writeRequestTable_ptr[thread]->deallocate(line_address(request.getAddress())); 443 } else { 444 m_readRequestTable_ptr[thread]->deallocate(line_address(request.getAddress())); 445 } 446 m_outstanding_count--; 447 448 total_outstanding = 0; 449 for(int p=0; p < smt_threads; ++p){ 450 total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size(); 451 } 452 assert(m_outstanding_count == total_outstanding); 453} 454 455void Sequencer::writeCallback(const Address& address) { 456 DataBlock data; 457 writeCallback(address, data); 458} 459 460void Sequencer::writeCallback(const Address& address, DataBlock& data) { 461 // process oldest thread first 462 int thread = -1; 463 Time oldest_time = 0; 464 int smt_threads = RubyConfig::numberofSMTThreads(); 465 for(int t=0; t < smt_threads; ++t){ 466 if(m_writeRequestTable_ptr[t]->exist(address)){ 467 CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address); 468 if(thread == -1 || (request.getTime() < oldest_time) ){ 469 thread = t; 470 oldest_time = request.getTime(); 471 } 472 } 473 } 474 // make sure we found an oldest thread 475 ASSERT(thread != -1); 476 477 CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address); 478 479 writeCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread); 480} 481 482void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) { 483 484 assert(address == line_address(address)); 485 assert(thread >= 0); 486 assert(m_writeRequestTable_ptr[thread]->exist(line_address(address))); 487 488 writeCallback(address, data, respondingMach, thread); 489 490} 491 492void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) { 493 assert(address == line_address(address)); 494 assert(m_writeRequestTable_ptr[thread]->exist(line_address(address))); 495 CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address); 496 assert( request.getThreadID() == thread); 497 removeRequest(request); 498 499 assert((request.getType() == CacheRequestType_ST) || 500 (request.getType() == CacheRequestType_ST_XACT) || 501 (request.getType() == CacheRequestType_LDX_XACT) || 502 (request.getType() == CacheRequestType_ATOMIC)); 503 504 hitCallback(request, data, respondingMach, thread); 505 506} 507 508void Sequencer::readCallback(const Address& address) { 509 DataBlock data; 510 readCallback(address, data); 511} 512 513void Sequencer::readCallback(const Address& address, DataBlock& data) { 514 // process oldest thread first 515 int thread = -1; 516 Time oldest_time = 0; 517 int smt_threads = RubyConfig::numberofSMTThreads(); 518 for(int t=0; t < smt_threads; ++t){ 519 if(m_readRequestTable_ptr[t]->exist(address)){ 520 CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address); 521 if(thread == -1 || (request.getTime() < oldest_time) ){ 522 thread = t; 523 oldest_time = request.getTime(); 524 } 525 } 526 } 527 // make sure we found an oldest thread 528 ASSERT(thread != -1); 529 530 CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address); 531 532 readCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread); 533} 534 535void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) { 536 537 assert(address == line_address(address)); 538 assert(m_readRequestTable_ptr[thread]->exist(line_address(address))); 539 540 readCallback(address, data, respondingMach, thread); 541} 542 543void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) { 544 assert(address == line_address(address)); 545 assert(m_readRequestTable_ptr[thread]->exist(line_address(address))); 546 547 CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address); 548 assert( request.getThreadID() == thread ); 549 removeRequest(request); 550 551 assert((request.getType() == CacheRequestType_LD) || 552 (request.getType() == CacheRequestType_LD_XACT) || 553 (request.getType() == CacheRequestType_IFETCH) 554 ); 555 556 hitCallback(request, data, respondingMach, thread); 557} 558 559void Sequencer::hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread) { 560 int size = request.getSize(); 561 Address request_address = request.getAddress(); 562 Address request_logical_address = request.getLogicalAddress(); 563 Address request_line_address = line_address(request_address); 564 CacheRequestType type = request.getType(); 565 int threadID = request.getThreadID(); 566 Time issued_time = request.getTime(); 567 int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID; 568 569 DEBUG_MSG(SEQUENCER_COMP, MedPrio, size); 570 571 // Set this cache entry to the most recently used 572 if (type == CacheRequestType_IFETCH) { 573 if (Protocol::m_TwoLevelCache) { 574 if (m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->isTagPresent(request_line_address)) { 575 m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->setMRU(request_line_address); 576 } 577 } 578 else { 579 if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) { 580 m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address); 581 } 582 } 583 } else { 584 if (Protocol::m_TwoLevelCache) { 585 if (m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->isTagPresent(request_line_address)) { 586 m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->setMRU(request_line_address); 587 } 588 } 589 else { 590 if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) { 591 m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address); 592 } 593 } 594 } 595 596 assert(g_eventQueue_ptr->getTime() >= issued_time); 597 Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; 598 599 if (PROTOCOL_DEBUG_TRACE) { 600 g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Done", "", 601 int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch())); 602 } 603 604 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address); 605 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch()); 606 if (request.getPrefetch() == PrefetchBit_Yes) { 607 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return"); 608 g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach); 609 return; // Ignore the software prefetch, don't callback the driver 610 } 611 612 // Profile the miss latency for all non-zero demand misses 613 if (miss_latency != 0) { 614 g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach); 615 616#if 0 617 uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick")); 618 uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr")); 619 uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick")); 620 uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr")); 621 cout << "END PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl; 622#endif 623 624 } 625 626 bool write = 627 (type == CacheRequestType_ST) || 628 (type == CacheRequestType_ST_XACT) || 629 (type == CacheRequestType_LDX_XACT) || 630 (type == CacheRequestType_ATOMIC); 631 632 if (TSO && write) { 633 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data); 634 } else { 635 636 // Copy the correct bytes out of the cache line into the subblock 637 SubBlock subblock(request_address, request_logical_address, size); 638 subblock.mergeFrom(data); // copy the correct bytes from DataBlock in the SubBlock 639 640 // Scan the store buffer to see if there are any outstanding stores we need to collect 641 if (TSO) { 642 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock); 643 } 644 645 // Call into the Driver (Tester or Simics) and let it read and/or modify the sub-block 646 g_system_ptr->getDriver()->hitCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID); 647 648 // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock 649 // (This is only triggered for the non-TSO case) 650 if (write) { 651 assert(!TSO); 652 subblock.mergeTo(data); // copy the correct bytes from SubBlock into the DataBlock 653 } 654 } 655} 656 657void Sequencer::readConflictCallback(const Address& address) { 658 // process oldest thread first 659 int thread = -1; 660 Time oldest_time = 0; 661 int smt_threads = RubyConfig::numberofSMTThreads(); 662 for(int t=0; t < smt_threads; ++t){ 663 if(m_readRequestTable_ptr[t]->exist(address)){ 664 CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address); 665 if(thread == -1 || (request.getTime() < oldest_time) ){ 666 thread = t; 667 oldest_time = request.getTime(); 668 } 669 } 670 } 671 // make sure we found an oldest thread 672 ASSERT(thread != -1); 673 674 CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address); 675 676 readConflictCallback(address, GenericMachineType_NULL, thread); 677} 678 679void Sequencer::readConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) { 680 assert(address == line_address(address)); 681 assert(m_readRequestTable_ptr[thread]->exist(line_address(address))); 682 683 CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address); 684 assert( request.getThreadID() == thread ); 685 removeRequest(request); 686 687 assert((request.getType() == CacheRequestType_LD) || 688 (request.getType() == CacheRequestType_LD_XACT) || 689 (request.getType() == CacheRequestType_IFETCH) 690 ); 691 692 conflictCallback(request, respondingMach, thread); 693} 694 695void Sequencer::writeConflictCallback(const Address& address) { 696 // process oldest thread first 697 int thread = -1; 698 Time oldest_time = 0; 699 int smt_threads = RubyConfig::numberofSMTThreads(); 700 for(int t=0; t < smt_threads; ++t){ 701 if(m_writeRequestTable_ptr[t]->exist(address)){ 702 CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address); 703 if(thread == -1 || (request.getTime() < oldest_time) ){ 704 thread = t; 705 oldest_time = request.getTime(); 706 } 707 } 708 } 709 // make sure we found an oldest thread 710 ASSERT(thread != -1); 711 712 CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address); 713 714 writeConflictCallback(address, GenericMachineType_NULL, thread); 715} 716 717void Sequencer::writeConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) { 718 assert(address == line_address(address)); 719 assert(m_writeRequestTable_ptr[thread]->exist(line_address(address))); 720 CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address); 721 assert( request.getThreadID() == thread); 722 removeRequest(request); 723 724 assert((request.getType() == CacheRequestType_ST) || 725 (request.getType() == CacheRequestType_ST_XACT) || 726 (request.getType() == CacheRequestType_LDX_XACT) || 727 (request.getType() == CacheRequestType_ATOMIC)); 728 729 conflictCallback(request, respondingMach, thread); 730 731} 732 733void Sequencer::conflictCallback(const CacheMsg& request, GenericMachineType respondingMach, int thread) { 734 assert(XACT_MEMORY); 735 int size = request.getSize(); 736 Address request_address = request.getAddress(); 737 Address request_logical_address = request.getLogicalAddress(); 738 Address request_line_address = line_address(request_address); 739 CacheRequestType type = request.getType(); 740 int threadID = request.getThreadID(); 741 Time issued_time = request.getTime(); 742 int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID; 743 744 DEBUG_MSG(SEQUENCER_COMP, MedPrio, size); 745 746 assert(g_eventQueue_ptr->getTime() >= issued_time); 747 Time miss_latency = g_eventQueue_ptr->getTime() - issued_time; 748 749 if (PROTOCOL_DEBUG_TRACE) { 750 g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Conflict", "", 751 int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch())); 752 } 753 754 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address); 755 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch()); 756 if (request.getPrefetch() == PrefetchBit_Yes) { 757 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return"); 758 g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach); 759 return; // Ignore the software prefetch, don't callback the driver 760 } 761 762 bool write = 763 (type == CacheRequestType_ST) || 764 (type == CacheRequestType_ST_XACT) || 765 (type == CacheRequestType_LDX_XACT) || 766 (type == CacheRequestType_ATOMIC); 767 768 // Copy the correct bytes out of the cache line into the subblock 769 SubBlock subblock(request_address, request_logical_address, size); 770 771 // Call into the Driver (Tester or Simics) 772 g_system_ptr->getDriver()->conflictCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID); 773 774 // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock 775 // (This is only triggered for the non-TSO case) 776 if (write) { 777 assert(!TSO); 778 } 779} 780 781void Sequencer::printDebug(){ 782 //notify driver of debug 783 g_system_ptr->getDriver()->printDebug(); 784} 785 786// Returns true if the sequencer already has a load or store outstanding 787bool 788Sequencer::isReady(const Packet* pkt) const 789{ 790 791 int cpu_number = pkt->req->contextId(); 792 la_t logical_addr = pkt->req->getVaddr(); 793 pa_t physical_addr = pkt->req->getPaddr(); 794 CacheRequestType type_of_request; 795 if ( pkt->req->isInstFetch() ) { 796 type_of_request = CacheRequestType_IFETCH; 797 } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) { 798 type_of_request = CacheRequestType_ATOMIC; 799 } else if ( pkt->isRead() ) { 800 type_of_request = CacheRequestType_LD; 801 } else if ( pkt->isWrite() ) { 802 type_of_request = CacheRequestType_ST; 803 } else { 804 assert(false); 805 } 806 int thread = pkt->req->threadId(); 807 808 CacheMsg request(Address( physical_addr ), 809 Address( physical_addr ), 810 type_of_request, 811 Address(0), 812 AccessModeType_UserMode, // User/supervisor mode 813 0, // Size in bytes of request 814 PrefetchBit_No, // Not a prefetch 815 0, // Version number 816 Address(logical_addr), // Virtual Address 817 thread, // SMT thread 818 0, // TM specific - timestamp of memory request 819 false // TM specific - whether request is part of escape action 820 ); 821 isReady(request); 822} 823 824bool 825Sequencer::isReady(const CacheMsg& request) const 826{ 827 if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) { 828 //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl; 829 //printProgress(cout); 830 return false; 831 } 832 833 // This code allows reads to be performed even when we have a write 834 // request outstanding for the line 835 bool write = 836 (request.getType() == CacheRequestType_ST) || 837 (request.getType() == CacheRequestType_ST_XACT) || 838 (request.getType() == CacheRequestType_LDX_XACT) || 839 (request.getType() == CacheRequestType_ATOMIC); 840 841 // LUKE - disallow more than one request type per address 842 // INVARIANT: at most one request type per address, per processor 843 int smt_threads = RubyConfig::numberofSMTThreads(); 844 for(int p=0; p < smt_threads; ++p){ 845 if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) || 846 m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){ 847 //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl; 848 //printProgress(cout); 849 return false; 850 } 851 } 852 853 if (TSO) { 854 return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady(); 855 } 856 return true; 857} 858 859// Called by Driver (Simics or Tester). 860void 861Sequencer::makeRequest(const Packet* pkt, void* data) 862{ 863 int cpu_number = pkt->req->contextId(); 864 la_t logical_addr = pkt->req->getVaddr(); 865 pa_t physical_addr = pkt->req->getPaddr(); 866 int request_size = pkt->getSize(); 867 CacheRequestType type_of_request; 868 if ( pkt->req->isInstFetch() ) { 869 type_of_request = CacheRequestType_IFETCH; 870 } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) { 871 type_of_request = CacheRequestType_ATOMIC; 872 } else if ( pkt->isRead() ) { 873 type_of_request = CacheRequestType_LD; 874 } else if ( pkt->isWrite() ) { 875 type_of_request = CacheRequestType_ST; 876 } else { 877 assert(false); 878 } 879 la_t virtual_pc = pkt->req->getPC(); 880 int isPriv = false; // TODO: get permission data 881 int thread = pkt->req->threadId(); 882 883 AccessModeType access_mode = AccessModeType_UserMode; // TODO: get actual permission 884 885 CacheMsg request(Address( physical_addr ), 886 Address( physical_addr ), 887 type_of_request, 888 Address(virtual_pc), 889 access_mode, // User/supervisor mode 890 request_size, // Size in bytes of request 891 PrefetchBit_No, // Not a prefetch 892 0, // Version number 893 Address(logical_addr), // Virtual Address 894 thread, // SMT thread 895 0, // TM specific - timestamp of memory request 896 false // TM specific - whether request is part of escape action 897 ); 898 makeRequest(request); 899} 900 901void 902Sequencer::makeRequest(const CacheMsg& request) 903{ 904 bool write = (request.getType() == CacheRequestType_ST) || 905 (request.getType() == CacheRequestType_ST_XACT) || 906 (request.getType() == CacheRequestType_LDX_XACT) || 907 (request.getType() == CacheRequestType_ATOMIC); 908 909 if (TSO && (request.getPrefetch() == PrefetchBit_No) && write) { 910 assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady()); 911 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(request); 912 return; 913 } 914 915 bool hit = doRequest(request); 916 917} 918 919bool Sequencer::doRequest(const CacheMsg& request) { 920 bool hit = false; 921 // Check the fast path 922 DataBlock* data_ptr; 923 924 int thread = request.getThreadID(); 925 926 hit = tryCacheAccess(line_address(request.getAddress()), 927 request.getType(), 928 request.getProgramCounter(), 929 request.getAccessMode(), 930 request.getSize(), 931 data_ptr); 932 933 if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) { 934 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit"); 935 hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread); 936 return true; 937 } 938 939#if 0 940 uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick")); 941 uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr")); 942 uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick")); 943 uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr")); 944 cout << "START PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl;; 945#endif 946 947 if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) { 948 949 // See if we can satisfy the load entirely from the store buffer 950 SubBlock subblock(line_address(request.getAddress()), request.getSize()); 951 if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) { 952 DataBlock dummy; 953 hitCallback(request, dummy, GenericMachineType_NULL, thread); // Call with an 'empty' datablock, since the data is in the store buffer 954 return true; 955 } 956 } 957 958 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss"); 959 issueRequest(request); 960 return hit; 961} 962 963void Sequencer::issueRequest(const CacheMsg& request) { 964 bool found = insertRequest(request); 965 966 if (!found) { 967 CacheMsg msg = request; 968 msg.getAddress() = line_address(request.getAddress()); // Make line address 969 970 // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code 971 if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) { 972 g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID()); 973 } 974 975 if (PROTOCOL_DEBUG_TRACE) { 976 g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType())); 977 } 978 979#if 0 980 // Commented out by nate binkert because I removed the trace stuff 981 if (g_system_ptr->getTracer()->traceEnabled()) { 982 g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(), 983 msg.getType(), g_eventQueue_ptr->getTime()); 984 } 985#endif 986 987 Time latency = 0; // initialzed to an null value 988 989 latency = SEQUENCER_TO_CONTROLLER_LATENCY; 990 991 // Send the message to the cache controller 992 assert(latency > 0); 993 m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency); 994 995 } // !found 996} 997 998bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, 999 const Address& pc, AccessModeType access_mode, 1000 int size, DataBlock*& data_ptr) { 1001 if (type == CacheRequestType_IFETCH) { 1002 if (Protocol::m_TwoLevelCache) { 1003 return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 1004 } 1005 else { 1006 return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 1007 } 1008 } else { 1009 if (Protocol::m_TwoLevelCache) { 1010 return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 1011 } 1012 else { 1013 return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 1014 } 1015 } 1016} 1017 1018void Sequencer::resetRequestTime(const Address& addr, int thread){ 1019 assert(thread >= 0); 1020 //reset both load and store requests, if they exist 1021 if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){ 1022 CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr); 1023 if( request.m_AccessMode != AccessModeType_UserMode){ 1024 cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl; 1025 printProgress(cout); 1026 } 1027 //ASSERT(request.m_AccessMode == AccessModeType_UserMode); 1028 request.setTime(g_eventQueue_ptr->getTime()); 1029 } 1030 if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){ 1031 CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr); 1032 if( request.m_AccessMode != AccessModeType_UserMode){ 1033 cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl; 1034 printProgress(cout); 1035 } 1036 //ASSERT(request.m_AccessMode == AccessModeType_UserMode); 1037 request.setTime(g_eventQueue_ptr->getTime()); 1038 } 1039} 1040 1041// removes load request from queue 1042void Sequencer::removeLoadRequest(const Address & addr, int thread){ 1043 removeRequest(getReadRequest(addr, thread)); 1044} 1045 1046void Sequencer::removeStoreRequest(const Address & addr, int thread){ 1047 removeRequest(getWriteRequest(addr, thread)); 1048} 1049 1050// returns the read CacheMsg 1051CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){ 1052 Address temp = addr; 1053 assert(thread >= 0); 1054 assert(temp == line_address(temp)); 1055 assert(m_readRequestTable_ptr[thread]->exist(addr)); 1056 return m_readRequestTable_ptr[thread]->lookup(addr); 1057} 1058 1059CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){ 1060 Address temp = addr; 1061 assert(thread >= 0); 1062 assert(temp == line_address(temp)); 1063 assert(m_writeRequestTable_ptr[thread]->exist(addr)); 1064 return m_writeRequestTable_ptr[thread]->lookup(addr); 1065} 1066 1067void Sequencer::print(ostream& out) const { 1068 out << "[Sequencer: " << m_chip_ptr->getID() 1069 << ", outstanding requests: " << m_outstanding_count; 1070 1071 int smt_threads = RubyConfig::numberofSMTThreads(); 1072 for(int p=0; p < smt_threads; ++p){ 1073 out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p] 1074 << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p]; 1075 } 1076 out << "]"; 1077} 1078 1079// this can be called from setState whenever coherence permissions are upgraded 1080// when invoked, coherence violations will be checked for the given block 1081void Sequencer::checkCoherence(const Address& addr) { 1082#ifdef CHECK_COHERENCE 1083 g_system_ptr->checkGlobalCoherenceInvariant(addr); 1084#endif 1085} 1086 1087bool Sequencer::getRubyMemoryValue(const Address& addr, char* value, 1088 unsigned int size_in_bytes ) { 1089 if(g_SIMICS){ 1090 for(unsigned int i=0; i < size_in_bytes; i++) { 1091 value[i] = SIMICS_read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, 1092 addr.getAddress() + i, 1 ); 1093 } 1094 return false; // Do nothing? 1095 } else { 1096 bool found = false; 1097 const Address lineAddr = line_address(addr); 1098 DataBlock data; 1099 PhysAddress paddr(addr); 1100 DataBlock* dataPtr = &data; 1101 Chip* n = dynamic_cast<Chip*>(m_chip_ptr); 1102 // LUKE - use variable names instead of macros 1103 assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL); 1104 assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL); 1105 1106 MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() ); 1107 int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip(); 1108 1109 if (Protocol::m_TwoLevelCache) { 1110 if(Protocol::m_CMP){ 1111 assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL); 1112 } 1113 else{ 1114 assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL); 1115 } 1116 } 1117 1118 if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){ 1119 n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes); 1120 found = true; 1121 } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1122 n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes); 1123 found = true; 1124 } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1125 n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes); 1126 found = true; 1127 // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){ 1128 // ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)); 1129 // L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr); 1130 1131 // int offset = addr.getOffset(); 1132 // for(int i=0; i<size_in_bytes; ++i){ 1133 // value[i] = tbeEntry.getDataBlk().getByte(offset + i); 1134 // } 1135 1136 // found = true; 1137 } else { 1138 // Address not found 1139 //cout << " " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl; 1140 n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip())); 1141 int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip(); 1142 for(unsigned int i=0; i<size_in_bytes; ++i){ 1143 int offset = addr.getOffset(); 1144 value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i); 1145 } 1146 // Address not found 1147 //WARN_MSG("Couldn't find address"); 1148 //WARN_EXPR(addr); 1149 found = false; 1150 } 1151 return true; 1152 } 1153} 1154 1155bool Sequencer::setRubyMemoryValue(const Address& addr, char *value, 1156 unsigned int size_in_bytes) { 1157 char test_buffer[64]; 1158 1159 if(g_SIMICS){ 1160 return false; // Do nothing? 1161 } else { 1162 // idea here is that coherent cache should find the 1163 // latest data, the update it 1164 bool found = false; 1165 const Address lineAddr = line_address(addr); 1166 PhysAddress paddr(addr); 1167 DataBlock data; 1168 DataBlock* dataPtr = &data; 1169 Chip* n = dynamic_cast<Chip*>(m_chip_ptr); 1170 1171 MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() ); 1172 int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip(); 1173 // LUKE - use variable names instead of macros 1174 //cout << "number of L2caches per chip = " << RubyConfig::numberOfL2CachePerChip(m_version) << endl; 1175 //cout << "L1I cache vec size = " << n->m_L1Cache_L1IcacheMemory_vec.size() << endl; 1176 //cout << "L1D cache vec size = " << n->m_L1Cache_L1DcacheMemory_vec.size() << endl; 1177 //cout << "L1cache_cachememory size = " << n->m_L1Cache_cacheMemory_vec.size() << endl; 1178 //cout << "L1cache_l2cachememory size = " << n->m_L1Cache_L2cacheMemory_vec.size() << endl; 1179 // if (Protocol::m_TwoLevelCache) { 1180 // if(Protocol::m_CMP){ 1181 // cout << "CMP L2 cache vec size = " << n->m_L2Cache_L2cacheMemory_vec.size() << endl; 1182 // } 1183 // else{ 1184 // cout << "L2 cache vec size = " << n->m_L1Cache_cacheMemory_vec.size() << endl; 1185 // } 1186 // } 1187 1188 assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL); 1189 assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL); 1190 if (Protocol::m_TwoLevelCache) { 1191 if(Protocol::m_CMP){ 1192 assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL); 1193 } 1194 else{ 1195 assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL); 1196 } 1197 } 1198 1199 if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){ 1200 n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes); 1201 found = true; 1202 } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1203 n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes); 1204 found = true; 1205 } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1206 n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes); 1207 found = true; 1208 // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isTagPresent(lineAddr)){ 1209 // L1Cache_TBE& tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr); 1210 // DataBlock tmpData; 1211 // int offset = addr.getOffset(); 1212 // for(int i=0; i<size_in_bytes; ++i){ 1213 // tmpData.setByte(offset + i, value[i]); 1214 // } 1215 // tbeEntry.setDataBlk(tmpData); 1216 // tbeEntry.setDirty(true); 1217 } else { 1218 // Address not found 1219 n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip())); 1220 int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip(); 1221 for(unsigned int i=0; i<size_in_bytes; ++i){ 1222 int offset = addr.getOffset(); 1223 n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]); 1224 } 1225 found = false; 1226 } 1227 1228 if (found){ 1229 found = getRubyMemoryValue(addr, test_buffer, size_in_bytes); 1230 assert(found); 1231 if(value[0] != test_buffer[0]){ 1232 WARN_EXPR((int) value[0]); 1233 WARN_EXPR((int) test_buffer[0]); 1234 ERROR_MSG("setRubyMemoryValue failed to set value."); 1235 } 1236 } 1237 1238 return true; 1239 } 1240} 1241