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