lsq_impl.hh revision 2329
17090SN/A/* 27090SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 37090SN/A * All rights reserved. 47090SN/A * 57090SN/A * Redistribution and use in source and binary forms, with or without 67090SN/A * modification, are permitted provided that the following conditions are 77090SN/A * met: redistributions of source code must retain the above copyright 87090SN/A * notice, this list of conditions and the following disclaimer; 97090SN/A * redistributions in binary form must reproduce the above copyright 107090SN/A * notice, this list of conditions and the following disclaimer in the 117090SN/A * documentation and/or other materials provided with the distribution; 127090SN/A * neither the name of the copyright holders nor the names of its 134486SN/A * contributors may be used to endorse or promote products derived from 144486SN/A * this software without specific prior written permission. 154486SN/A * 164486SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174486SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184486SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194486SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204486SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214486SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224486SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234486SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244486SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254486SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264486SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274486SN/A */ 284486SN/A 294486SN/A#include <algorithm> 304486SN/A#include <string> 314486SN/A 324486SN/A#include "cpu/o3/lsq.hh" 334486SN/A 344486SN/Ausing namespace std; 354486SN/A 364486SN/Atemplate <class Impl> 374486SN/ALSQ<Impl>::LSQ(Params *params) 384486SN/A : LQEntries(params->LQEntries), SQEntries(params->SQEntries), 397584SAli.Saidi@arm.com numThreads(params->numberOfThreads) 407584SAli.Saidi@arm.com{ 417754SWilliam.Wang@arm.com DPRINTF(LSQ, "Creating LSQ object.\n"); 424486SN/A 433630SN/A //**********************************************/ 443630SN/A //************ Handle SMT Parameters ***********/ 457587SAli.Saidi@arm.com //**********************************************/ 468212SAli.Saidi@ARM.com string policy = params->smtLSQPolicy; 475478SN/A 485478SN/A //Convert string to lowercase 497584SAli.Saidi@arm.com std::transform(policy.begin(), policy.end(), policy.begin(), 503630SN/A (int(*)(int)) tolower); 517584SAli.Saidi@arm.com 527584SAli.Saidi@arm.com //Figure out fetch policy 537584SAli.Saidi@arm.com if (policy == "dynamic") { 547584SAli.Saidi@arm.com lsqPolicy = Dynamic; 553898SN/A 567950SAli.Saidi@ARM.com maxLQEntries = LQEntries; 577950SAli.Saidi@ARM.com maxSQEntries = SQEntries; 587950SAli.Saidi@ARM.com 597950SAli.Saidi@ARM.com DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 607950SAli.Saidi@ARM.com 617950SAli.Saidi@ARM.com } else if (policy == "partitioned") { 627950SAli.Saidi@ARM.com lsqPolicy = Partitioned; 637950SAli.Saidi@ARM.com 647587SAli.Saidi@arm.com //@todo:make work if part_amt doesnt divide evenly. 657587SAli.Saidi@arm.com maxLQEntries = LQEntries / numThreads; 667587SAli.Saidi@arm.com maxSQEntries = SQEntries / numThreads; 677753SWilliam.Wang@arm.com 687753SWilliam.Wang@arm.com DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 697753SWilliam.Wang@arm.com "%i entries per LQ | %i entries per SQ", 707753SWilliam.Wang@arm.com maxLQEntries,maxSQEntries); 717587SAli.Saidi@arm.com 727587SAli.Saidi@arm.com } else if (policy == "threshold") { 738282SAli.Saidi@ARM.com lsqPolicy = Threshold; 748282SAli.Saidi@ARM.com 758282SAli.Saidi@ARM.com assert(params->smtLSQThreshold > LQEntries); 767584SAli.Saidi@arm.com assert(params->smtLSQThreshold > SQEntries); 777584SAli.Saidi@arm.com 787584SAli.Saidi@arm.com //Divide up by threshold amount 797584SAli.Saidi@arm.com //@todo: Should threads check the max and the total 807584SAli.Saidi@arm.com //amount of the LSQ 817584SAli.Saidi@arm.com maxLQEntries = params->smtLSQThreshold; 827584SAli.Saidi@arm.com maxSQEntries = params->smtLSQThreshold; 837584SAli.Saidi@arm.com 847584SAli.Saidi@arm.com DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 857584SAli.Saidi@arm.com "%i entries per LQ | %i entries per SQ", 867584SAli.Saidi@arm.com maxLQEntries,maxSQEntries); 877584SAli.Saidi@arm.com 887584SAli.Saidi@arm.com } else { 897584SAli.Saidi@arm.com assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 907584SAli.Saidi@arm.com "Partitioned, Threshold}"); 917584SAli.Saidi@arm.com } 927584SAli.Saidi@arm.com 937584SAli.Saidi@arm.com //Initialize LSQs 947584SAli.Saidi@arm.com for (int tid=0; tid < numThreads; tid++) { 957584SAli.Saidi@arm.com thread[tid].init(params, maxLQEntries, maxSQEntries, tid); 967584SAli.Saidi@arm.com } 977584SAli.Saidi@arm.com} 987584SAli.Saidi@arm.com 997584SAli.Saidi@arm.com 1007584SAli.Saidi@arm.comtemplate<class Impl> 1017584SAli.Saidi@arm.comstd::string 1027584SAli.Saidi@arm.comLSQ<Impl>::name() const 1037584SAli.Saidi@arm.com{ 1047584SAli.Saidi@arm.com return iewStage->name() + ".lsq"; 1057584SAli.Saidi@arm.com} 1067584SAli.Saidi@arm.com 1077584SAli.Saidi@arm.comtemplate<class Impl> 1087584SAli.Saidi@arm.comvoid 1097950SAli.Saidi@ARM.comLSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr) 1107754SWilliam.Wang@arm.com{ 1117950SAli.Saidi@ARM.com activeThreads = at_ptr; 1127950SAli.Saidi@ARM.com assert(activeThreads != 0); 1137950SAli.Saidi@ARM.com} 1147754SWilliam.Wang@arm.com 1157754SWilliam.Wang@arm.comtemplate<class Impl> 1167753SWilliam.Wang@arm.comvoid 1177753SWilliam.Wang@arm.comLSQ<Impl>::setCPU(FullCPU *cpu_ptr) 1187753SWilliam.Wang@arm.com{ 1197950SAli.Saidi@ARM.com cpu = cpu_ptr; 1207753SWilliam.Wang@arm.com 1217753SWilliam.Wang@arm.com for (int tid=0; tid < numThreads; tid++) { 1227584SAli.Saidi@arm.com thread[tid].setCPU(cpu_ptr); 1237584SAli.Saidi@arm.com } 1243630SN/A} 1253630SN/A 1267753SWilliam.Wang@arm.comtemplate<class Impl> 1277753SWilliam.Wang@arm.comvoid 1287753SWilliam.Wang@arm.comLSQ<Impl>::setIEW(IEW *iew_ptr) 1297584SAli.Saidi@arm.com{ 1307584SAli.Saidi@arm.com iewStage = iew_ptr; 1317584SAli.Saidi@arm.com 1327584SAli.Saidi@arm.com for (int tid=0; tid < numThreads; tid++) { 1337584SAli.Saidi@arm.com thread[tid].setIEW(iew_ptr); 1347584SAli.Saidi@arm.com } 1357753SWilliam.Wang@arm.com} 1367754SWilliam.Wang@arm.com 1377950SAli.Saidi@ARM.com#if 0 1388282SAli.Saidi@ARM.comtemplate<class Impl> 1398212SAli.Saidi@ARM.comvoid 1408212SAli.Saidi@ARM.comLSQ<Impl>::setPageTable(PageTable *pt_ptr) 1418212SAli.Saidi@ARM.com{ 1428212SAli.Saidi@ARM.com for (int tid=0; tid < numThreads; tid++) { 1438212SAli.Saidi@ARM.com thread[tid].setPageTable(pt_ptr); 1448212SAli.Saidi@ARM.com } 1457584SAli.Saidi@arm.com} 1467731SAli.Saidi@ARM.com#endif 1477696SAli.Saidi@ARM.com 1487696SAli.Saidi@ARM.comtemplate <class Impl> 1497696SAli.Saidi@ARM.comvoid 1507696SAli.Saidi@ARM.comLSQ<Impl>::switchOut() 1517696SAli.Saidi@ARM.com{ 1527696SAli.Saidi@ARM.com for (int tid = 0; tid < numThreads; tid++) { 1537696SAli.Saidi@ARM.com thread[tid].switchOut(); 1547696SAli.Saidi@ARM.com } 1557696SAli.Saidi@ARM.com} 1567696SAli.Saidi@ARM.com 1577696SAli.Saidi@ARM.comtemplate <class Impl> 1587696SAli.Saidi@ARM.comvoid 1597696SAli.Saidi@ARM.comLSQ<Impl>::takeOverFrom() 1607696SAli.Saidi@ARM.com{ 1617696SAli.Saidi@ARM.com for (int tid = 0; tid < numThreads; tid++) { 1627696SAli.Saidi@ARM.com thread[tid].takeOverFrom(); 1637696SAli.Saidi@ARM.com } 1647696SAli.Saidi@ARM.com} 1657696SAli.Saidi@ARM.com 1667696SAli.Saidi@ARM.comtemplate <class Impl> 1677696SAli.Saidi@ARM.comint 1687696SAli.Saidi@ARM.comLSQ<Impl>::entryAmount(int num_threads) 1698282SAli.Saidi@ARM.com{ 1707696SAli.Saidi@ARM.com if (lsqPolicy == Partitioned) { 1717696SAli.Saidi@ARM.com return LQEntries / num_threads; 1727696SAli.Saidi@ARM.com } else { 1737696SAli.Saidi@ARM.com return 0; 1747696SAli.Saidi@ARM.com } 1757696SAli.Saidi@ARM.com} 1767696SAli.Saidi@ARM.com 1777696SAli.Saidi@ARM.comtemplate <class Impl> 1787696SAli.Saidi@ARM.comvoid 1797753SWilliam.Wang@arm.comLSQ<Impl>::resetEntries() 1807754SWilliam.Wang@arm.com{ 1817754SWilliam.Wang@arm.com if (lsqPolicy != Dynamic || numThreads > 1) { 1828212SAli.Saidi@ARM.com int active_threads = (*activeThreads).size(); 1837696SAli.Saidi@ARM.com 1847696SAli.Saidi@ARM.com list<unsigned>::iterator threads = (*activeThreads).begin(); 1857696SAli.Saidi@ARM.com list<unsigned>::iterator list_end = (*activeThreads).end(); 1867696SAli.Saidi@ARM.com 1877696SAli.Saidi@ARM.com int maxEntries; 1887696SAli.Saidi@ARM.com 1897696SAli.Saidi@ARM.com if (lsqPolicy == Partitioned) { 1907696SAli.Saidi@ARM.com maxEntries = LQEntries / active_threads; 1917696SAli.Saidi@ARM.com } else if (lsqPolicy == Threshold && active_threads == 1) { 1927696SAli.Saidi@ARM.com maxEntries = LQEntries; 1937696SAli.Saidi@ARM.com } else { 1947696SAli.Saidi@ARM.com maxEntries = LQEntries; 1957696SAli.Saidi@ARM.com } 1967696SAli.Saidi@ARM.com 1977696SAli.Saidi@ARM.com while (threads != list_end) { 1987696SAli.Saidi@ARM.com resizeEntries(maxEntries,*threads++); 1997696SAli.Saidi@ARM.com } 2007754SWilliam.Wang@arm.com } 2017754SWilliam.Wang@arm.com} 2027754SWilliam.Wang@arm.com 2037696SAli.Saidi@ARM.comtemplate<class Impl> 2047696SAli.Saidi@ARM.comvoid 2057696SAli.Saidi@ARM.comLSQ<Impl>::removeEntries(unsigned tid) 2067696SAli.Saidi@ARM.com{ 2077696SAli.Saidi@ARM.com thread[tid].clearLQ(); 2087696SAli.Saidi@ARM.com thread[tid].clearSQ(); 2097754SWilliam.Wang@arm.com} 2107754SWilliam.Wang@arm.com 2117950SAli.Saidi@ARM.comtemplate<class Impl> 2127696SAli.Saidi@ARM.comvoid 2137696SAli.Saidi@ARM.comLSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 2147584SAli.Saidi@arm.com{ 2157584SAli.Saidi@arm.com thread[tid].resizeLQ(size); 2167584SAli.Saidi@arm.com thread[tid].resizeSQ(size); 2177584SAli.Saidi@arm.com} 2187584SAli.Saidi@arm.com 2197584SAli.Saidi@arm.comtemplate<class Impl> 2207584SAli.Saidi@arm.comvoid 2217584SAli.Saidi@arm.comLSQ<Impl>::tick() 2227584SAli.Saidi@arm.com{ 2237584SAli.Saidi@arm.com list<unsigned>::iterator active_threads = (*activeThreads).begin(); 2247584SAli.Saidi@arm.com 2257584SAli.Saidi@arm.com while (active_threads != (*activeThreads).end()) { 2267584SAli.Saidi@arm.com unsigned tid = *active_threads++; 2277584SAli.Saidi@arm.com 2287584SAli.Saidi@arm.com thread[tid].tick(); 2297584SAli.Saidi@arm.com } 2307584SAli.Saidi@arm.com} 2317584SAli.Saidi@arm.com 2324104SN/Atemplate<class Impl> 2334104SN/Avoid 2347584SAli.Saidi@arm.comLSQ<Impl>::insertLoad(DynInstPtr &load_inst) 2357584SAli.Saidi@arm.com{ 2364104SN/A unsigned tid = load_inst->threadNumber; 2373630SN/A 2383630SN/A thread[tid].insertLoad(load_inst); 2393630SN/A} 2403630SN/A 2417584SAli.Saidi@arm.comtemplate<class Impl> 2427584SAli.Saidi@arm.comvoid 2437584SAli.Saidi@arm.comLSQ<Impl>::insertStore(DynInstPtr &store_inst) 2447584SAli.Saidi@arm.com{ 2457753SWilliam.Wang@arm.com unsigned tid = store_inst->threadNumber; 2467754SWilliam.Wang@arm.com 2477754SWilliam.Wang@arm.com thread[tid].insertStore(store_inst); 2487584SAli.Saidi@arm.com} 2497584SAli.Saidi@arm.com 2507584SAli.Saidi@arm.comtemplate<class Impl> 2517584SAli.Saidi@arm.comFault 2527584SAli.Saidi@arm.comLSQ<Impl>::executeLoad(DynInstPtr &inst) 2537584SAli.Saidi@arm.com{ 2547584SAli.Saidi@arm.com unsigned tid = inst->threadNumber; 2557584SAli.Saidi@arm.com 2567584SAli.Saidi@arm.com return thread[tid].executeLoad(inst); 2577584SAli.Saidi@arm.com} 2587584SAli.Saidi@arm.com 2597584SAli.Saidi@arm.comtemplate<class Impl> 2607584SAli.Saidi@arm.comFault 2617584SAli.Saidi@arm.comLSQ<Impl>::executeStore(DynInstPtr &inst) 2627584SAli.Saidi@arm.com{ 2637584SAli.Saidi@arm.com 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