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