lsq_impl.hh revision 2689:dbf969c18a65
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 * 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>::setActiveThreads(list<unsigned> *at_ptr) 112{ 113 activeThreads = at_ptr; 114 assert(activeThreads != 0); 115} 116 117template<class Impl> 118void 119LSQ<Impl>::setCPU(FullCPU *cpu_ptr) 120{ 121 cpu = cpu_ptr; 122 123 for (int tid=0; tid < numThreads; tid++) { 124 thread[tid].setCPU(cpu_ptr); 125 } 126} 127 128template<class Impl> 129void 130LSQ<Impl>::setIEW(IEW *iew_ptr) 131{ 132 iewStage = iew_ptr; 133 134 for (int tid=0; tid < numThreads; tid++) { 135 thread[tid].setIEW(iew_ptr); 136 } 137} 138 139#if 0 140template<class Impl> 141void 142LSQ<Impl>::setPageTable(PageTable *pt_ptr) 143{ 144 for (int tid=0; tid < numThreads; tid++) { 145 thread[tid].setPageTable(pt_ptr); 146 } 147} 148#endif 149 150template <class Impl> 151void 152LSQ<Impl>::switchOut() 153{ 154 for (int tid = 0; tid < numThreads; tid++) { 155 thread[tid].switchOut(); 156 } 157} 158 159template <class Impl> 160void 161LSQ<Impl>::takeOverFrom() 162{ 163 for (int tid = 0; tid < numThreads; tid++) { 164 thread[tid].takeOverFrom(); 165 } 166} 167 168template <class Impl> 169int 170LSQ<Impl>::entryAmount(int num_threads) 171{ 172 if (lsqPolicy == Partitioned) { 173 return LQEntries / num_threads; 174 } else { 175 return 0; 176 } 177} 178 179template <class Impl> 180void 181LSQ<Impl>::resetEntries() 182{ 183 if (lsqPolicy != Dynamic || numThreads > 1) { 184 int active_threads = (*activeThreads).size(); 185 186 list<unsigned>::iterator threads = (*activeThreads).begin(); 187 list<unsigned>::iterator list_end = (*activeThreads).end(); 188 189 int maxEntries; 190 191 if (lsqPolicy == Partitioned) { 192 maxEntries = LQEntries / active_threads; 193 } else if (lsqPolicy == Threshold && active_threads == 1) { 194 maxEntries = LQEntries; 195 } else { 196 maxEntries = LQEntries; 197 } 198 199 while (threads != list_end) { 200 resizeEntries(maxEntries,*threads++); 201 } 202 } 203} 204 205template<class Impl> 206void 207LSQ<Impl>::removeEntries(unsigned tid) 208{ 209 thread[tid].clearLQ(); 210 thread[tid].clearSQ(); 211} 212 213template<class Impl> 214void 215LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 216{ 217 thread[tid].resizeLQ(size); 218 thread[tid].resizeSQ(size); 219} 220 221template<class Impl> 222void 223LSQ<Impl>::tick() 224{ 225 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 226 227 while (active_threads != (*activeThreads).end()) { 228 unsigned tid = *active_threads++; 229 230 thread[tid].tick(); 231 } 232} 233 234template<class Impl> 235void 236LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 237{ 238 unsigned tid = load_inst->threadNumber; 239 240 thread[tid].insertLoad(load_inst); 241} 242 243template<class Impl> 244void 245LSQ<Impl>::insertStore(DynInstPtr &store_inst) 246{ 247 unsigned tid = store_inst->threadNumber; 248 249 thread[tid].insertStore(store_inst); 250} 251 252template<class Impl> 253Fault 254LSQ<Impl>::executeLoad(DynInstPtr &inst) 255{ 256 unsigned tid = inst->threadNumber; 257 258 return thread[tid].executeLoad(inst); 259} 260 261template<class Impl> 262Fault 263LSQ<Impl>::executeStore(DynInstPtr &inst) 264{ 265 unsigned tid = inst->threadNumber; 266 267 return thread[tid].executeStore(inst); 268} 269 270template<class Impl> 271void 272LSQ<Impl>::writebackStores() 273{ 274 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 275 276 while (active_threads != (*activeThreads).end()) { 277 unsigned tid = *active_threads++; 278 279 if (numStoresToWB(tid) > 0) { 280 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 281 "available for Writeback.\n", tid, numStoresToWB(tid)); 282 } 283 284 thread[tid].writebackStores(); 285 } 286} 287 288template<class Impl> 289bool 290LSQ<Impl>::violation() 291{ 292 /* Answers: Does Anybody Have a Violation?*/ 293 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 294 295 while (active_threads != (*activeThreads).end()) { 296 unsigned tid = *active_threads++; 297 if (thread[tid].violation()) 298 return true; 299 } 300 301 return false; 302} 303 304template<class Impl> 305int 306LSQ<Impl>::getCount() 307{ 308 unsigned total = 0; 309 310 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 311 312 while (active_threads != (*activeThreads).end()) { 313 unsigned tid = *active_threads++; 314 total += getCount(tid); 315 } 316 317 return total; 318} 319 320template<class Impl> 321int 322LSQ<Impl>::numLoads() 323{ 324 unsigned total = 0; 325 326 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 327 328 while (active_threads != (*activeThreads).end()) { 329 unsigned tid = *active_threads++; 330 total += numLoads(tid); 331 } 332 333 return total; 334} 335 336template<class Impl> 337int 338LSQ<Impl>::numStores() 339{ 340 unsigned total = 0; 341 342 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 343 344 while (active_threads != (*activeThreads).end()) { 345 unsigned tid = *active_threads++; 346 total += thread[tid].numStores(); 347 } 348 349 return total; 350} 351 352template<class Impl> 353int 354LSQ<Impl>::numLoadsReady() 355{ 356 unsigned total = 0; 357 358 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 359 360 while (active_threads != (*activeThreads).end()) { 361 unsigned tid = *active_threads++; 362 total += thread[tid].numLoadsReady(); 363 } 364 365 return total; 366} 367 368template<class Impl> 369unsigned 370LSQ<Impl>::numFreeEntries() 371{ 372 unsigned total = 0; 373 374 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 375 376 while (active_threads != (*activeThreads).end()) { 377 unsigned tid = *active_threads++; 378 total += thread[tid].numFreeEntries(); 379 } 380 381 return total; 382} 383 384template<class Impl> 385unsigned 386LSQ<Impl>::numFreeEntries(unsigned tid) 387{ 388 //if( lsqPolicy == Dynamic ) 389 //return numFreeEntries(); 390 //else 391 return thread[tid].numFreeEntries(); 392} 393 394template<class Impl> 395bool 396LSQ<Impl>::isFull() 397{ 398 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 399 400 while (active_threads != (*activeThreads).end()) { 401 unsigned tid = *active_threads++; 402 if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 403 return false; 404 } 405 406 return true; 407} 408 409template<class Impl> 410bool 411LSQ<Impl>::isFull(unsigned tid) 412{ 413 //@todo: Change to Calculate All Entries for 414 //Dynamic Policy 415 if( lsqPolicy == Dynamic ) 416 return isFull(); 417 else 418 return thread[tid].lqFull() || thread[tid].sqFull(); 419} 420 421template<class Impl> 422bool 423LSQ<Impl>::lqFull() 424{ 425 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 426 427 while (active_threads != (*activeThreads).end()) { 428 unsigned tid = *active_threads++; 429 if (!thread[tid].lqFull()) 430 return false; 431 } 432 433 return true; 434} 435 436template<class Impl> 437bool 438LSQ<Impl>::lqFull(unsigned tid) 439{ 440 //@todo: Change to Calculate All Entries for 441 //Dynamic Policy 442 if( lsqPolicy == Dynamic ) 443 return lqFull(); 444 else 445 return thread[tid].lqFull(); 446} 447 448template<class Impl> 449bool 450LSQ<Impl>::sqFull() 451{ 452 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 453 454 while (active_threads != (*activeThreads).end()) { 455 unsigned tid = *active_threads++; 456 if (!sqFull(tid)) 457 return false; 458 } 459 460 return true; 461} 462 463template<class Impl> 464bool 465LSQ<Impl>::sqFull(unsigned tid) 466{ 467 //@todo: Change to Calculate All Entries for 468 //Dynamic Policy 469 if( lsqPolicy == Dynamic ) 470 return sqFull(); 471 else 472 return thread[tid].sqFull(); 473} 474 475template<class Impl> 476bool 477LSQ<Impl>::isStalled() 478{ 479 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 480 481 while (active_threads != (*activeThreads).end()) { 482 unsigned tid = *active_threads++; 483 if (!thread[tid].isStalled()) 484 return false; 485 } 486 487 return true; 488} 489 490template<class Impl> 491bool 492LSQ<Impl>::isStalled(unsigned tid) 493{ 494 if( lsqPolicy == Dynamic ) 495 return isStalled(); 496 else 497 return thread[tid].isStalled(); 498} 499 500template<class Impl> 501bool 502LSQ<Impl>::hasStoresToWB() 503{ 504 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 505 506 while (active_threads != (*activeThreads).end()) { 507 unsigned tid = *active_threads++; 508 if (!hasStoresToWB(tid)) 509 return false; 510 } 511 512 return true; 513} 514 515template<class Impl> 516bool 517LSQ<Impl>::willWB() 518{ 519 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 520 521 while (active_threads != (*activeThreads).end()) { 522 unsigned tid = *active_threads++; 523 if (!willWB(tid)) 524 return false; 525 } 526 527 return true; 528} 529 530template<class Impl> 531void 532LSQ<Impl>::dumpInsts() 533{ 534 list<unsigned>::iterator active_threads = (*activeThreads).begin(); 535 536 while (active_threads != (*activeThreads).end()) { 537 unsigned tid = *active_threads++; 538 thread[tid].dumpInsts(); 539 } 540} 541