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> 38Tick 39LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 40{ 41 panic("O3CPU model does not work with atomic mode!"); 42 return curTick; 43} 44 45template <class Impl> 46void 47LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 48{ 49 DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional."); 50} 51 52template <class Impl> 53void 54LSQ<Impl>::DcachePort::recvStatusChange(Status status) 55{
| 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> 38Tick 39LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 40{ 41 panic("O3CPU model does not work with atomic mode!"); 42 return curTick; 43} 44 45template <class Impl> 46void 47LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 48{ 49 DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional."); 50} 51 52template <class Impl> 53void 54LSQ<Impl>::DcachePort::recvStatusChange(Status status) 55{
|
56 if (status == RangeChange)
| 56 if (status == RangeChange) { 57 if (!snoopRangeSent) { 58 snoopRangeSent = true; 59 sendStatusChange(Port::RangeChange); 60 }
|
57 return;
| 61 return;
|
58
| 62 }
|
59 panic("O3CPU doesn't expect recvStatusChange callback!"); 60} 61 62template <class Impl> 63bool 64LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 65{ 66 if (pkt->isResponse()) { 67 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 68 } 69 else { 70 //else it is a coherence request, maybe you need to do something 71 warn("Recieved a coherence request (Invalidate?), 03CPU doesn't" 72 "update LSQ for these\n"); 73 } 74 return true; 75} 76 77template <class Impl> 78void 79LSQ<Impl>::DcachePort::recvRetry() 80{ 81 if (lsq->retryTid == -1) 82 { 83 //Squashed, so drop it 84 return; 85 } 86 lsq->thread[lsq->retryTid].recvRetry(); 87 // Speculatively clear the retry Tid. This will get set again if 88 // the LSQUnit was unable to complete its access. 89 lsq->retryTid = -1; 90} 91 92template <class Impl> 93LSQ<Impl>::LSQ(Params *params) 94 : dcachePort(this), LQEntries(params->LQEntries), 95 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 96 retryTid(-1) 97{ 98 DPRINTF(LSQ, "Creating LSQ object.\n"); 99
| 63 panic("O3CPU doesn't expect recvStatusChange callback!"); 64} 65 66template <class Impl> 67bool 68LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 69{ 70 if (pkt->isResponse()) { 71 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 72 } 73 else { 74 //else it is a coherence request, maybe you need to do something 75 warn("Recieved a coherence request (Invalidate?), 03CPU doesn't" 76 "update LSQ for these\n"); 77 } 78 return true; 79} 80 81template <class Impl> 82void 83LSQ<Impl>::DcachePort::recvRetry() 84{ 85 if (lsq->retryTid == -1) 86 { 87 //Squashed, so drop it 88 return; 89 } 90 lsq->thread[lsq->retryTid].recvRetry(); 91 // Speculatively clear the retry Tid. This will get set again if 92 // the LSQUnit was unable to complete its access. 93 lsq->retryTid = -1; 94} 95 96template <class Impl> 97LSQ<Impl>::LSQ(Params *params) 98 : dcachePort(this), LQEntries(params->LQEntries), 99 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 100 retryTid(-1) 101{ 102 DPRINTF(LSQ, "Creating LSQ object.\n"); 103
|
| 104 dcachePort.snoopRangeSent = false; 105
|
100 //**********************************************/ 101 //************ Handle SMT Parameters ***********/ 102 //**********************************************/ 103 std::string policy = params->smtLSQPolicy; 104 105 //Convert string to lowercase 106 std::transform(policy.begin(), policy.end(), policy.begin(), 107 (int(*)(int)) tolower); 108 109 //Figure out fetch policy 110 if (policy == "dynamic") { 111 lsqPolicy = Dynamic; 112 113 maxLQEntries = LQEntries; 114 maxSQEntries = SQEntries; 115 116 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 117 118 } else if (policy == "partitioned") { 119 lsqPolicy = Partitioned; 120 121 //@todo:make work if part_amt doesnt divide evenly. 122 maxLQEntries = LQEntries / numThreads; 123 maxSQEntries = SQEntries / numThreads; 124 125 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 126 "%i entries per LQ | %i entries per SQ", 127 maxLQEntries,maxSQEntries); 128 129 } else if (policy == "threshold") { 130 lsqPolicy = Threshold; 131 132 assert(params->smtLSQThreshold > LQEntries); 133 assert(params->smtLSQThreshold > SQEntries); 134 135 //Divide up by threshold amount 136 //@todo: Should threads check the max and the total 137 //amount of the LSQ 138 maxLQEntries = params->smtLSQThreshold; 139 maxSQEntries = params->smtLSQThreshold; 140 141 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 142 "%i entries per LQ | %i entries per SQ", 143 maxLQEntries,maxSQEntries); 144 145 } else { 146 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 147 "Partitioned, Threshold}"); 148 } 149 150 //Initialize LSQs 151 for (int tid=0; tid < numThreads; tid++) { 152 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 153 thread[tid].setDcachePort(&dcachePort); 154 } 155} 156 157 158template<class Impl> 159std::string 160LSQ<Impl>::name() const 161{ 162 return iewStage->name() + ".lsq"; 163} 164 165template<class Impl> 166void 167LSQ<Impl>::regStats() 168{ 169 //Initialize LSQs 170 for (int tid=0; tid < numThreads; tid++) { 171 thread[tid].regStats(); 172 } 173} 174 175template<class Impl> 176void 177LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 178{ 179 activeThreads = at_ptr; 180 assert(activeThreads != 0); 181} 182 183template<class Impl> 184void 185LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 186{ 187 cpu = cpu_ptr; 188 189 dcachePort.setName(name()); 190 191 for (int tid=0; tid < numThreads; tid++) { 192 thread[tid].setCPU(cpu_ptr); 193 } 194} 195 196template<class Impl> 197void 198LSQ<Impl>::setIEW(IEW *iew_ptr) 199{ 200 iewStage = iew_ptr; 201 202 for (int tid=0; tid < numThreads; tid++) { 203 thread[tid].setIEW(iew_ptr); 204 } 205} 206 207template <class Impl> 208void 209LSQ<Impl>::switchOut() 210{ 211 for (int tid = 0; tid < numThreads; tid++) { 212 thread[tid].switchOut(); 213 } 214} 215 216template <class Impl> 217void 218LSQ<Impl>::takeOverFrom() 219{ 220 for (int tid = 0; tid < numThreads; tid++) { 221 thread[tid].takeOverFrom(); 222 } 223} 224 225template <class Impl> 226int 227LSQ<Impl>::entryAmount(int num_threads) 228{ 229 if (lsqPolicy == Partitioned) { 230 return LQEntries / num_threads; 231 } else { 232 return 0; 233 } 234} 235 236template <class Impl> 237void 238LSQ<Impl>::resetEntries() 239{ 240 if (lsqPolicy != Dynamic || numThreads > 1) { 241 int active_threads = (*activeThreads).size(); 242 243 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 244 std::list<unsigned>::iterator list_end = (*activeThreads).end(); 245 246 int maxEntries; 247 248 if (lsqPolicy == Partitioned) { 249 maxEntries = LQEntries / active_threads; 250 } else if (lsqPolicy == Threshold && active_threads == 1) { 251 maxEntries = LQEntries; 252 } else { 253 maxEntries = LQEntries; 254 } 255 256 while (threads != list_end) { 257 resizeEntries(maxEntries,*threads++); 258 } 259 } 260} 261 262template<class Impl> 263void 264LSQ<Impl>::removeEntries(unsigned tid) 265{ 266 thread[tid].clearLQ(); 267 thread[tid].clearSQ(); 268} 269 270template<class Impl> 271void 272LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 273{ 274 thread[tid].resizeLQ(size); 275 thread[tid].resizeSQ(size); 276} 277 278template<class Impl> 279void 280LSQ<Impl>::tick() 281{ 282 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 283 284 while (active_threads != (*activeThreads).end()) { 285 unsigned tid = *active_threads++; 286 287 thread[tid].tick(); 288 } 289} 290 291template<class Impl> 292void 293LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 294{ 295 unsigned tid = load_inst->threadNumber; 296 297 thread[tid].insertLoad(load_inst); 298} 299 300template<class Impl> 301void 302LSQ<Impl>::insertStore(DynInstPtr &store_inst) 303{ 304 unsigned tid = store_inst->threadNumber; 305 306 thread[tid].insertStore(store_inst); 307} 308 309template<class Impl> 310Fault 311LSQ<Impl>::executeLoad(DynInstPtr &inst) 312{ 313 unsigned tid = inst->threadNumber; 314 315 return thread[tid].executeLoad(inst); 316} 317 318template<class Impl> 319Fault 320LSQ<Impl>::executeStore(DynInstPtr &inst) 321{ 322 unsigned tid = inst->threadNumber; 323 324 return thread[tid].executeStore(inst); 325} 326 327template<class Impl> 328void 329LSQ<Impl>::writebackStores() 330{ 331 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 332 333 while (active_threads != (*activeThreads).end()) { 334 unsigned tid = *active_threads++; 335 336 if (numStoresToWB(tid) > 0) { 337 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 338 "available for Writeback.\n", tid, numStoresToWB(tid)); 339 } 340 341 thread[tid].writebackStores(); 342 } 343} 344 345template<class Impl> 346bool 347LSQ<Impl>::violation() 348{ 349 /* Answers: Does Anybody Have a Violation?*/ 350 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 351 352 while (active_threads != (*activeThreads).end()) { 353 unsigned tid = *active_threads++; 354 if (thread[tid].violation()) 355 return true; 356 } 357 358 return false; 359} 360 361template<class Impl> 362int 363LSQ<Impl>::getCount() 364{ 365 unsigned total = 0; 366 367 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 368 369 while (active_threads != (*activeThreads).end()) { 370 unsigned tid = *active_threads++; 371 total += getCount(tid); 372 } 373 374 return total; 375} 376 377template<class Impl> 378int 379LSQ<Impl>::numLoads() 380{ 381 unsigned total = 0; 382 383 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 384 385 while (active_threads != (*activeThreads).end()) { 386 unsigned tid = *active_threads++; 387 total += numLoads(tid); 388 } 389 390 return total; 391} 392 393template<class Impl> 394int 395LSQ<Impl>::numStores() 396{ 397 unsigned total = 0; 398 399 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 400 401 while (active_threads != (*activeThreads).end()) { 402 unsigned tid = *active_threads++; 403 total += thread[tid].numStores(); 404 } 405 406 return total; 407} 408 409template<class Impl> 410int 411LSQ<Impl>::numLoadsReady() 412{ 413 unsigned total = 0; 414 415 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 416 417 while (active_threads != (*activeThreads).end()) { 418 unsigned tid = *active_threads++; 419 total += thread[tid].numLoadsReady(); 420 } 421 422 return total; 423} 424 425template<class Impl> 426unsigned 427LSQ<Impl>::numFreeEntries() 428{ 429 unsigned total = 0; 430 431 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 432 433 while (active_threads != (*activeThreads).end()) { 434 unsigned tid = *active_threads++; 435 total += thread[tid].numFreeEntries(); 436 } 437 438 return total; 439} 440 441template<class Impl> 442unsigned 443LSQ<Impl>::numFreeEntries(unsigned tid) 444{ 445 //if( lsqPolicy == Dynamic ) 446 //return numFreeEntries(); 447 //else 448 return thread[tid].numFreeEntries(); 449} 450 451template<class Impl> 452bool 453LSQ<Impl>::isFull() 454{ 455 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 456 457 while (active_threads != (*activeThreads).end()) { 458 unsigned tid = *active_threads++; 459 if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 460 return false; 461 } 462 463 return true; 464} 465 466template<class Impl> 467bool 468LSQ<Impl>::isFull(unsigned tid) 469{ 470 //@todo: Change to Calculate All Entries for 471 //Dynamic Policy 472 if( lsqPolicy == Dynamic ) 473 return isFull(); 474 else 475 return thread[tid].lqFull() || thread[tid].sqFull(); 476} 477 478template<class Impl> 479bool 480LSQ<Impl>::lqFull() 481{ 482 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 483 484 while (active_threads != (*activeThreads).end()) { 485 unsigned tid = *active_threads++; 486 if (!thread[tid].lqFull()) 487 return false; 488 } 489 490 return true; 491} 492 493template<class Impl> 494bool 495LSQ<Impl>::lqFull(unsigned tid) 496{ 497 //@todo: Change to Calculate All Entries for 498 //Dynamic Policy 499 if( lsqPolicy == Dynamic ) 500 return lqFull(); 501 else 502 return thread[tid].lqFull(); 503} 504 505template<class Impl> 506bool 507LSQ<Impl>::sqFull() 508{ 509 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 510 511 while (active_threads != (*activeThreads).end()) { 512 unsigned tid = *active_threads++; 513 if (!sqFull(tid)) 514 return false; 515 } 516 517 return true; 518} 519 520template<class Impl> 521bool 522LSQ<Impl>::sqFull(unsigned tid) 523{ 524 //@todo: Change to Calculate All Entries for 525 //Dynamic Policy 526 if( lsqPolicy == Dynamic ) 527 return sqFull(); 528 else 529 return thread[tid].sqFull(); 530} 531 532template<class Impl> 533bool 534LSQ<Impl>::isStalled() 535{ 536 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 537 538 while (active_threads != (*activeThreads).end()) { 539 unsigned tid = *active_threads++; 540 if (!thread[tid].isStalled()) 541 return false; 542 } 543 544 return true; 545} 546 547template<class Impl> 548bool 549LSQ<Impl>::isStalled(unsigned tid) 550{ 551 if( lsqPolicy == Dynamic ) 552 return isStalled(); 553 else 554 return thread[tid].isStalled(); 555} 556 557template<class Impl> 558bool 559LSQ<Impl>::hasStoresToWB() 560{ 561 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 562 563 if ((*activeThreads).empty()) 564 return false; 565 566 while (active_threads != (*activeThreads).end()) { 567 unsigned tid = *active_threads++; 568 if (!hasStoresToWB(tid)) 569 return false; 570 } 571 572 return true; 573} 574 575template<class Impl> 576bool 577LSQ<Impl>::willWB() 578{ 579 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 580 581 while (active_threads != (*activeThreads).end()) { 582 unsigned tid = *active_threads++; 583 if (!willWB(tid)) 584 return false; 585 } 586 587 return true; 588} 589 590template<class Impl> 591void 592LSQ<Impl>::dumpInsts() 593{ 594 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 595 596 while (active_threads != (*activeThreads).end()) { 597 unsigned tid = *active_threads++; 598 thread[tid].dumpInsts(); 599 } 600}
| 106 //**********************************************/ 107 //************ Handle SMT Parameters ***********/ 108 //**********************************************/ 109 std::string policy = params->smtLSQPolicy; 110 111 //Convert string to lowercase 112 std::transform(policy.begin(), policy.end(), policy.begin(), 113 (int(*)(int)) tolower); 114 115 //Figure out fetch policy 116 if (policy == "dynamic") { 117 lsqPolicy = Dynamic; 118 119 maxLQEntries = LQEntries; 120 maxSQEntries = SQEntries; 121 122 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 123 124 } else if (policy == "partitioned") { 125 lsqPolicy = Partitioned; 126 127 //@todo:make work if part_amt doesnt divide evenly. 128 maxLQEntries = LQEntries / numThreads; 129 maxSQEntries = SQEntries / numThreads; 130 131 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 132 "%i entries per LQ | %i entries per SQ", 133 maxLQEntries,maxSQEntries); 134 135 } else if (policy == "threshold") { 136 lsqPolicy = Threshold; 137 138 assert(params->smtLSQThreshold > LQEntries); 139 assert(params->smtLSQThreshold > SQEntries); 140 141 //Divide up by threshold amount 142 //@todo: Should threads check the max and the total 143 //amount of the LSQ 144 maxLQEntries = params->smtLSQThreshold; 145 maxSQEntries = params->smtLSQThreshold; 146 147 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 148 "%i entries per LQ | %i entries per SQ", 149 maxLQEntries,maxSQEntries); 150 151 } else { 152 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 153 "Partitioned, Threshold}"); 154 } 155 156 //Initialize LSQs 157 for (int tid=0; tid < numThreads; tid++) { 158 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 159 thread[tid].setDcachePort(&dcachePort); 160 } 161} 162 163 164template<class Impl> 165std::string 166LSQ<Impl>::name() const 167{ 168 return iewStage->name() + ".lsq"; 169} 170 171template<class Impl> 172void 173LSQ<Impl>::regStats() 174{ 175 //Initialize LSQs 176 for (int tid=0; tid < numThreads; tid++) { 177 thread[tid].regStats(); 178 } 179} 180 181template<class Impl> 182void 183LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 184{ 185 activeThreads = at_ptr; 186 assert(activeThreads != 0); 187} 188 189template<class Impl> 190void 191LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 192{ 193 cpu = cpu_ptr; 194 195 dcachePort.setName(name()); 196 197 for (int tid=0; tid < numThreads; tid++) { 198 thread[tid].setCPU(cpu_ptr); 199 } 200} 201 202template<class Impl> 203void 204LSQ<Impl>::setIEW(IEW *iew_ptr) 205{ 206 iewStage = iew_ptr; 207 208 for (int tid=0; tid < numThreads; tid++) { 209 thread[tid].setIEW(iew_ptr); 210 } 211} 212 213template <class Impl> 214void 215LSQ<Impl>::switchOut() 216{ 217 for (int tid = 0; tid < numThreads; tid++) { 218 thread[tid].switchOut(); 219 } 220} 221 222template <class Impl> 223void 224LSQ<Impl>::takeOverFrom() 225{ 226 for (int tid = 0; tid < numThreads; tid++) { 227 thread[tid].takeOverFrom(); 228 } 229} 230 231template <class Impl> 232int 233LSQ<Impl>::entryAmount(int num_threads) 234{ 235 if (lsqPolicy == Partitioned) { 236 return LQEntries / num_threads; 237 } else { 238 return 0; 239 } 240} 241 242template <class Impl> 243void 244LSQ<Impl>::resetEntries() 245{ 246 if (lsqPolicy != Dynamic || numThreads > 1) { 247 int active_threads = (*activeThreads).size(); 248 249 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 250 std::list<unsigned>::iterator list_end = (*activeThreads).end(); 251 252 int maxEntries; 253 254 if (lsqPolicy == Partitioned) { 255 maxEntries = LQEntries / active_threads; 256 } else if (lsqPolicy == Threshold && active_threads == 1) { 257 maxEntries = LQEntries; 258 } else { 259 maxEntries = LQEntries; 260 } 261 262 while (threads != list_end) { 263 resizeEntries(maxEntries,*threads++); 264 } 265 } 266} 267 268template<class Impl> 269void 270LSQ<Impl>::removeEntries(unsigned tid) 271{ 272 thread[tid].clearLQ(); 273 thread[tid].clearSQ(); 274} 275 276template<class Impl> 277void 278LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 279{ 280 thread[tid].resizeLQ(size); 281 thread[tid].resizeSQ(size); 282} 283 284template<class Impl> 285void 286LSQ<Impl>::tick() 287{ 288 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 289 290 while (active_threads != (*activeThreads).end()) { 291 unsigned tid = *active_threads++; 292 293 thread[tid].tick(); 294 } 295} 296 297template<class Impl> 298void 299LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 300{ 301 unsigned tid = load_inst->threadNumber; 302 303 thread[tid].insertLoad(load_inst); 304} 305 306template<class Impl> 307void 308LSQ<Impl>::insertStore(DynInstPtr &store_inst) 309{ 310 unsigned tid = store_inst->threadNumber; 311 312 thread[tid].insertStore(store_inst); 313} 314 315template<class Impl> 316Fault 317LSQ<Impl>::executeLoad(DynInstPtr &inst) 318{ 319 unsigned tid = inst->threadNumber; 320 321 return thread[tid].executeLoad(inst); 322} 323 324template<class Impl> 325Fault 326LSQ<Impl>::executeStore(DynInstPtr &inst) 327{ 328 unsigned tid = inst->threadNumber; 329 330 return thread[tid].executeStore(inst); 331} 332 333template<class Impl> 334void 335LSQ<Impl>::writebackStores() 336{ 337 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 338 339 while (active_threads != (*activeThreads).end()) { 340 unsigned tid = *active_threads++; 341 342 if (numStoresToWB(tid) > 0) { 343 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 344 "available for Writeback.\n", tid, numStoresToWB(tid)); 345 } 346 347 thread[tid].writebackStores(); 348 } 349} 350 351template<class Impl> 352bool 353LSQ<Impl>::violation() 354{ 355 /* Answers: Does Anybody Have a Violation?*/ 356 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 357 358 while (active_threads != (*activeThreads).end()) { 359 unsigned tid = *active_threads++; 360 if (thread[tid].violation()) 361 return true; 362 } 363 364 return false; 365} 366 367template<class Impl> 368int 369LSQ<Impl>::getCount() 370{ 371 unsigned total = 0; 372 373 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 374 375 while (active_threads != (*activeThreads).end()) { 376 unsigned tid = *active_threads++; 377 total += getCount(tid); 378 } 379 380 return total; 381} 382 383template<class Impl> 384int 385LSQ<Impl>::numLoads() 386{ 387 unsigned total = 0; 388 389 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 390 391 while (active_threads != (*activeThreads).end()) { 392 unsigned tid = *active_threads++; 393 total += numLoads(tid); 394 } 395 396 return total; 397} 398 399template<class Impl> 400int 401LSQ<Impl>::numStores() 402{ 403 unsigned total = 0; 404 405 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 406 407 while (active_threads != (*activeThreads).end()) { 408 unsigned tid = *active_threads++; 409 total += thread[tid].numStores(); 410 } 411 412 return total; 413} 414 415template<class Impl> 416int 417LSQ<Impl>::numLoadsReady() 418{ 419 unsigned total = 0; 420 421 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 422 423 while (active_threads != (*activeThreads).end()) { 424 unsigned tid = *active_threads++; 425 total += thread[tid].numLoadsReady(); 426 } 427 428 return total; 429} 430 431template<class Impl> 432unsigned 433LSQ<Impl>::numFreeEntries() 434{ 435 unsigned total = 0; 436 437 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 438 439 while (active_threads != (*activeThreads).end()) { 440 unsigned tid = *active_threads++; 441 total += thread[tid].numFreeEntries(); 442 } 443 444 return total; 445} 446 447template<class Impl> 448unsigned 449LSQ<Impl>::numFreeEntries(unsigned tid) 450{ 451 //if( lsqPolicy == Dynamic ) 452 //return numFreeEntries(); 453 //else 454 return thread[tid].numFreeEntries(); 455} 456 457template<class Impl> 458bool 459LSQ<Impl>::isFull() 460{ 461 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 462 463 while (active_threads != (*activeThreads).end()) { 464 unsigned tid = *active_threads++; 465 if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 466 return false; 467 } 468 469 return true; 470} 471 472template<class Impl> 473bool 474LSQ<Impl>::isFull(unsigned tid) 475{ 476 //@todo: Change to Calculate All Entries for 477 //Dynamic Policy 478 if( lsqPolicy == Dynamic ) 479 return isFull(); 480 else 481 return thread[tid].lqFull() || thread[tid].sqFull(); 482} 483 484template<class Impl> 485bool 486LSQ<Impl>::lqFull() 487{ 488 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 489 490 while (active_threads != (*activeThreads).end()) { 491 unsigned tid = *active_threads++; 492 if (!thread[tid].lqFull()) 493 return false; 494 } 495 496 return true; 497} 498 499template<class Impl> 500bool 501LSQ<Impl>::lqFull(unsigned tid) 502{ 503 //@todo: Change to Calculate All Entries for 504 //Dynamic Policy 505 if( lsqPolicy == Dynamic ) 506 return lqFull(); 507 else 508 return thread[tid].lqFull(); 509} 510 511template<class Impl> 512bool 513LSQ<Impl>::sqFull() 514{ 515 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 516 517 while (active_threads != (*activeThreads).end()) { 518 unsigned tid = *active_threads++; 519 if (!sqFull(tid)) 520 return false; 521 } 522 523 return true; 524} 525 526template<class Impl> 527bool 528LSQ<Impl>::sqFull(unsigned tid) 529{ 530 //@todo: Change to Calculate All Entries for 531 //Dynamic Policy 532 if( lsqPolicy == Dynamic ) 533 return sqFull(); 534 else 535 return thread[tid].sqFull(); 536} 537 538template<class Impl> 539bool 540LSQ<Impl>::isStalled() 541{ 542 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 543 544 while (active_threads != (*activeThreads).end()) { 545 unsigned tid = *active_threads++; 546 if (!thread[tid].isStalled()) 547 return false; 548 } 549 550 return true; 551} 552 553template<class Impl> 554bool 555LSQ<Impl>::isStalled(unsigned tid) 556{ 557 if( lsqPolicy == Dynamic ) 558 return isStalled(); 559 else 560 return thread[tid].isStalled(); 561} 562 563template<class Impl> 564bool 565LSQ<Impl>::hasStoresToWB() 566{ 567 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 568 569 if ((*activeThreads).empty()) 570 return false; 571 572 while (active_threads != (*activeThreads).end()) { 573 unsigned tid = *active_threads++; 574 if (!hasStoresToWB(tid)) 575 return false; 576 } 577 578 return true; 579} 580 581template<class Impl> 582bool 583LSQ<Impl>::willWB() 584{ 585 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 586 587 while (active_threads != (*activeThreads).end()) { 588 unsigned tid = *active_threads++; 589 if (!willWB(tid)) 590 return false; 591 } 592 593 return true; 594} 595 596template<class Impl> 597void 598LSQ<Impl>::dumpInsts() 599{ 600 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 601 602 while (active_threads != (*activeThreads).end()) { 603 unsigned tid = *active_threads++; 604 thread[tid].dumpInsts(); 605 } 606}
|