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