Sequencer.cc revision 6145
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 Sequencer::isReady(const CacheMsg& request) const { 788 789 if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) { 790 //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl; 791 //printProgress(cout); 792 return false; 793 } 794 int thread = request.getThreadID(); 795 796 // This code allows reads to be performed even when we have a write 797 // request outstanding for the line 798 bool write = 799 (request.getType() == CacheRequestType_ST) || 800 (request.getType() == CacheRequestType_ST_XACT) || 801 (request.getType() == CacheRequestType_LDX_XACT) || 802 (request.getType() == CacheRequestType_ATOMIC); 803 804 // LUKE - disallow more than one request type per address 805 // INVARIANT: at most one request type per address, per processor 806 int smt_threads = RubyConfig::numberofSMTThreads(); 807 for(int p=0; p < smt_threads; ++p){ 808 if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) || 809 m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){ 810 //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl; 811 //printProgress(cout); 812 return false; 813 } 814 } 815 816 if (TSO) { 817 return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady(); 818 } 819 return true; 820} 821 822// Called by Driver (Simics or Tester). 823void Sequencer::makeRequest(const CacheMsg& request) { 824 //assert(isReady(request)); 825 bool write = (request.getType() == CacheRequestType_ST) || 826 (request.getType() == CacheRequestType_ST_XACT) || 827 (request.getType() == CacheRequestType_LDX_XACT) || 828 (request.getType() == CacheRequestType_ATOMIC); 829 830 if (TSO && (request.getPrefetch() == PrefetchBit_No) && write) { 831 assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady()); 832 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(request); 833 return; 834 } 835 836 bool hit = doRequest(request); 837 838} 839 840bool Sequencer::doRequest(const CacheMsg& request) { 841 bool hit = false; 842 // Check the fast path 843 DataBlock* data_ptr; 844 845 int thread = request.getThreadID(); 846 847 hit = tryCacheAccess(line_address(request.getAddress()), 848 request.getType(), 849 request.getProgramCounter(), 850 request.getAccessMode(), 851 request.getSize(), 852 data_ptr); 853 854 if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) { 855 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit"); 856 hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread); 857 return true; 858 } 859 860 #if 0 861 uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick")); 862 uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr")); 863 uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick")); 864 uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr")); 865 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;; 866 #endif 867 868 if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) { 869 870 // See if we can satisfy the load entirely from the store buffer 871 SubBlock subblock(line_address(request.getAddress()), request.getSize()); 872 if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) { 873 DataBlock dummy; 874 hitCallback(request, dummy, GenericMachineType_NULL, thread); // Call with an 'empty' datablock, since the data is in the store buffer 875 return true; 876 } 877 } 878 879 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss"); 880 issueRequest(request); 881 return hit; 882} 883 884void Sequencer::issueRequest(const CacheMsg& request) { 885 bool found = insertRequest(request); 886 887 if (!found) { 888 CacheMsg msg = request; 889 msg.getAddress() = line_address(request.getAddress()); // Make line address 890 891 // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code 892 if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) { 893 g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID()); 894 } 895 896 if (PROTOCOL_DEBUG_TRACE) { 897 g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType())); 898 } 899 900#if 0 901 // Commented out by nate binkert because I removed the trace stuff 902 if (g_system_ptr->getTracer()->traceEnabled()) { 903 g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(), 904 msg.getType(), g_eventQueue_ptr->getTime()); 905 } 906#endif 907 908 Time latency = 0; // initialzed to an null value 909 910 latency = SEQUENCER_TO_CONTROLLER_LATENCY; 911 912 // Send the message to the cache controller 913 assert(latency > 0); 914 m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency); 915 916 } // !found 917} 918 919bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, 920 const Address& pc, AccessModeType access_mode, 921 int size, DataBlock*& data_ptr) { 922 if (type == CacheRequestType_IFETCH) { 923 if (Protocol::m_TwoLevelCache) { 924 return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 925 } 926 else { 927 return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 928 } 929 } else { 930 if (Protocol::m_TwoLevelCache) { 931 return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 932 } 933 else { 934 return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr); 935 } 936 } 937} 938 939void Sequencer::resetRequestTime(const Address& addr, int thread){ 940 assert(thread >= 0); 941 //reset both load and store requests, if they exist 942 if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){ 943 CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr); 944 if( request.m_AccessMode != AccessModeType_UserMode){ 945 cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl; 946 printProgress(cout); 947 } 948 //ASSERT(request.m_AccessMode == AccessModeType_UserMode); 949 request.setTime(g_eventQueue_ptr->getTime()); 950 } 951 if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){ 952 CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr); 953 if( request.m_AccessMode != AccessModeType_UserMode){ 954 cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl; 955 printProgress(cout); 956 } 957 //ASSERT(request.m_AccessMode == AccessModeType_UserMode); 958 request.setTime(g_eventQueue_ptr->getTime()); 959 } 960} 961 962// removes load request from queue 963void Sequencer::removeLoadRequest(const Address & addr, int thread){ 964 removeRequest(getReadRequest(addr, thread)); 965} 966 967void Sequencer::removeStoreRequest(const Address & addr, int thread){ 968 removeRequest(getWriteRequest(addr, thread)); 969} 970 971// returns the read CacheMsg 972CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){ 973 Address temp = addr; 974 assert(thread >= 0); 975 assert(temp == line_address(temp)); 976 assert(m_readRequestTable_ptr[thread]->exist(addr)); 977 return m_readRequestTable_ptr[thread]->lookup(addr); 978} 979 980CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){ 981 Address temp = addr; 982 assert(thread >= 0); 983 assert(temp == line_address(temp)); 984 assert(m_writeRequestTable_ptr[thread]->exist(addr)); 985 return m_writeRequestTable_ptr[thread]->lookup(addr); 986} 987 988void Sequencer::print(ostream& out) const { 989 out << "[Sequencer: " << m_chip_ptr->getID() 990 << ", outstanding requests: " << m_outstanding_count; 991 992 int smt_threads = RubyConfig::numberofSMTThreads(); 993 for(int p=0; p < smt_threads; ++p){ 994 out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p] 995 << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p]; 996 } 997 out << "]"; 998} 999 1000// this can be called from setState whenever coherence permissions are upgraded 1001// when invoked, coherence violations will be checked for the given block 1002void Sequencer::checkCoherence(const Address& addr) { 1003#ifdef CHECK_COHERENCE 1004 g_system_ptr->checkGlobalCoherenceInvariant(addr); 1005#endif 1006} 1007 1008bool Sequencer::getRubyMemoryValue(const Address& addr, char* value, 1009 unsigned int size_in_bytes ) { 1010 if(g_SIMICS){ 1011 for(unsigned int i=0; i < size_in_bytes; i++) { 1012 value[i] = SIMICS_read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, 1013 addr.getAddress() + i, 1 ); 1014 } 1015 return false; // Do nothing? 1016 } else { 1017 bool found = false; 1018 const Address lineAddr = line_address(addr); 1019 DataBlock data; 1020 PhysAddress paddr(addr); 1021 DataBlock* dataPtr = &data; 1022 Chip* n = dynamic_cast<Chip*>(m_chip_ptr); 1023 // LUKE - use variable names instead of macros 1024 assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL); 1025 assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL); 1026 1027 MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() ); 1028 int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip(); 1029 1030 if (Protocol::m_TwoLevelCache) { 1031 if(Protocol::m_CMP){ 1032 assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL); 1033 } 1034 else{ 1035 assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL); 1036 } 1037 } 1038 1039 if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){ 1040 n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes); 1041 found = true; 1042 } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1043 n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes); 1044 found = true; 1045 } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1046 n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes); 1047 found = true; 1048 // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){ 1049// ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)); 1050// L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr); 1051 1052// int offset = addr.getOffset(); 1053// for(int i=0; i<size_in_bytes; ++i){ 1054// value[i] = tbeEntry.getDataBlk().getByte(offset + i); 1055// } 1056 1057// found = true; 1058 } else { 1059 // Address not found 1060 //cout << " " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl; 1061 n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip())); 1062 int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip(); 1063 for(unsigned int i=0; i<size_in_bytes; ++i){ 1064 int offset = addr.getOffset(); 1065 value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i); 1066 } 1067 // Address not found 1068 //WARN_MSG("Couldn't find address"); 1069 //WARN_EXPR(addr); 1070 found = false; 1071 } 1072 return true; 1073 } 1074} 1075 1076bool Sequencer::setRubyMemoryValue(const Address& addr, char *value, 1077 unsigned int size_in_bytes) { 1078 char test_buffer[64]; 1079 1080 if(g_SIMICS){ 1081 return false; // Do nothing? 1082 } else { 1083 // idea here is that coherent cache should find the 1084 // latest data, the update it 1085 bool found = false; 1086 const Address lineAddr = line_address(addr); 1087 PhysAddress paddr(addr); 1088 DataBlock data; 1089 DataBlock* dataPtr = &data; 1090 Chip* n = dynamic_cast<Chip*>(m_chip_ptr); 1091 1092 MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() ); 1093 int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip(); 1094 // LUKE - use variable names instead of macros 1095 //cout << "number of L2caches per chip = " << RubyConfig::numberOfL2CachePerChip(m_version) << endl; 1096 //cout << "L1I cache vec size = " << n->m_L1Cache_L1IcacheMemory_vec.size() << endl; 1097 //cout << "L1D cache vec size = " << n->m_L1Cache_L1DcacheMemory_vec.size() << endl; 1098 //cout << "L1cache_cachememory size = " << n->m_L1Cache_cacheMemory_vec.size() << endl; 1099 //cout << "L1cache_l2cachememory size = " << n->m_L1Cache_L2cacheMemory_vec.size() << endl; 1100 // if (Protocol::m_TwoLevelCache) { 1101// if(Protocol::m_CMP){ 1102// cout << "CMP L2 cache vec size = " << n->m_L2Cache_L2cacheMemory_vec.size() << endl; 1103// } 1104// else{ 1105// cout << "L2 cache vec size = " << n->m_L1Cache_cacheMemory_vec.size() << endl; 1106// } 1107// } 1108 1109 assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL); 1110 assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL); 1111 if (Protocol::m_TwoLevelCache) { 1112 if(Protocol::m_CMP){ 1113 assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL); 1114 } 1115 else{ 1116 assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL); 1117 } 1118 } 1119 1120 if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){ 1121 n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes); 1122 found = true; 1123 } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1124 n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes); 1125 found = true; 1126 } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){ 1127 n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes); 1128 found = true; 1129 // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isTagPresent(lineAddr)){ 1130// L1Cache_TBE& tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr); 1131// DataBlock tmpData; 1132// int offset = addr.getOffset(); 1133// for(int i=0; i<size_in_bytes; ++i){ 1134// tmpData.setByte(offset + i, value[i]); 1135// } 1136// tbeEntry.setDataBlk(tmpData); 1137// tbeEntry.setDirty(true); 1138 } else { 1139 // Address not found 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 n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]); 1145 } 1146 found = false; 1147 } 1148 1149 if (found){ 1150 found = getRubyMemoryValue(addr, test_buffer, size_in_bytes); 1151 assert(found); 1152 if(value[0] != test_buffer[0]){ 1153 WARN_EXPR((int) value[0]); 1154 WARN_EXPR((int) test_buffer[0]); 1155 ERROR_MSG("setRubyMemoryValue failed to set value."); 1156 } 1157 } 1158 1159 return true; 1160 } 1161} 1162