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