1/* 2 * Copyright (c) 2005-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Korey Sewell 29 */ 30 31#include <algorithm> 32#include <list> 33#include <string> 34 35#include "cpu/o3/lsq.hh" 36 37template<class Impl> 38void 39LSQ<Impl>::DcachePort::setPeer(Port *port) 40{ 41 Port::setPeer(port); 42 43#if FULL_SYSTEM 44 // Update the ThreadContext's memory ports (Functional/Virtual 45 // Ports) 46 lsq->updateMemPorts(); 47#endif 48} 49 50template <class Impl> 51Tick 52LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 53{ 54 panic("O3CPU model does not work with atomic mode!"); 55 return curTick; 56} 57 58template <class Impl> 59void 60LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 61{ 62 DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional."); 63} 64 65template <class Impl> 66void 67LSQ<Impl>::DcachePort::recvStatusChange(Status status) 68{ 69 if (status == RangeChange) { 70 if (!snoopRangeSent) { 71 snoopRangeSent = true; 72 sendStatusChange(Port::RangeChange); 73 } 74 return; 75 } 76 panic("O3CPU doesn't expect recvStatusChange callback!"); 77} 78 79template <class Impl> 80bool 81LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 82{ 83 if (pkt->isResponse()) { 84 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 85 } 86 else { 87 //else it is a coherence request, maybe you need to do something 88 warn("Recieved a coherence request (Invalidate?), 03CPU doesn't" 89 "update LSQ for these\n"); 90 } 91 return true; 92} 93 94template <class Impl> 95void 96LSQ<Impl>::DcachePort::recvRetry() 97{ 98 if (lsq->retryTid == -1) 99 { 100 //Squashed, so drop it 101 return; 102 } 103 lsq->thread[lsq->retryTid].recvRetry(); 104 // Speculatively clear the retry Tid. This will get set again if 105 // the LSQUnit was unable to complete its access. 106 lsq->retryTid = -1; 107} 108 109template <class Impl> 110LSQ<Impl>::LSQ(Params *params) 111 : dcachePort(this), LQEntries(params->LQEntries), 112 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 113 retryTid(-1) 114{
| 1/* 2 * Copyright (c) 2005-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Korey Sewell 29 */ 30 31#include <algorithm> 32#include <list> 33#include <string> 34 35#include "cpu/o3/lsq.hh" 36 37template<class Impl> 38void 39LSQ<Impl>::DcachePort::setPeer(Port *port) 40{ 41 Port::setPeer(port); 42 43#if FULL_SYSTEM 44 // Update the ThreadContext's memory ports (Functional/Virtual 45 // Ports) 46 lsq->updateMemPorts(); 47#endif 48} 49 50template <class Impl> 51Tick 52LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 53{ 54 panic("O3CPU model does not work with atomic mode!"); 55 return curTick; 56} 57 58template <class Impl> 59void 60LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 61{ 62 DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional."); 63} 64 65template <class Impl> 66void 67LSQ<Impl>::DcachePort::recvStatusChange(Status status) 68{ 69 if (status == RangeChange) { 70 if (!snoopRangeSent) { 71 snoopRangeSent = true; 72 sendStatusChange(Port::RangeChange); 73 } 74 return; 75 } 76 panic("O3CPU doesn't expect recvStatusChange callback!"); 77} 78 79template <class Impl> 80bool 81LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 82{ 83 if (pkt->isResponse()) { 84 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 85 } 86 else { 87 //else it is a coherence request, maybe you need to do something 88 warn("Recieved a coherence request (Invalidate?), 03CPU doesn't" 89 "update LSQ for these\n"); 90 } 91 return true; 92} 93 94template <class Impl> 95void 96LSQ<Impl>::DcachePort::recvRetry() 97{ 98 if (lsq->retryTid == -1) 99 { 100 //Squashed, so drop it 101 return; 102 } 103 lsq->thread[lsq->retryTid].recvRetry(); 104 // Speculatively clear the retry Tid. This will get set again if 105 // the LSQUnit was unable to complete its access. 106 lsq->retryTid = -1; 107} 108 109template <class Impl> 110LSQ<Impl>::LSQ(Params *params) 111 : dcachePort(this), LQEntries(params->LQEntries), 112 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 113 retryTid(-1) 114{
|
115 DPRINTF(LSQ, "Creating LSQ object.\n"); 116
| |
117 dcachePort.snoopRangeSent = false; 118 119 //**********************************************/ 120 //************ Handle SMT Parameters ***********/ 121 //**********************************************/ 122 std::string policy = params->smtLSQPolicy; 123 124 //Convert string to lowercase 125 std::transform(policy.begin(), policy.end(), policy.begin(), 126 (int(*)(int)) tolower); 127 128 //Figure out fetch policy 129 if (policy == "dynamic") { 130 lsqPolicy = Dynamic; 131 132 maxLQEntries = LQEntries; 133 maxSQEntries = SQEntries;
| 115 dcachePort.snoopRangeSent = false; 116 117 //**********************************************/ 118 //************ Handle SMT Parameters ***********/ 119 //**********************************************/ 120 std::string policy = params->smtLSQPolicy; 121 122 //Convert string to lowercase 123 std::transform(policy.begin(), policy.end(), policy.begin(), 124 (int(*)(int)) tolower); 125 126 //Figure out fetch policy 127 if (policy == "dynamic") { 128 lsqPolicy = Dynamic; 129 130 maxLQEntries = LQEntries; 131 maxSQEntries = SQEntries;
|
134
| 132/*
|
135 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
| 133 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
|
136
| 134*/
|
137 } else if (policy == "partitioned") { 138 lsqPolicy = Partitioned; 139 140 //@todo:make work if part_amt doesnt divide evenly. 141 maxLQEntries = LQEntries / numThreads; 142 maxSQEntries = SQEntries / numThreads;
| 135 } else if (policy == "partitioned") { 136 lsqPolicy = Partitioned; 137 138 //@todo:make work if part_amt doesnt divide evenly. 139 maxLQEntries = LQEntries / numThreads; 140 maxSQEntries = SQEntries / numThreads;
|
143
| 141/*
|
144 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 145 "%i entries per LQ | %i entries per SQ", 146 maxLQEntries,maxSQEntries);
| 142 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 143 "%i entries per LQ | %i entries per SQ", 144 maxLQEntries,maxSQEntries);
|
147
| 145*/
|
148 } else if (policy == "threshold") { 149 lsqPolicy = Threshold; 150 151 assert(params->smtLSQThreshold > LQEntries); 152 assert(params->smtLSQThreshold > SQEntries); 153 154 //Divide up by threshold amount 155 //@todo: Should threads check the max and the total 156 //amount of the LSQ 157 maxLQEntries = params->smtLSQThreshold; 158 maxSQEntries = params->smtLSQThreshold;
| 146 } else if (policy == "threshold") { 147 lsqPolicy = Threshold; 148 149 assert(params->smtLSQThreshold > LQEntries); 150 assert(params->smtLSQThreshold > SQEntries); 151 152 //Divide up by threshold amount 153 //@todo: Should threads check the max and the total 154 //amount of the LSQ 155 maxLQEntries = params->smtLSQThreshold; 156 maxSQEntries = params->smtLSQThreshold;
|
159
| 157/*
|
160 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 161 "%i entries per LQ | %i entries per SQ", 162 maxLQEntries,maxSQEntries);
| 158 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 159 "%i entries per LQ | %i entries per SQ", 160 maxLQEntries,maxSQEntries);
|
| 161*/
|
163 164 } else { 165 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 166 "Partitioned, Threshold}"); 167 } 168 169 //Initialize LSQs 170 for (int tid=0; tid < numThreads; tid++) { 171 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 172 thread[tid].setDcachePort(&dcachePort); 173 } 174} 175 176 177template<class Impl> 178std::string 179LSQ<Impl>::name() const 180{ 181 return iewStage->name() + ".lsq"; 182} 183 184template<class Impl> 185void 186LSQ<Impl>::regStats() 187{ 188 //Initialize LSQs 189 for (int tid=0; tid < numThreads; tid++) { 190 thread[tid].regStats(); 191 } 192} 193 194template<class Impl> 195void 196LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 197{ 198 activeThreads = at_ptr; 199 assert(activeThreads != 0); 200} 201 202template<class Impl> 203void 204LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 205{ 206 cpu = cpu_ptr; 207 208 dcachePort.setName(name()); 209 210 for (int tid=0; tid < numThreads; tid++) { 211 thread[tid].setCPU(cpu_ptr); 212 } 213} 214 215template<class Impl> 216void 217LSQ<Impl>::setIEW(IEW *iew_ptr) 218{ 219 iewStage = iew_ptr; 220 221 for (int tid=0; tid < numThreads; tid++) { 222 thread[tid].setIEW(iew_ptr); 223 } 224} 225 226template <class Impl> 227void 228LSQ<Impl>::switchOut() 229{ 230 for (int tid = 0; tid < numThreads; tid++) { 231 thread[tid].switchOut(); 232 } 233} 234 235template <class Impl> 236void 237LSQ<Impl>::takeOverFrom() 238{ 239 for (int tid = 0; tid < numThreads; tid++) { 240 thread[tid].takeOverFrom(); 241 } 242} 243 244template <class Impl> 245int 246LSQ<Impl>::entryAmount(int num_threads) 247{ 248 if (lsqPolicy == Partitioned) { 249 return LQEntries / num_threads; 250 } else { 251 return 0; 252 } 253} 254 255template <class Impl> 256void 257LSQ<Impl>::resetEntries() 258{ 259 if (lsqPolicy != Dynamic || numThreads > 1) { 260 int active_threads = activeThreads->size(); 261 262 int maxEntries; 263 264 if (lsqPolicy == Partitioned) { 265 maxEntries = LQEntries / active_threads; 266 } else if (lsqPolicy == Threshold && active_threads == 1) { 267 maxEntries = LQEntries; 268 } else { 269 maxEntries = LQEntries; 270 } 271 272 std::list<unsigned>::iterator threads = activeThreads->begin(); 273 std::list<unsigned>::iterator end = activeThreads->end(); 274 275 while (threads != end) { 276 unsigned tid = *threads++; 277 278 resizeEntries(maxEntries, tid); 279 } 280 } 281} 282 283template<class Impl> 284void 285LSQ<Impl>::removeEntries(unsigned tid) 286{ 287 thread[tid].clearLQ(); 288 thread[tid].clearSQ(); 289} 290 291template<class Impl> 292void 293LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 294{ 295 thread[tid].resizeLQ(size); 296 thread[tid].resizeSQ(size); 297} 298 299template<class Impl> 300void 301LSQ<Impl>::tick() 302{ 303 std::list<unsigned>::iterator threads = activeThreads->begin(); 304 std::list<unsigned>::iterator end = activeThreads->end(); 305 306 while (threads != end) { 307 unsigned tid = *threads++; 308 309 thread[tid].tick(); 310 } 311} 312 313template<class Impl> 314void 315LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 316{ 317 unsigned tid = load_inst->threadNumber; 318 319 thread[tid].insertLoad(load_inst); 320} 321 322template<class Impl> 323void 324LSQ<Impl>::insertStore(DynInstPtr &store_inst) 325{ 326 unsigned tid = store_inst->threadNumber; 327 328 thread[tid].insertStore(store_inst); 329} 330 331template<class Impl> 332Fault 333LSQ<Impl>::executeLoad(DynInstPtr &inst) 334{ 335 unsigned tid = inst->threadNumber; 336 337 return thread[tid].executeLoad(inst); 338} 339 340template<class Impl> 341Fault 342LSQ<Impl>::executeStore(DynInstPtr &inst) 343{ 344 unsigned tid = inst->threadNumber; 345 346 return thread[tid].executeStore(inst); 347} 348 349template<class Impl> 350void 351LSQ<Impl>::writebackStores() 352{ 353 std::list<unsigned>::iterator threads = activeThreads->begin(); 354 std::list<unsigned>::iterator end = activeThreads->end(); 355 356 while (threads != end) { 357 unsigned tid = *threads++; 358 359 if (numStoresToWB(tid) > 0) { 360 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 361 "available for Writeback.\n", tid, numStoresToWB(tid)); 362 } 363 364 thread[tid].writebackStores(); 365 } 366} 367 368template<class Impl> 369bool 370LSQ<Impl>::violation() 371{ 372 /* Answers: Does Anybody Have a Violation?*/ 373 std::list<unsigned>::iterator threads = activeThreads->begin(); 374 std::list<unsigned>::iterator end = activeThreads->end(); 375 376 while (threads != end) { 377 unsigned tid = *threads++; 378 379 if (thread[tid].violation()) 380 return true; 381 } 382 383 return false; 384} 385 386template<class Impl> 387int 388LSQ<Impl>::getCount() 389{ 390 unsigned total = 0; 391 392 std::list<unsigned>::iterator threads = activeThreads->begin(); 393 std::list<unsigned>::iterator end = activeThreads->end(); 394 395 while (threads != end) { 396 unsigned tid = *threads++; 397 398 total += getCount(tid); 399 } 400 401 return total; 402} 403 404template<class Impl> 405int 406LSQ<Impl>::numLoads() 407{ 408 unsigned total = 0; 409 410 std::list<unsigned>::iterator threads = activeThreads->begin(); 411 std::list<unsigned>::iterator end = activeThreads->end(); 412 413 while (threads != end) { 414 unsigned tid = *threads++; 415 416 total += numLoads(tid); 417 } 418 419 return total; 420} 421 422template<class Impl> 423int 424LSQ<Impl>::numStores() 425{ 426 unsigned total = 0; 427 428 std::list<unsigned>::iterator threads = activeThreads->begin(); 429 std::list<unsigned>::iterator end = activeThreads->end(); 430 431 while (threads != end) { 432 unsigned tid = *threads++; 433 434 total += thread[tid].numStores(); 435 } 436 437 return total; 438} 439 440template<class Impl> 441int 442LSQ<Impl>::numLoadsReady() 443{ 444 unsigned total = 0; 445 446 std::list<unsigned>::iterator threads = activeThreads->begin(); 447 std::list<unsigned>::iterator end = activeThreads->end(); 448 449 while (threads != end) { 450 unsigned tid = *threads++; 451 452 total += thread[tid].numLoadsReady(); 453 } 454 455 return total; 456} 457 458template<class Impl> 459unsigned 460LSQ<Impl>::numFreeEntries() 461{ 462 unsigned total = 0; 463 464 std::list<unsigned>::iterator threads = activeThreads->begin(); 465 std::list<unsigned>::iterator end = activeThreads->end(); 466 467 while (threads != end) { 468 unsigned tid = *threads++; 469 470 total += thread[tid].numFreeEntries(); 471 } 472 473 return total; 474} 475 476template<class Impl> 477unsigned 478LSQ<Impl>::numFreeEntries(unsigned tid) 479{ 480 //if (lsqPolicy == Dynamic) 481 //return numFreeEntries(); 482 //else 483 return thread[tid].numFreeEntries(); 484} 485 486template<class Impl> 487bool 488LSQ<Impl>::isFull() 489{ 490 std::list<unsigned>::iterator threads = activeThreads->begin(); 491 std::list<unsigned>::iterator end = activeThreads->end(); 492 493 while (threads != end) { 494 unsigned tid = *threads++; 495 496 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 497 return false; 498 } 499 500 return true; 501} 502 503template<class Impl> 504bool 505LSQ<Impl>::isFull(unsigned tid) 506{ 507 //@todo: Change to Calculate All Entries for 508 //Dynamic Policy 509 if (lsqPolicy == Dynamic) 510 return isFull(); 511 else 512 return thread[tid].lqFull() || thread[tid].sqFull(); 513} 514 515template<class Impl> 516bool 517LSQ<Impl>::lqFull() 518{ 519 std::list<unsigned>::iterator threads = activeThreads->begin(); 520 std::list<unsigned>::iterator end = activeThreads->end(); 521 522 while (threads != end) { 523 unsigned tid = *threads++; 524 525 if (!thread[tid].lqFull()) 526 return false; 527 } 528 529 return true; 530} 531 532template<class Impl> 533bool 534LSQ<Impl>::lqFull(unsigned tid) 535{ 536 //@todo: Change to Calculate All Entries for 537 //Dynamic Policy 538 if (lsqPolicy == Dynamic) 539 return lqFull(); 540 else 541 return thread[tid].lqFull(); 542} 543 544template<class Impl> 545bool 546LSQ<Impl>::sqFull() 547{ 548 std::list<unsigned>::iterator threads = activeThreads->begin(); 549 std::list<unsigned>::iterator end = activeThreads->end(); 550 551 while (threads != end) { 552 unsigned tid = *threads++; 553 554 if (!sqFull(tid)) 555 return false; 556 } 557 558 return true; 559} 560 561template<class Impl> 562bool 563LSQ<Impl>::sqFull(unsigned tid) 564{ 565 //@todo: Change to Calculate All Entries for 566 //Dynamic Policy 567 if (lsqPolicy == Dynamic) 568 return sqFull(); 569 else 570 return thread[tid].sqFull(); 571} 572 573template<class Impl> 574bool 575LSQ<Impl>::isStalled() 576{ 577 std::list<unsigned>::iterator threads = activeThreads->begin(); 578 std::list<unsigned>::iterator end = activeThreads->end(); 579 580 while (threads != end) { 581 unsigned tid = *threads++; 582 583 if (!thread[tid].isStalled()) 584 return false; 585 } 586 587 return true; 588} 589 590template<class Impl> 591bool 592LSQ<Impl>::isStalled(unsigned tid) 593{ 594 if (lsqPolicy == Dynamic) 595 return isStalled(); 596 else 597 return thread[tid].isStalled(); 598} 599 600template<class Impl> 601bool 602LSQ<Impl>::hasStoresToWB() 603{ 604 std::list<unsigned>::iterator threads = activeThreads->begin(); 605 std::list<unsigned>::iterator end = activeThreads->end(); 606 607 if (threads == end) 608 return false; 609 610 while (threads != end) { 611 unsigned tid = *threads++; 612 613 if (!hasStoresToWB(tid)) 614 return false; 615 } 616 617 return true; 618} 619 620template<class Impl> 621bool 622LSQ<Impl>::willWB() 623{ 624 std::list<unsigned>::iterator threads = activeThreads->begin(); 625 std::list<unsigned>::iterator end = activeThreads->end(); 626 627 while (threads != end) { 628 unsigned tid = *threads++; 629 630 if (!willWB(tid)) 631 return false; 632 } 633 634 return true; 635} 636 637template<class Impl> 638void 639LSQ<Impl>::dumpInsts() 640{ 641 std::list<unsigned>::iterator threads = activeThreads->begin(); 642 std::list<unsigned>::iterator end = activeThreads->end(); 643 644 while (threads != end) { 645 unsigned tid = *threads++; 646 647 thread[tid].dumpInsts(); 648 } 649}
| 162 163 } else { 164 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 165 "Partitioned, Threshold}"); 166 } 167 168 //Initialize LSQs 169 for (int tid=0; tid < numThreads; tid++) { 170 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 171 thread[tid].setDcachePort(&dcachePort); 172 } 173} 174 175 176template<class Impl> 177std::string 178LSQ<Impl>::name() const 179{ 180 return iewStage->name() + ".lsq"; 181} 182 183template<class Impl> 184void 185LSQ<Impl>::regStats() 186{ 187 //Initialize LSQs 188 for (int tid=0; tid < numThreads; tid++) { 189 thread[tid].regStats(); 190 } 191} 192 193template<class Impl> 194void 195LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 196{ 197 activeThreads = at_ptr; 198 assert(activeThreads != 0); 199} 200 201template<class Impl> 202void 203LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 204{ 205 cpu = cpu_ptr; 206 207 dcachePort.setName(name()); 208 209 for (int tid=0; tid < numThreads; tid++) { 210 thread[tid].setCPU(cpu_ptr); 211 } 212} 213 214template<class Impl> 215void 216LSQ<Impl>::setIEW(IEW *iew_ptr) 217{ 218 iewStage = iew_ptr; 219 220 for (int tid=0; tid < numThreads; tid++) { 221 thread[tid].setIEW(iew_ptr); 222 } 223} 224 225template <class Impl> 226void 227LSQ<Impl>::switchOut() 228{ 229 for (int tid = 0; tid < numThreads; tid++) { 230 thread[tid].switchOut(); 231 } 232} 233 234template <class Impl> 235void 236LSQ<Impl>::takeOverFrom() 237{ 238 for (int tid = 0; tid < numThreads; tid++) { 239 thread[tid].takeOverFrom(); 240 } 241} 242 243template <class Impl> 244int 245LSQ<Impl>::entryAmount(int num_threads) 246{ 247 if (lsqPolicy == Partitioned) { 248 return LQEntries / num_threads; 249 } else { 250 return 0; 251 } 252} 253 254template <class Impl> 255void 256LSQ<Impl>::resetEntries() 257{ 258 if (lsqPolicy != Dynamic || numThreads > 1) { 259 int active_threads = activeThreads->size(); 260 261 int maxEntries; 262 263 if (lsqPolicy == Partitioned) { 264 maxEntries = LQEntries / active_threads; 265 } else if (lsqPolicy == Threshold && active_threads == 1) { 266 maxEntries = LQEntries; 267 } else { 268 maxEntries = LQEntries; 269 } 270 271 std::list<unsigned>::iterator threads = activeThreads->begin(); 272 std::list<unsigned>::iterator end = activeThreads->end(); 273 274 while (threads != end) { 275 unsigned tid = *threads++; 276 277 resizeEntries(maxEntries, tid); 278 } 279 } 280} 281 282template<class Impl> 283void 284LSQ<Impl>::removeEntries(unsigned tid) 285{ 286 thread[tid].clearLQ(); 287 thread[tid].clearSQ(); 288} 289 290template<class Impl> 291void 292LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 293{ 294 thread[tid].resizeLQ(size); 295 thread[tid].resizeSQ(size); 296} 297 298template<class Impl> 299void 300LSQ<Impl>::tick() 301{ 302 std::list<unsigned>::iterator threads = activeThreads->begin(); 303 std::list<unsigned>::iterator end = activeThreads->end(); 304 305 while (threads != end) { 306 unsigned tid = *threads++; 307 308 thread[tid].tick(); 309 } 310} 311 312template<class Impl> 313void 314LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 315{ 316 unsigned tid = load_inst->threadNumber; 317 318 thread[tid].insertLoad(load_inst); 319} 320 321template<class Impl> 322void 323LSQ<Impl>::insertStore(DynInstPtr &store_inst) 324{ 325 unsigned tid = store_inst->threadNumber; 326 327 thread[tid].insertStore(store_inst); 328} 329 330template<class Impl> 331Fault 332LSQ<Impl>::executeLoad(DynInstPtr &inst) 333{ 334 unsigned tid = inst->threadNumber; 335 336 return thread[tid].executeLoad(inst); 337} 338 339template<class Impl> 340Fault 341LSQ<Impl>::executeStore(DynInstPtr &inst) 342{ 343 unsigned tid = inst->threadNumber; 344 345 return thread[tid].executeStore(inst); 346} 347 348template<class Impl> 349void 350LSQ<Impl>::writebackStores() 351{ 352 std::list<unsigned>::iterator threads = activeThreads->begin(); 353 std::list<unsigned>::iterator end = activeThreads->end(); 354 355 while (threads != end) { 356 unsigned tid = *threads++; 357 358 if (numStoresToWB(tid) > 0) { 359 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 360 "available for Writeback.\n", tid, numStoresToWB(tid)); 361 } 362 363 thread[tid].writebackStores(); 364 } 365} 366 367template<class Impl> 368bool 369LSQ<Impl>::violation() 370{ 371 /* Answers: Does Anybody Have a Violation?*/ 372 std::list<unsigned>::iterator threads = activeThreads->begin(); 373 std::list<unsigned>::iterator end = activeThreads->end(); 374 375 while (threads != end) { 376 unsigned tid = *threads++; 377 378 if (thread[tid].violation()) 379 return true; 380 } 381 382 return false; 383} 384 385template<class Impl> 386int 387LSQ<Impl>::getCount() 388{ 389 unsigned total = 0; 390 391 std::list<unsigned>::iterator threads = activeThreads->begin(); 392 std::list<unsigned>::iterator end = activeThreads->end(); 393 394 while (threads != end) { 395 unsigned tid = *threads++; 396 397 total += getCount(tid); 398 } 399 400 return total; 401} 402 403template<class Impl> 404int 405LSQ<Impl>::numLoads() 406{ 407 unsigned total = 0; 408 409 std::list<unsigned>::iterator threads = activeThreads->begin(); 410 std::list<unsigned>::iterator end = activeThreads->end(); 411 412 while (threads != end) { 413 unsigned tid = *threads++; 414 415 total += numLoads(tid); 416 } 417 418 return total; 419} 420 421template<class Impl> 422int 423LSQ<Impl>::numStores() 424{ 425 unsigned total = 0; 426 427 std::list<unsigned>::iterator threads = activeThreads->begin(); 428 std::list<unsigned>::iterator end = activeThreads->end(); 429 430 while (threads != end) { 431 unsigned tid = *threads++; 432 433 total += thread[tid].numStores(); 434 } 435 436 return total; 437} 438 439template<class Impl> 440int 441LSQ<Impl>::numLoadsReady() 442{ 443 unsigned total = 0; 444 445 std::list<unsigned>::iterator threads = activeThreads->begin(); 446 std::list<unsigned>::iterator end = activeThreads->end(); 447 448 while (threads != end) { 449 unsigned tid = *threads++; 450 451 total += thread[tid].numLoadsReady(); 452 } 453 454 return total; 455} 456 457template<class Impl> 458unsigned 459LSQ<Impl>::numFreeEntries() 460{ 461 unsigned total = 0; 462 463 std::list<unsigned>::iterator threads = activeThreads->begin(); 464 std::list<unsigned>::iterator end = activeThreads->end(); 465 466 while (threads != end) { 467 unsigned tid = *threads++; 468 469 total += thread[tid].numFreeEntries(); 470 } 471 472 return total; 473} 474 475template<class Impl> 476unsigned 477LSQ<Impl>::numFreeEntries(unsigned tid) 478{ 479 //if (lsqPolicy == Dynamic) 480 //return numFreeEntries(); 481 //else 482 return thread[tid].numFreeEntries(); 483} 484 485template<class Impl> 486bool 487LSQ<Impl>::isFull() 488{ 489 std::list<unsigned>::iterator threads = activeThreads->begin(); 490 std::list<unsigned>::iterator end = activeThreads->end(); 491 492 while (threads != end) { 493 unsigned tid = *threads++; 494 495 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 496 return false; 497 } 498 499 return true; 500} 501 502template<class Impl> 503bool 504LSQ<Impl>::isFull(unsigned tid) 505{ 506 //@todo: Change to Calculate All Entries for 507 //Dynamic Policy 508 if (lsqPolicy == Dynamic) 509 return isFull(); 510 else 511 return thread[tid].lqFull() || thread[tid].sqFull(); 512} 513 514template<class Impl> 515bool 516LSQ<Impl>::lqFull() 517{ 518 std::list<unsigned>::iterator threads = activeThreads->begin(); 519 std::list<unsigned>::iterator end = activeThreads->end(); 520 521 while (threads != end) { 522 unsigned tid = *threads++; 523 524 if (!thread[tid].lqFull()) 525 return false; 526 } 527 528 return true; 529} 530 531template<class Impl> 532bool 533LSQ<Impl>::lqFull(unsigned tid) 534{ 535 //@todo: Change to Calculate All Entries for 536 //Dynamic Policy 537 if (lsqPolicy == Dynamic) 538 return lqFull(); 539 else 540 return thread[tid].lqFull(); 541} 542 543template<class Impl> 544bool 545LSQ<Impl>::sqFull() 546{ 547 std::list<unsigned>::iterator threads = activeThreads->begin(); 548 std::list<unsigned>::iterator end = activeThreads->end(); 549 550 while (threads != end) { 551 unsigned tid = *threads++; 552 553 if (!sqFull(tid)) 554 return false; 555 } 556 557 return true; 558} 559 560template<class Impl> 561bool 562LSQ<Impl>::sqFull(unsigned tid) 563{ 564 //@todo: Change to Calculate All Entries for 565 //Dynamic Policy 566 if (lsqPolicy == Dynamic) 567 return sqFull(); 568 else 569 return thread[tid].sqFull(); 570} 571 572template<class Impl> 573bool 574LSQ<Impl>::isStalled() 575{ 576 std::list<unsigned>::iterator threads = activeThreads->begin(); 577 std::list<unsigned>::iterator end = activeThreads->end(); 578 579 while (threads != end) { 580 unsigned tid = *threads++; 581 582 if (!thread[tid].isStalled()) 583 return false; 584 } 585 586 return true; 587} 588 589template<class Impl> 590bool 591LSQ<Impl>::isStalled(unsigned tid) 592{ 593 if (lsqPolicy == Dynamic) 594 return isStalled(); 595 else 596 return thread[tid].isStalled(); 597} 598 599template<class Impl> 600bool 601LSQ<Impl>::hasStoresToWB() 602{ 603 std::list<unsigned>::iterator threads = activeThreads->begin(); 604 std::list<unsigned>::iterator end = activeThreads->end(); 605 606 if (threads == end) 607 return false; 608 609 while (threads != end) { 610 unsigned tid = *threads++; 611 612 if (!hasStoresToWB(tid)) 613 return false; 614 } 615 616 return true; 617} 618 619template<class Impl> 620bool 621LSQ<Impl>::willWB() 622{ 623 std::list<unsigned>::iterator threads = activeThreads->begin(); 624 std::list<unsigned>::iterator end = activeThreads->end(); 625 626 while (threads != end) { 627 unsigned tid = *threads++; 628 629 if (!willWB(tid)) 630 return false; 631 } 632 633 return true; 634} 635 636template<class Impl> 637void 638LSQ<Impl>::dumpInsts() 639{ 640 std::list<unsigned>::iterator threads = activeThreads->begin(); 641 std::list<unsigned>::iterator end = activeThreads->end(); 642 643 while (threads != end) { 644 unsigned tid = *threads++; 645 646 thread[tid].dumpInsts(); 647 } 648}
|