iew_impl.hh revision 2301
110447Snilay@cs.wisc.edu/* 210447Snilay@cs.wisc.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 310447Snilay@cs.wisc.edu * All rights reserved. 410447Snilay@cs.wisc.edu * 510447Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without 610447Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 710447Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright 810447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer; 910447Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright 1010447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the 1110447Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution; 1210447Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its 1310447Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 1410447Snilay@cs.wisc.edu * this software without specific prior written permission. 1510447Snilay@cs.wisc.edu * 1610447Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710447Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810447Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910447Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010447Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110447Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210447Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310447Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410447Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510447Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610447Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710447Snilay@cs.wisc.edu */ 2810447Snilay@cs.wisc.edu 2910447Snilay@cs.wisc.edu// @todo: Fix the instantaneous communication among all the stages within 3010447Snilay@cs.wisc.edu// iew. There's a clear delay between issue and execute, yet backwards 3110447Snilay@cs.wisc.edu// communication happens simultaneously. 3210447Snilay@cs.wisc.edu 3310447Snilay@cs.wisc.edu#include <queue> 3410447Snilay@cs.wisc.edu 3510447Snilay@cs.wisc.edu#include "base/timebuf.hh" 3610447Snilay@cs.wisc.edu#include "cpu/o3/fu_pool.hh" 3710447Snilay@cs.wisc.edu#include "cpu/o3/iew.hh" 3810447Snilay@cs.wisc.edu 3910447Snilay@cs.wisc.eduusing namespace std; 4010447Snilay@cs.wisc.edu 4110447Snilay@cs.wisc.edutemplate<class Impl> 4210447Snilay@cs.wisc.eduDefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst, 4310447Snilay@cs.wisc.edu DefaultIEW<Impl> *_iew) 4410447Snilay@cs.wisc.edu : Event(&mainEventQueue), inst(_inst), iewStage(_iew) 4510447Snilay@cs.wisc.edu{ 4610447Snilay@cs.wisc.edu this->setFlags(Event::AutoDelete); 4710447Snilay@cs.wisc.edu} 4810447Snilay@cs.wisc.edu 4910447Snilay@cs.wisc.edutemplate<class Impl> 5010447Snilay@cs.wisc.eduvoid 5110447Snilay@cs.wisc.eduDefaultIEW<Impl>::LdWritebackEvent::process() 5210447Snilay@cs.wisc.edu{ 5310447Snilay@cs.wisc.edu DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum); 5410447Snilay@cs.wisc.edu DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum); 5510447Snilay@cs.wisc.edu 5610447Snilay@cs.wisc.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 5710447Snilay@cs.wisc.edu 5810447Snilay@cs.wisc.edu iewStage->wakeCPU(); 5910447Snilay@cs.wisc.edu 6010447Snilay@cs.wisc.edu if (inst->isSquashed()) { 6110447Snilay@cs.wisc.edu inst = NULL; 6210447Snilay@cs.wisc.edu return; 6310447Snilay@cs.wisc.edu } 6410447Snilay@cs.wisc.edu 6510447Snilay@cs.wisc.edu if (!inst->isExecuted()) { 6610447Snilay@cs.wisc.edu inst->setExecuted(); 6710447Snilay@cs.wisc.edu 6810447Snilay@cs.wisc.edu // Execute again to copy data to proper place. 6910447Snilay@cs.wisc.edu if (inst->isStore()) { 7010447Snilay@cs.wisc.edu inst->completeAcc(); 7110447Snilay@cs.wisc.edu } 7210447Snilay@cs.wisc.edu } 7310447Snilay@cs.wisc.edu 7410447Snilay@cs.wisc.edu // Need to insert instruction into queue to commit 7510447Snilay@cs.wisc.edu iewStage->instToCommit(inst); 7610447Snilay@cs.wisc.edu 7710447Snilay@cs.wisc.edu //wroteToTimeBuffer = true; 7810447Snilay@cs.wisc.edu iewStage->activityThisCycle(); 7910447Snilay@cs.wisc.edu 8010447Snilay@cs.wisc.edu inst = NULL; 8110447Snilay@cs.wisc.edu} 8210447Snilay@cs.wisc.edu 8310447Snilay@cs.wisc.edutemplate<class Impl> 8410447Snilay@cs.wisc.educonst char * 8510447Snilay@cs.wisc.eduDefaultIEW<Impl>::LdWritebackEvent::description() 8610447Snilay@cs.wisc.edu{ 8710447Snilay@cs.wisc.edu return "Load writeback event"; 8810447Snilay@cs.wisc.edu} 8910447Snilay@cs.wisc.edu 9010447Snilay@cs.wisc.edutemplate<class Impl> 9110447Snilay@cs.wisc.eduDefaultIEW<Impl>::DefaultIEW(Params *params) 9210447Snilay@cs.wisc.edu : // Just make this time buffer really big for now 9310447Snilay@cs.wisc.edu // @todo: Make this into a parameter. 9410447Snilay@cs.wisc.edu issueToExecQueue(5, 5), 9510447Snilay@cs.wisc.edu instQueue(params), 9610447Snilay@cs.wisc.edu ldstQueue(params), 9710447Snilay@cs.wisc.edu fuPool(params->fuPool), 9810447Snilay@cs.wisc.edu commitToIEWDelay(params->commitToIEWDelay), 9910447Snilay@cs.wisc.edu renameToIEWDelay(params->renameToIEWDelay), 10010447Snilay@cs.wisc.edu issueToExecuteDelay(params->issueToExecuteDelay), 10110447Snilay@cs.wisc.edu issueReadWidth(params->issueWidth), 10210447Snilay@cs.wisc.edu issueWidth(params->issueWidth), 10310447Snilay@cs.wisc.edu executeWidth(params->executeWidth), 10410447Snilay@cs.wisc.edu numThreads(params->numberOfThreads) 10510447Snilay@cs.wisc.edu{ 10610447Snilay@cs.wisc.edu DPRINTF(IEW, "executeIntWidth: %i.\n", params->executeIntWidth); 10710447Snilay@cs.wisc.edu _status = Active; 10810447Snilay@cs.wisc.edu exeStatus = Running; 10910447Snilay@cs.wisc.edu wbStatus = Idle; 11010447Snilay@cs.wisc.edu 11110447Snilay@cs.wisc.edu // Setup wire to read instructions coming from issue. 11210447Snilay@cs.wisc.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 11310447Snilay@cs.wisc.edu 11410447Snilay@cs.wisc.edu // Instruction queue needs the queue between issue and execute. 11510447Snilay@cs.wisc.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 11610447Snilay@cs.wisc.edu 11710447Snilay@cs.wisc.edu instQueue.setIEW(this); 11810447Snilay@cs.wisc.edu ldstQueue.setIEW(this); 11910447Snilay@cs.wisc.edu 12010447Snilay@cs.wisc.edu for (int i=0; i < numThreads; i++) { 12110447Snilay@cs.wisc.edu dispatchStatus[i] = Running; 12210447Snilay@cs.wisc.edu stalls[i].commit = false; 12310447Snilay@cs.wisc.edu fetchRedirect[i] = false; 12410447Snilay@cs.wisc.edu } 12510447Snilay@cs.wisc.edu 12610447Snilay@cs.wisc.edu updateLSQNextCycle = false; 12710447Snilay@cs.wisc.edu 12810447Snilay@cs.wisc.edu // @todo: Make into a parameter 12910447Snilay@cs.wisc.edu skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 13010447Snilay@cs.wisc.edu} 13110447Snilay@cs.wisc.edu 13210447Snilay@cs.wisc.edutemplate <class Impl> 13310447Snilay@cs.wisc.edustd::string 13410447Snilay@cs.wisc.eduDefaultIEW<Impl>::name() const 13510447Snilay@cs.wisc.edu{ 13610447Snilay@cs.wisc.edu return cpu->name() + ".iew"; 13710447Snilay@cs.wisc.edu} 13810447Snilay@cs.wisc.edu 13910447Snilay@cs.wisc.edutemplate <class Impl> 14010447Snilay@cs.wisc.eduvoid 14110447Snilay@cs.wisc.eduDefaultIEW<Impl>::regStats() 14210447Snilay@cs.wisc.edu{ 14310447Snilay@cs.wisc.edu using namespace Stats; 14410447Snilay@cs.wisc.edu 14510447Snilay@cs.wisc.edu instQueue.regStats(); 14610447Snilay@cs.wisc.edu 14710447Snilay@cs.wisc.edu //ldstQueue.regStats(); 14810447Snilay@cs.wisc.edu 14910447Snilay@cs.wisc.edu iewIdleCycles 15010447Snilay@cs.wisc.edu .name(name() + ".iewIdleCycles") 15110447Snilay@cs.wisc.edu .desc("Number of cycles IEW is idle"); 15210447Snilay@cs.wisc.edu 15310447Snilay@cs.wisc.edu iewSquashCycles 15410447Snilay@cs.wisc.edu .name(name() + ".iewSquashCycles") 15510447Snilay@cs.wisc.edu .desc("Number of cycles IEW is squashing"); 15610447Snilay@cs.wisc.edu 15710447Snilay@cs.wisc.edu iewBlockCycles 15810447Snilay@cs.wisc.edu .name(name() + ".iewBlockCycles") 15910447Snilay@cs.wisc.edu .desc("Number of cycles IEW is blocking"); 16010447Snilay@cs.wisc.edu 16110447Snilay@cs.wisc.edu iewUnblockCycles 16210447Snilay@cs.wisc.edu .name(name() + ".iewUnblockCycles") 16310447Snilay@cs.wisc.edu .desc("Number of cycles IEW is unblocking"); 16410447Snilay@cs.wisc.edu 16510447Snilay@cs.wisc.edu// iewWBInsts; 16610447Snilay@cs.wisc.edu 16710447Snilay@cs.wisc.edu iewDispatchedInsts 16810447Snilay@cs.wisc.edu .name(name() + ".iewDispatchedInsts") 16910447Snilay@cs.wisc.edu .desc("Number of instructions dispatched to IQ"); 17010447Snilay@cs.wisc.edu 17110447Snilay@cs.wisc.edu iewDispSquashedInsts 17210447Snilay@cs.wisc.edu .name(name() + ".iewDispSquashedInsts") 17310447Snilay@cs.wisc.edu .desc("Number of squashed instructions skipped by dispatch"); 17410447Snilay@cs.wisc.edu 17510447Snilay@cs.wisc.edu iewDispLoadInsts 17610447Snilay@cs.wisc.edu .name(name() + ".iewDispLoadInsts") 17710447Snilay@cs.wisc.edu .desc("Number of dispatched load instructions"); 17810447Snilay@cs.wisc.edu 17910447Snilay@cs.wisc.edu iewDispStoreInsts 18010447Snilay@cs.wisc.edu .name(name() + ".iewDispStoreInsts") 18110447Snilay@cs.wisc.edu .desc("Number of dispatched store instructions"); 18210447Snilay@cs.wisc.edu 18310447Snilay@cs.wisc.edu iewDispNonSpecInsts 18410447Snilay@cs.wisc.edu .name(name() + ".iewDispNonSpecInsts") 18510447Snilay@cs.wisc.edu .desc("Number of dispatched non-speculative instructions"); 18610447Snilay@cs.wisc.edu 18710447Snilay@cs.wisc.edu iewIQFullEvents 18810447Snilay@cs.wisc.edu .name(name() + ".iewIQFullEvents") 18910447Snilay@cs.wisc.edu .desc("Number of times the IQ has become full, causing a stall"); 19010447Snilay@cs.wisc.edu 19110447Snilay@cs.wisc.edu iewLSQFullEvents 19210447Snilay@cs.wisc.edu .name(name() + ".iewLSQFullEvents") 19310447Snilay@cs.wisc.edu .desc("Number of times the LSQ has become full, causing a stall"); 19410447Snilay@cs.wisc.edu 19510447Snilay@cs.wisc.edu iewExecutedInsts 19610447Snilay@cs.wisc.edu .name(name() + ".iewExecutedInsts") 19710447Snilay@cs.wisc.edu .desc("Number of executed instructions"); 19810447Snilay@cs.wisc.edu 19910447Snilay@cs.wisc.edu iewExecLoadInsts 20010447Snilay@cs.wisc.edu .init(cpu->number_of_threads) 20110447Snilay@cs.wisc.edu .name(name() + ".iewExecLoadInsts") 20210447Snilay@cs.wisc.edu .desc("Number of load instructions executed") 20310447Snilay@cs.wisc.edu .flags(total); 20410447Snilay@cs.wisc.edu/* 20510447Snilay@cs.wisc.edu iewExecStoreInsts 20610447Snilay@cs.wisc.edu .name(name() + ".iewExecStoreInsts") 20710447Snilay@cs.wisc.edu .desc("Number of store instructions executed"); 20810447Snilay@cs.wisc.edu*/ 20910447Snilay@cs.wisc.edu iewExecSquashedInsts 21010447Snilay@cs.wisc.edu .name(name() + ".iewExecSquashedInsts") 21110447Snilay@cs.wisc.edu .desc("Number of squashed instructions skipped in execute"); 21210447Snilay@cs.wisc.edu 21310447Snilay@cs.wisc.edu memOrderViolationEvents 21410447Snilay@cs.wisc.edu .name(name() + ".memOrderViolationEvents") 21510447Snilay@cs.wisc.edu .desc("Number of memory order violations"); 21610447Snilay@cs.wisc.edu 21710447Snilay@cs.wisc.edu predictedTakenIncorrect 21810447Snilay@cs.wisc.edu .name(name() + ".predictedTakenIncorrect") 21910447Snilay@cs.wisc.edu .desc("Number of branches that were predicted taken incorrectly"); 220 221 predictedNotTakenIncorrect 222 .name(name() + ".predictedNotTakenIncorrect") 223 .desc("Number of branches that were predicted not taken incorrectly"); 224 225 branchMispredicts 226 .name(name() + ".branchMispredicts") 227 .desc("Number of branch mispredicts detected at execute"); 228 229 branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 230 231 exe_swp 232 .init(cpu->number_of_threads) 233 .name(name() + ".EXEC:swp") 234 .desc("number of swp insts executed") 235 .flags(total) 236 ; 237 238 exe_nop 239 .init(cpu->number_of_threads) 240 .name(name() + ".EXEC:nop") 241 .desc("number of nop insts executed") 242 .flags(total) 243 ; 244 245 exe_refs 246 .init(cpu->number_of_threads) 247 .name(name() + ".EXEC:refs") 248 .desc("number of memory reference insts executed") 249 .flags(total) 250 ; 251 252 exe_branches 253 .init(cpu->number_of_threads) 254 .name(name() + ".EXEC:branches") 255 .desc("Number of branches executed") 256 .flags(total) 257 ; 258 259 issue_rate 260 .name(name() + ".EXEC:rate") 261 .desc("Inst execution rate") 262 .flags(total) 263 ; 264 issue_rate = iewExecutedInsts / cpu->numCycles; 265 266 iewExecStoreInsts 267 .name(name() + ".EXEC:stores") 268 .desc("Number of stores executed") 269 .flags(total) 270 ; 271 iewExecStoreInsts = exe_refs - iewExecLoadInsts; 272/* 273 for (int i=0; i<Num_OpClasses; ++i) { 274 stringstream subname; 275 subname << opClassStrings[i] << "_delay"; 276 issue_delay_dist.subname(i, subname.str()); 277 } 278*/ 279 // 280 // Other stats 281 // 282 283 iewInstsToCommit 284 .init(cpu->number_of_threads) 285 .name(name() + ".WB:sent") 286 .desc("cumulative count of insts sent to commit") 287 .flags(total) 288 ; 289 290 writeback_count 291 .init(cpu->number_of_threads) 292 .name(name() + ".WB:count") 293 .desc("cumulative count of insts written-back") 294 .flags(total) 295 ; 296 297 producer_inst 298 .init(cpu->number_of_threads) 299 .name(name() + ".WB:producers") 300 .desc("num instructions producing a value") 301 .flags(total) 302 ; 303 304 consumer_inst 305 .init(cpu->number_of_threads) 306 .name(name() + ".WB:consumers") 307 .desc("num instructions consuming a value") 308 .flags(total) 309 ; 310 311 wb_penalized 312 .init(cpu->number_of_threads) 313 .name(name() + ".WB:penalized") 314 .desc("number of instrctions required to write to 'other' IQ") 315 .flags(total) 316 ; 317 318 wb_penalized_rate 319 .name(name() + ".WB:penalized_rate") 320 .desc ("fraction of instructions written-back that wrote to 'other' IQ") 321 .flags(total) 322 ; 323 324 wb_penalized_rate = wb_penalized / writeback_count; 325 326 wb_fanout 327 .name(name() + ".WB:fanout") 328 .desc("average fanout of values written-back") 329 .flags(total) 330 ; 331 332 wb_fanout = producer_inst / consumer_inst; 333 334 wb_rate 335 .name(name() + ".WB:rate") 336 .desc("insts written-back per cycle") 337 .flags(total) 338 ; 339 wb_rate = writeback_count / cpu->numCycles; 340} 341 342template<class Impl> 343void 344DefaultIEW<Impl>::initStage() 345{ 346 for (int tid=0; tid < numThreads; tid++) { 347 toRename->iewInfo[tid].usedIQ = true; 348 toRename->iewInfo[tid].freeIQEntries = 349 instQueue.numFreeEntries(tid); 350 351 toRename->iewInfo[tid].usedLSQ = true; 352 toRename->iewInfo[tid].freeLSQEntries = 353 ldstQueue.numFreeEntries(tid); 354 } 355} 356 357template<class Impl> 358void 359DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr) 360{ 361 DPRINTF(IEW, "Setting CPU pointer.\n"); 362 cpu = cpu_ptr; 363 364 instQueue.setCPU(cpu_ptr); 365 ldstQueue.setCPU(cpu_ptr); 366 367 cpu->activateStage(FullCPU::IEWIdx); 368} 369 370template<class Impl> 371void 372DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 373{ 374 DPRINTF(IEW, "Setting time buffer pointer.\n"); 375 timeBuffer = tb_ptr; 376 377 // Setup wire to read information from time buffer, from commit. 378 fromCommit = timeBuffer->getWire(-commitToIEWDelay); 379 380 // Setup wire to write information back to previous stages. 381 toRename = timeBuffer->getWire(0); 382 383 toFetch = timeBuffer->getWire(0); 384 385 // Instruction queue also needs main time buffer. 386 instQueue.setTimeBuffer(tb_ptr); 387} 388 389template<class Impl> 390void 391DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 392{ 393 DPRINTF(IEW, "Setting rename queue pointer.\n"); 394 renameQueue = rq_ptr; 395 396 // Setup wire to read information from rename queue. 397 fromRename = renameQueue->getWire(-renameToIEWDelay); 398} 399 400template<class Impl> 401void 402DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 403{ 404 DPRINTF(IEW, "Setting IEW queue pointer.\n"); 405 iewQueue = iq_ptr; 406 407 // Setup wire to write instructions to commit. 408 toCommit = iewQueue->getWire(0); 409} 410 411template<class Impl> 412void 413DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr) 414{ 415 DPRINTF(IEW, "Setting active threads list pointer.\n"); 416 activeThreads = at_ptr; 417 418 ldstQueue.setActiveThreads(at_ptr); 419 instQueue.setActiveThreads(at_ptr); 420} 421 422template<class Impl> 423void 424DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 425{ 426 DPRINTF(IEW, "Setting scoreboard pointer.\n"); 427 scoreboard = sb_ptr; 428} 429 430#if 0 431template<class Impl> 432void 433DefaultIEW<Impl>::setPageTable(PageTable *pt_ptr) 434{ 435 ldstQueue.setPageTable(pt_ptr); 436} 437#endif 438 439template<class Impl> 440void 441DefaultIEW<Impl>::squash(unsigned tid) 442{ 443 DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", 444 tid); 445 446 // Tell the IQ to start squashing. 447 instQueue.squash(tid); 448 449 // Tell the LDSTQ to start squashing. 450 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum,tid); 451 452 updatedQueues = true; 453 454 // Clear the skid buffer in case it has any data in it. 455 while (!skidBuffer[tid].empty()) { 456 457 if (skidBuffer[tid].front()->isLoad() || 458 skidBuffer[tid].front()->isStore() ) { 459 toRename->iewInfo[tid].dispatchedToLSQ++; 460 } 461 462 toRename->iewInfo[tid].dispatched++; 463 464 skidBuffer[tid].pop(); 465 } 466 467 while (!insts[tid].empty()) { 468 if (insts[tid].front()->isLoad() || 469 insts[tid].front()->isStore() ) { 470 toRename->iewInfo[tid].dispatchedToLSQ++; 471 } 472 473 toRename->iewInfo[tid].dispatched++; 474 475 insts[tid].pop(); 476 } 477} 478 479template<class Impl> 480void 481DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid) 482{ 483 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x " 484 "[sn:%i].\n", tid, inst->readPC(), inst->seqNum); 485 486 // Tell rename to squash through the time buffer. 487 toCommit->squash[tid] = true; 488 toCommit->squashedSeqNum[tid] = inst->seqNum; 489 toCommit->mispredPC[tid] = inst->readPC(); 490 toCommit->nextPC[tid] = inst->readNextPC(); 491 toCommit->branchMispredict[tid] = true; 492 // Prediction was incorrect, so send back inverse. 493 toCommit->branchTaken[tid] = inst->readNextPC() != 494 (inst->readPC() + sizeof(TheISA::MachInst)); 495 496 toCommit->includeSquashInst[tid] = false; 497 //toCommit->iewSquashNum[tid] = inst->seqNum; 498 499 wroteToTimeBuffer = true; 500} 501 502template<class Impl> 503void 504DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid) 505{ 506 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " 507 "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); 508 509 // Tell rename to squash through the time buffer. 510 toCommit->squash[tid] = true; 511 toCommit->squashedSeqNum[tid] = inst->seqNum; 512 toCommit->nextPC[tid] = inst->readNextPC(); 513 514 toCommit->includeSquashInst[tid] = false; 515 //toCommit->iewSquashNum[tid] = inst->seqNum; 516 517 wroteToTimeBuffer = true; 518} 519 520template<class Impl> 521void 522DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid) 523{ 524 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 525 "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); 526 527 toCommit->squash[tid] = true; 528 toCommit->squashedSeqNum[tid] = inst->seqNum; 529 toCommit->nextPC[tid] = inst->readPC(); 530 531 toCommit->includeSquashInst[tid] = true; 532 533 ldstQueue.setLoadBlockedHandled(tid); 534 535 wroteToTimeBuffer = true; 536} 537 538template<class Impl> 539void 540DefaultIEW<Impl>::block(unsigned tid) 541{ 542 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 543 544 if (dispatchStatus[tid] != Blocked && 545 dispatchStatus[tid] != Unblocking) { 546 toRename->iewBlock[tid] = true; 547 wroteToTimeBuffer = true; 548 } 549 550 // Add the current inputs to the skid buffer so they can be 551 // reprocessed when this stage unblocks. 552 skidInsert(tid); 553 554 // Set the status to Blocked. 555 dispatchStatus[tid] = Blocked; 556} 557 558template<class Impl> 559void 560DefaultIEW<Impl>::unblock(unsigned tid) 561{ 562 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 563 "buffer %u.\n",tid, tid); 564 565 // If the skid bufffer is empty, signal back to previous stages to unblock. 566 // Also switch status to running. 567 if (skidBuffer[tid].empty()) { 568 toRename->iewUnblock[tid] = true; 569 wroteToTimeBuffer = true; 570 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 571 dispatchStatus[tid] = Running; 572 } 573} 574 575template<class Impl> 576void 577DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 578{ 579 instQueue.wakeDependents(inst); 580} 581 582template<class Impl> 583void 584DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 585{ 586 instQueue.rescheduleMemInst(inst); 587} 588 589template<class Impl> 590void 591DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 592{ 593 instQueue.replayMemInst(inst); 594} 595 596template<class Impl> 597void 598DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 599{ 600 // First check the time slot that this instruction will write 601 // to. If there are free write ports at the time, then go ahead 602 // and write the instruction to that time. If there are not, 603 // keep looking back to see where's the first time there's a 604 // free slot. What happens if you run out of free spaces? 605 // For now naively assume that all instructions take one cycle. 606 // Otherwise would have to look into the time buffer based on the 607 // latency of the instruction. 608 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 609 ++wbNumInst; 610 if (wbNumInst == issueWidth) { 611 ++wbCycle; 612 wbNumInst = 0; 613 } 614 615 assert(wbCycle < 5); 616 } 617 618 // Add finished instruction to queue to commit. 619 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 620 (*iewQueue)[wbCycle].size++; 621} 622 623template <class Impl> 624unsigned 625DefaultIEW<Impl>::validInstsFromRename() 626{ 627 unsigned inst_count = 0; 628 629 for (int i=0; i<fromRename->size; i++) { 630 if (!fromRename->insts[i]->squashed) 631 inst_count++; 632 } 633 634 return inst_count; 635} 636 637template<class Impl> 638void 639DefaultIEW<Impl>::skidInsert(unsigned tid) 640{ 641 DynInstPtr inst = NULL; 642 643 while (!insts[tid].empty()) { 644 inst = insts[tid].front(); 645 646 insts[tid].pop(); 647 648 DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into " 649 "dispatch skidBuffer %i\n",tid, inst->seqNum, 650 inst->readPC(),tid); 651 652 skidBuffer[tid].push(inst); 653 } 654 655 assert(skidBuffer[tid].size() <= skidBufferMax && 656 "Skidbuffer Exceeded Max Size"); 657} 658 659template<class Impl> 660int 661DefaultIEW<Impl>::skidCount() 662{ 663 int max=0; 664 665 list<unsigned>::iterator threads = (*activeThreads).begin(); 666 667 while (threads != (*activeThreads).end()) { 668 unsigned thread_count = skidBuffer[*threads++].size(); 669 if (max < thread_count) 670 max = thread_count; 671 } 672 673 return max; 674} 675 676template<class Impl> 677bool 678DefaultIEW<Impl>::skidsEmpty() 679{ 680 list<unsigned>::iterator threads = (*activeThreads).begin(); 681 682 while (threads != (*activeThreads).end()) { 683 if (!skidBuffer[*threads++].empty()) 684 return false; 685 } 686 687 return true; 688} 689 690template <class Impl> 691void 692DefaultIEW<Impl>::updateStatus() 693{ 694 bool any_unblocking = false; 695 696 list<unsigned>::iterator threads = (*activeThreads).begin(); 697 698 threads = (*activeThreads).begin(); 699 700 while (threads != (*activeThreads).end()) { 701 unsigned tid = *threads++; 702 703 if (dispatchStatus[tid] == Unblocking) { 704 any_unblocking = true; 705 break; 706 } 707 } 708 709 // If there are no ready instructions waiting to be scheduled by the IQ, 710 // and there's no stores waiting to write back, and dispatch is not 711 // unblocking, then there is no internal activity for the IEW stage. 712 if (_status == Active && !instQueue.hasReadyInsts() && 713 !ldstQueue.willWB() && !any_unblocking) { 714 DPRINTF(IEW, "IEW switching to idle\n"); 715 716 deactivateStage(); 717 718 _status = Inactive; 719 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 720 ldstQueue.willWB() || 721 any_unblocking)) { 722 // Otherwise there is internal activity. Set to active. 723 DPRINTF(IEW, "IEW switching to active\n"); 724 725 activateStage(); 726 727 _status = Active; 728 } 729} 730 731template <class Impl> 732void 733DefaultIEW<Impl>::resetEntries() 734{ 735 instQueue.resetEntries(); 736 ldstQueue.resetEntries(); 737} 738 739template <class Impl> 740void 741DefaultIEW<Impl>::readStallSignals(unsigned tid) 742{ 743 if (fromCommit->commitBlock[tid]) { 744 stalls[tid].commit = true; 745 } 746 747 if (fromCommit->commitUnblock[tid]) { 748 assert(stalls[tid].commit); 749 stalls[tid].commit = false; 750 } 751} 752 753template <class Impl> 754bool 755DefaultIEW<Impl>::checkStall(unsigned tid) 756{ 757 bool ret_val(false); 758 759 if (stalls[tid].commit) { 760 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 761 ret_val = true; 762 } else if (instQueue.isFull(tid)) { 763 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 764 ret_val = true; 765 } else if (ldstQueue.isFull(tid)) { 766 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 767 768 if (ldstQueue.numLoads(tid) > 0 ) { 769 770 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 771 tid,ldstQueue.getLoadHeadSeqNum(tid)); 772 } 773 774 if (ldstQueue.numStores(tid) > 0) { 775 776 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 777 tid,ldstQueue.getStoreHeadSeqNum(tid)); 778 } 779 780 ret_val = true; 781 } else if (ldstQueue.isStalled(tid)) { 782 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 783 ret_val = true; 784 } 785 786 return ret_val; 787} 788 789template <class Impl> 790void 791DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid) 792{ 793 // Check if there's a squash signal, squash if there is 794 // Check stall signals, block if there is. 795 // If status was Blocked 796 // if so then go to unblocking 797 // If status was Squashing 798 // check if squashing is not high. Switch to running this cycle. 799 800 readStallSignals(tid); 801 802 if (fromCommit->commitInfo[tid].squash) { 803 squash(tid); 804 805 if (dispatchStatus[tid] == Blocked || 806 dispatchStatus[tid] == Unblocking) { 807 toRename->iewUnblock[tid] = true; 808 wroteToTimeBuffer = true; 809 } 810 811 dispatchStatus[tid] = Squashing; 812 813 fetchRedirect[tid] = false; 814 return; 815 } 816 817 if (fromCommit->commitInfo[tid].robSquashing) { 818 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n"); 819 820 dispatchStatus[tid] = Squashing; 821 822 return; 823 } 824 825 if (checkStall(tid)) { 826 block(tid); 827 dispatchStatus[tid] = Blocked; 828 return; 829 } 830 831 if (dispatchStatus[tid] == Blocked) { 832 // Status from previous cycle was blocked, but there are no more stall 833 // conditions. Switch over to unblocking. 834 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 835 tid); 836 837 dispatchStatus[tid] = Unblocking; 838 839 unblock(tid); 840 841 return; 842 } 843 844 if (dispatchStatus[tid] == Squashing) { 845 // Switch status to running if rename isn't being told to block or 846 // squash this cycle. 847 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 848 tid); 849 850 dispatchStatus[tid] = Running; 851 852 return; 853 } 854} 855 856template <class Impl> 857void 858DefaultIEW<Impl>::sortInsts() 859{ 860 int insts_from_rename = fromRename->size; 861 862 for (int i = 0; i < numThreads; i++) 863 assert(insts[i].empty()); 864 865 for (int i = 0; i < insts_from_rename; ++i) { 866 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 867 } 868} 869 870template <class Impl> 871void 872DefaultIEW<Impl>::wakeCPU() 873{ 874 cpu->wakeCPU(); 875} 876 877template <class Impl> 878void 879DefaultIEW<Impl>::activityThisCycle() 880{ 881 DPRINTF(Activity, "Activity this cycle.\n"); 882 cpu->activityThisCycle(); 883} 884 885template <class Impl> 886inline void 887DefaultIEW<Impl>::activateStage() 888{ 889 DPRINTF(Activity, "Activating stage.\n"); 890 cpu->activateStage(FullCPU::IEWIdx); 891} 892 893template <class Impl> 894inline void 895DefaultIEW<Impl>::deactivateStage() 896{ 897 DPRINTF(Activity, "Deactivating stage.\n"); 898 cpu->deactivateStage(FullCPU::IEWIdx); 899} 900 901template<class Impl> 902void 903DefaultIEW<Impl>::dispatch(unsigned tid) 904{ 905 // If status is Running or idle, 906 // call dispatchInsts() 907 // If status is Unblocking, 908 // buffer any instructions coming from rename 909 // continue trying to empty skid buffer 910 // check if stall conditions have passed 911 912 if (dispatchStatus[tid] == Blocked) { 913 ++iewBlockCycles; 914 915 } else if (dispatchStatus[tid] == Squashing) { 916 ++iewSquashCycles; 917 } 918 919 // Dispatch should try to dispatch as many instructions as its bandwidth 920 // will allow, as long as it is not currently blocked. 921 if (dispatchStatus[tid] == Running || 922 dispatchStatus[tid] == Idle) { 923 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 924 "dispatch.\n", tid); 925 926 dispatchInsts(tid); 927 } else if (dispatchStatus[tid] == Unblocking) { 928 // Make sure that the skid buffer has something in it if the 929 // status is unblocking. 930 assert(!skidsEmpty()); 931 932 // If the status was unblocking, then instructions from the skid 933 // buffer were used. Remove those instructions and handle 934 // the rest of unblocking. 935 dispatchInsts(tid); 936 937 ++iewUnblockCycles; 938 939 if (validInstsFromRename() && dispatchedAllInsts) { 940 // Add the current inputs to the skid buffer so they can be 941 // reprocessed when this stage unblocks. 942 skidInsert(tid); 943 } 944 945 unblock(tid); 946 } 947} 948 949template <class Impl> 950void 951DefaultIEW<Impl>::dispatchInsts(unsigned tid) 952{ 953 dispatchedAllInsts = true; 954 955 // Obtain instructions from skid buffer if unblocking, or queue from rename 956 // otherwise. 957 std::queue<DynInstPtr> &insts_to_dispatch = 958 dispatchStatus[tid] == Unblocking ? 959 skidBuffer[tid] : insts[tid]; 960 961 int insts_to_add = insts_to_dispatch.size(); 962 963 DynInstPtr inst; 964 bool add_to_iq = false; 965 int dis_num_inst = 0; 966 967 // Loop through the instructions, putting them in the instruction 968 // queue. 969 for ( ; dis_num_inst < insts_to_add && 970 dis_num_inst < issueReadWidth; 971 ++dis_num_inst) 972 { 973 inst = insts_to_dispatch.front(); 974 975 if (dispatchStatus[tid] == Unblocking) { 976 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 977 "buffer\n", tid); 978 } 979 980 // Make sure there's a valid instruction there. 981 assert(inst); 982 983 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to " 984 "IQ.\n", 985 tid, inst->readPC(), inst->seqNum, inst->threadNumber); 986 987 // Be sure to mark these instructions as ready so that the 988 // commit stage can go ahead and execute them, and mark 989 // them as issued so the IQ doesn't reprocess them. 990 // ------------- 991 // @TODO: What happens if the ldstqueue is full? 992 // Do we process the other instructions? 993 994 // Check for squashed instructions. 995 if (inst->isSquashed()) { 996 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 997 "not adding to IQ.\n", tid); 998 999 ++iewDispSquashedInsts; 1000 1001 insts_to_dispatch.pop(); 1002 1003 //Tell Rename That An Instruction has been processed 1004 if (inst->isLoad() || inst->isStore()) { 1005 toRename->iewInfo[tid].dispatchedToLSQ++; 1006 } 1007 toRename->iewInfo[tid].dispatched++; 1008 1009 continue; 1010 } 1011 1012 // Check for full conditions. 1013 if (instQueue.isFull(tid)) { 1014 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1015 1016 // Call function to start blocking. 1017 block(tid); 1018 1019 // Set unblock to false. Special case where we are using 1020 // skidbuffer (unblocking) instructions but then we still 1021 // get full in the IQ. 1022 toRename->iewUnblock[tid] = false; 1023 1024 dispatchedAllInsts = false; 1025 1026 ++iewIQFullEvents; 1027 break; 1028 } else if (ldstQueue.isFull(tid)) { 1029 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1030 1031 // Call function to start blocking. 1032 block(tid); 1033 1034 // Set unblock to false. Special case where we are using 1035 // skidbuffer (unblocking) instructions but then we still 1036 // get full in the IQ. 1037 toRename->iewUnblock[tid] = false; 1038 1039 dispatchedAllInsts = false; 1040 1041 ++iewLSQFullEvents; 1042 break; 1043 } 1044 1045 // Otherwise issue the instruction just fine. 1046 if (inst->isLoad()) { 1047 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1048 "encountered, adding to LSQ.\n", tid); 1049 1050 // Reserve a spot in the load store queue for this 1051 // memory access. 1052 ldstQueue.insertLoad(inst); 1053 1054 ++iewDispLoadInsts; 1055 1056 add_to_iq = true; 1057 1058 toRename->iewInfo[tid].dispatchedToLSQ++; 1059 } else if (inst->isStore()) { 1060 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1061 "encountered, adding to LSQ.\n", tid); 1062 1063 ldstQueue.insertStore(inst); 1064 1065 ++iewDispStoreInsts; 1066 1067 if (inst->isNonSpeculative()) { 1068 inst->setCanCommit(); 1069 instQueue.insertNonSpec(inst); 1070 add_to_iq = false; 1071 1072 ++iewDispNonSpecInsts; 1073 } else { 1074 add_to_iq = true; 1075 } 1076 1077 toRename->iewInfo[tid].dispatchedToLSQ++; 1078#if FULL_SYSTEM 1079 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1080 inst->setCanCommit(); 1081 instQueue.insertBarrier(inst); 1082 add_to_iq = false; 1083#endif 1084 } else if (inst->isNonSpeculative()) { 1085 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1086 "encountered, skipping.\n", tid); 1087 1088 // Same hack as with stores. 1089 inst->setCanCommit(); 1090 1091 // Specifically insert it as nonspeculative. 1092 instQueue.insertNonSpec(inst); 1093 1094 ++iewDispNonSpecInsts; 1095 1096 add_to_iq = false; 1097 } else if (inst->isNop()) { 1098 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1099 "skipping.\n", tid); 1100 1101 inst->setIssued(); 1102 inst->setExecuted(); 1103 inst->setCanCommit(); 1104 1105 instQueue.advanceTail(inst); 1106 1107 exe_nop[tid]++; 1108 1109 add_to_iq = false; 1110 } else if (inst->isExecuted()) { 1111 assert(0 && "Instruction shouldn't be executed.\n"); 1112 DPRINTF(IEW, "Issue: Executed branch encountered, " 1113 "skipping.\n"); 1114 1115 inst->setIssued(); 1116 inst->setCanCommit(); 1117 1118 instQueue.advanceTail(inst); 1119 1120 add_to_iq = false; 1121 } else { 1122 add_to_iq = true; 1123 } 1124 1125 // If the instruction queue is not full, then add the 1126 // instruction. 1127 if (add_to_iq) { 1128 instQueue.insert(inst); 1129 } 1130 1131 insts_to_dispatch.pop(); 1132 1133 toRename->iewInfo[tid].dispatched++; 1134 1135 ++iewDispatchedInsts; 1136 } 1137 1138 if (!insts_to_dispatch.empty()) { 1139 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n"); 1140 block(tid); 1141 toRename->iewUnblock[tid] = false; 1142 } 1143 1144 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1145 dispatchStatus[tid] = Running; 1146 1147 updatedQueues = true; 1148 } 1149 1150 dis_num_inst = 0; 1151} 1152 1153template <class Impl> 1154void 1155DefaultIEW<Impl>::printAvailableInsts() 1156{ 1157 int inst = 0; 1158 1159 cout << "Available Instructions: "; 1160 1161 while (fromIssue->insts[inst]) { 1162 1163 if (inst%3==0) cout << "\n\t"; 1164 1165 cout << "PC: " << fromIssue->insts[inst]->readPC() 1166 << " TN: " << fromIssue->insts[inst]->threadNumber 1167 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1168 1169 inst++; 1170 1171 } 1172 1173 cout << "\n"; 1174} 1175 1176template <class Impl> 1177void 1178DefaultIEW<Impl>::executeInsts() 1179{ 1180 //bool fetch_redirect[(*activeThreads).size()]; 1181 wbNumInst = 0; 1182 wbCycle = 0; 1183 1184 list<unsigned>::iterator threads = (*activeThreads).begin(); 1185 1186 while (threads != (*activeThreads).end()) { 1187 unsigned tid = *threads++; 1188 fetchRedirect[tid] = false; 1189 } 1190 1191#if 0 1192 printAvailableInsts(); 1193#endif 1194 1195 // Execute/writeback any instructions that are available. 1196 int inst_num = 0; 1197 for ( ; inst_num < issueWidth && /* Haven't exceeded issue bandwidth */ 1198 fromIssue->insts[inst_num]; 1199 ++inst_num) { 1200 1201 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1202 1203 // Get instruction from issue's queue. 1204 DynInstPtr inst = fromIssue->insts[inst_num]; 1205 1206 DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", 1207 inst->readPC(), inst->threadNumber,inst->seqNum); 1208 1209 // Check if the instruction is squashed; if so then skip it 1210 // and don't count it towards the FU usage. 1211 if (inst->isSquashed()) { 1212 DPRINTF(IEW, "Execute: Instruction was squashed.\n"); 1213 1214 // Consider this instruction executed so that commit can go 1215 // ahead and retire the instruction. 1216 inst->setExecuted(); 1217 1218 // Not sure if I should set this here or just let commit try to 1219 // commit any squashed instructions. I like the latter a bit more. 1220 inst->setCanCommit(); 1221 1222 ++iewExecSquashedInsts; 1223 1224 continue; 1225 } 1226 1227 Fault fault = NoFault; 1228 1229 // Execute instruction. 1230 // Note that if the instruction faults, it will be handled 1231 // at the commit stage. 1232 if (inst->isMemRef() && 1233 (!inst->isDataPrefetch() && !inst->isInstPrefetch())) { 1234 DPRINTF(IEW, "Execute: Calculating address for memory " 1235 "reference.\n"); 1236 1237 // Tell the LDSTQ to execute this instruction (if it is a load). 1238 if (inst->isLoad()) { 1239 // Loads will mark themselves as executed, and their writeback 1240 // event adds the instruction to the queue to commit 1241 fault = ldstQueue.executeLoad(inst); 1242 1243// ++iewExecLoadInsts; 1244 } else if (inst->isStore()) { 1245 ldstQueue.executeStore(inst); 1246 1247// ++iewExecStoreInsts; 1248 1249 // If the store had a fault then it may not have a mem req 1250 if (inst->req && !(inst->req->flags & LOCKED)) { 1251 inst->setExecuted(); 1252 1253 instToCommit(inst); 1254 } 1255 // Store conditionals will mark themselves as executed, and 1256 // their writeback event will add the instruction to the queue 1257 // to commit. 1258 } else { 1259 panic("Unexpected memory type!\n"); 1260 } 1261 1262 } else { 1263 inst->execute(); 1264 1265 inst->setExecuted(); 1266 1267 instToCommit(inst); 1268 } 1269 1270 updateExeInstStats(inst); 1271 1272 // Check if branch was correct. This check happens after the 1273 // instruction is added to the queue because even if the branch 1274 // is mispredicted, the branch instruction itself is still valid. 1275 // Only handle this if there hasn't already been something that 1276 // redirects fetch in this group of instructions. 1277 1278 // This probably needs to prioritize the redirects if a different 1279 // scheduler is used. Currently the scheduler schedules the oldest 1280 // instruction first, so the branch resolution order will be correct. 1281 unsigned tid = inst->threadNumber; 1282 1283 if (!fetchRedirect[tid]) { 1284 1285 if (inst->mispredicted()) { 1286 fetchRedirect[tid] = true; 1287 1288 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1289 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", 1290 inst->nextPC); 1291 1292 // If incorrect, then signal the ROB that it must be squashed. 1293 squashDueToBranch(inst, tid); 1294 1295 if (inst->predTaken()) { 1296 predictedTakenIncorrect++; 1297 } else { 1298 predictedNotTakenIncorrect++; 1299 } 1300 } else if (ldstQueue.violation(tid)) { 1301 fetchRedirect[tid] = true; 1302 1303 // Get the DynInst that caused the violation. Note that this 1304 // clears the violation signal. 1305 DynInstPtr violator; 1306 violator = ldstQueue.getMemDepViolator(tid); 1307 1308 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1309 "%#x, inst PC: %#x. Addr is: %#x.\n", 1310 violator->readPC(), inst->readPC(), inst->physEffAddr); 1311 1312 // Tell the instruction queue that a violation has occured. 1313 instQueue.violation(inst, violator); 1314 1315 // Squash. 1316 squashDueToMemOrder(inst,tid); 1317 1318 ++memOrderViolationEvents; 1319 } else if (ldstQueue.loadBlocked(tid) && 1320 !ldstQueue.isLoadBlockedHandled(tid)) { 1321 fetchRedirect[tid] = true; 1322 1323 DPRINTF(IEW, "Load operation couldn't execute because the " 1324 "memory system is blocked. PC: %#x [sn:%lli]\n", 1325 inst->readPC(), inst->seqNum); 1326 1327 squashDueToMemBlocked(inst, tid); 1328 } 1329 } 1330 } 1331 1332 if (inst_num) { 1333 if (exeStatus == Idle) { 1334 exeStatus = Running; 1335 } 1336 1337 updatedQueues = true; 1338 1339 cpu->activityThisCycle(); 1340 } 1341 1342 // Need to reset this in case a writeback event needs to write into the 1343 // iew queue. That way the writeback event will write into the correct 1344 // spot in the queue. 1345 wbNumInst = 0; 1346} 1347 1348template <class Impl> 1349void 1350DefaultIEW<Impl>::writebackInsts() 1351{ 1352 // Loop through the head of the time buffer and wake any dependents. 1353 // These instructions are about to write back. In the simple model 1354 // this loop can really happen within the previous loop, but when 1355 // instructions have actual latencies, this loop must be separate. 1356 // Also mark scoreboard that this instruction is finally complete. 1357 // Either have IEW have direct access to rename map, or have this as 1358 // part of backwards communication. 1359 for (int inst_num = 0; inst_num < issueWidth && 1360 toCommit->insts[inst_num]; inst_num++) { 1361 DynInstPtr inst = toCommit->insts[inst_num]; 1362 int tid = inst->threadNumber; 1363 1364 DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n", 1365 inst->readPC()); 1366 1367 iewInstsToCommit[tid]++; 1368 1369 // Some instructions will be sent to commit without having 1370 // executed because they need commit to handle them. 1371 // E.g. Uncached loads have not actually executed when they 1372 // are first sent to commit. Instead commit must tell the LSQ 1373 // when it's ready to execute the uncached load. 1374 if (!inst->isSquashed() && inst->isExecuted()) { 1375 int dependents = instQueue.wakeDependents(inst); 1376 1377 for (int i = 0; i < inst->numDestRegs(); i++) { 1378 //mark as Ready 1379 DPRINTF(IEW,"Setting Destination Register %i\n", 1380 inst->renamedDestRegIdx(i)); 1381 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1382 } 1383 1384 producer_inst[tid]++; 1385 consumer_inst[tid]+= dependents; 1386 writeback_count[tid]++; 1387 } 1388 } 1389} 1390 1391template<class Impl> 1392void 1393DefaultIEW<Impl>::tick() 1394{ 1395 // Try to fill up issue queue with as many instructions as bandwidth 1396 // allows. 1397 wbNumInst = 0; 1398 wbCycle = 0; 1399 1400 wroteToTimeBuffer = false; 1401 updatedQueues = false; 1402 1403 sortInsts(); 1404 1405 list<unsigned>::iterator threads = (*activeThreads).begin(); 1406 1407 // Check stall and squash signals. 1408 while (threads != (*activeThreads).end()) { 1409 unsigned tid = *threads++; 1410 1411 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1412 1413 checkSignalsAndUpdate(tid); 1414 dispatch(tid); 1415 1416 } 1417 1418 if (exeStatus != Squashing) { 1419 executeInsts(); 1420 1421 writebackInsts(); 1422 1423 // Have the instruction queue try to schedule any ready instructions. 1424 // (In actuality, this scheduling is for instructions that will 1425 // be executed next cycle.) 1426 instQueue.scheduleReadyInsts(); 1427 1428 // Also should advance its own time buffers if the stage ran. 1429 // Not the best place for it, but this works (hopefully). 1430 issueToExecQueue.advance(); 1431 } 1432 1433 bool broadcast_free_entries = false; 1434 1435 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1436 exeStatus = Idle; 1437 updateLSQNextCycle = false; 1438 1439 broadcast_free_entries = true; 1440 } 1441 1442 // Writeback any stores using any leftover bandwidth. 1443 ldstQueue.writebackStores(); 1444 1445 // Free function units marked as being freed this cycle. 1446 fuPool->processFreeUnits(); 1447 1448 // Check the committed load/store signals to see if there's a load 1449 // or store to commit. Also check if it's being told to execute a 1450 // nonspeculative instruction. 1451 // This is pretty inefficient... 1452 1453 threads = (*activeThreads).begin(); 1454 while (threads != (*activeThreads).end()) { 1455 unsigned tid = (*threads++); 1456 1457 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1458 1459 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1460 !fromCommit->commitInfo[tid].squash && 1461 !fromCommit->commitInfo[tid].robSquashing) { 1462 1463 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1464 1465 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1466 1467 updateLSQNextCycle = true; 1468 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1469 } 1470 1471 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1472 1473 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1474 if (fromCommit->commitInfo[tid].uncached) { 1475 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1476 } else { 1477 instQueue.scheduleNonSpec( 1478 fromCommit->commitInfo[tid].nonSpecSeqNum); 1479 } 1480 } 1481 1482 if (broadcast_free_entries) { 1483 toFetch->iewInfo[tid].iqCount = 1484 instQueue.getCount(tid); 1485 toFetch->iewInfo[tid].ldstqCount = 1486 ldstQueue.getCount(tid); 1487 1488 toRename->iewInfo[tid].usedIQ = true; 1489 toRename->iewInfo[tid].freeIQEntries = 1490 instQueue.numFreeEntries(); 1491 toRename->iewInfo[tid].usedLSQ = true; 1492 toRename->iewInfo[tid].freeLSQEntries = 1493 ldstQueue.numFreeEntries(tid); 1494 1495 wroteToTimeBuffer = true; 1496 } 1497 1498 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1499 tid, toRename->iewInfo[tid].dispatched); 1500 1501 //thread_queue.pop(); 1502 } 1503 1504 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1505 "LSQ has %i free entries.\n", 1506 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1507 ldstQueue.numFreeEntries()); 1508 1509 updateStatus(); 1510 1511 if (wroteToTimeBuffer) { 1512 DPRINTF(Activity, "Activity this cycle.\n"); 1513 cpu->activityThisCycle(); 1514 } 1515} 1516 1517template <class Impl> 1518void 1519DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1520{ 1521 int thread_number = inst->threadNumber; 1522 1523 // 1524 // Pick off the software prefetches 1525 // 1526#ifdef TARGET_ALPHA 1527 if (inst->isDataPrefetch()) 1528 exe_swp[thread_number]++; 1529 else 1530 iewExecutedInsts++; 1531#else 1532 iewExecutedInsts[thread_number]++; 1533#endif 1534 1535 // 1536 // Control operations 1537 // 1538 if (inst->isControl()) 1539 exe_branches[thread_number]++; 1540 1541 // 1542 // Memory operations 1543 // 1544 if (inst->isMemRef()) { 1545 exe_refs[thread_number]++; 1546 1547 if (inst->isLoad()) { 1548 iewExecLoadInsts[thread_number]++; 1549 } 1550 } 1551} 1552