gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
iew.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2013, 2018-2019 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42// @todo: Fix the instantaneous communication among all the stages within
43// iew. There's a clear delay between issue and execute, yet backwards
44// communication happens simultaneously.
45
46#include "cpu/o3/iew.hh"
47
48#include <queue>
49
50#include "cpu/checker/cpu.hh"
51#include "cpu/o3/dyn_inst.hh"
52#include "cpu/o3/fu_pool.hh"
53#include "cpu/o3/limits.hh"
54#include "cpu/timebuf.hh"
55#include "debug/Activity.hh"
56#include "debug/Drain.hh"
57#include "debug/IEW.hh"
58#include "debug/O3PipeView.hh"
59#include "params/BaseO3CPU.hh"
60
61namespace gem5
62{
63
64namespace o3
65{
66
67IEW::IEW(CPU *_cpu, const BaseO3CPUParams &params)
68 : issueToExecQueue(params.backComSize, params.forwardComSize),
69 cpu(_cpu),
70 instQueue(_cpu, this, params),
71 ldstQueue(_cpu, this, params),
72 fuPool(params.fuPool),
77 issueWidth(params.issueWidth),
78 wbNumInst(0),
79 wbCycle(0),
80 wbWidth(params.wbWidth),
81 numThreads(params.numThreads),
83{
85 fatal("dispatchWidth (%d) is larger than compiled limit (%d),\n"
86 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
87 dispatchWidth, static_cast<int>(MaxWidth));
88 if (issueWidth > MaxWidth)
89 fatal("issueWidth (%d) is larger than compiled limit (%d),\n"
90 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
91 issueWidth, static_cast<int>(MaxWidth));
92 if (wbWidth > MaxWidth)
93 fatal("wbWidth (%d) is larger than compiled limit (%d),\n"
94 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
95 wbWidth, static_cast<int>(MaxWidth));
96
99 wbStatus = Idle;
100
101 // Setup wire to read instructions coming from issue.
103
104 // Instruction queue needs the queue between issue and execute.
105 instQueue.setIssueToExecuteQueue(&issueToExecQueue);
106
107 for (ThreadID tid = 0; tid < MaxThreads; tid++) {
108 dispatchStatus[tid] = Running;
109 fetchRedirect[tid] = false;
110 }
111
112 updateLSQNextCycle = false;
113
114 skidBufferMax = (renameToIEWDelay + 1) * params.renameWidth;
115}
116
117std::string
119{
120 return cpu->name() + ".iew";
121}
122
123void
125{
127 cpu->getProbeManager(), "Dispatch");
129 cpu->getProbeManager(), "Mispredict");
135 cpu->getProbeManager(), "Execute");
141 cpu->getProbeManager(), "ToCommit");
142}
143
145 : statistics::Group(cpu, "iew"),
146 ADD_STAT(idleCycles, statistics::units::Cycle::get(),
147 "Number of cycles IEW is idle"),
148 ADD_STAT(squashCycles, statistics::units::Cycle::get(),
149 "Number of cycles IEW is squashing"),
150 ADD_STAT(blockCycles, statistics::units::Cycle::get(),
151 "Number of cycles IEW is blocking"),
152 ADD_STAT(unblockCycles, statistics::units::Cycle::get(),
153 "Number of cycles IEW is unblocking"),
155 "Number of instructions dispatched to IQ"),
157 "Number of squashed instructions skipped by dispatch"),
158 ADD_STAT(dispLoadInsts, statistics::units::Count::get(),
159 "Number of dispatched load instructions"),
160 ADD_STAT(dispStoreInsts, statistics::units::Count::get(),
161 "Number of dispatched store instructions"),
163 "Number of dispatched non-speculative instructions"),
164 ADD_STAT(iqFullEvents, statistics::units::Count::get(),
165 "Number of times the IQ has become full, causing a stall"),
166 ADD_STAT(lsqFullEvents, statistics::units::Count::get(),
167 "Number of times the LSQ has become full, causing a stall"),
169 "Number of memory order violations"),
171 "Number of branches that were predicted taken incorrectly"),
173 "Number of branches that were predicted not taken incorrectly"),
175 "Number of branch mispredicts detected at execute",
178 ADD_STAT(instsToCommit, statistics::units::Count::get(),
179 "Cumulative count of insts sent to commit"),
180 ADD_STAT(writebackCount, statistics::units::Count::get(),
181 "Cumulative count of insts written-back"),
182 ADD_STAT(producerInst, statistics::units::Count::get(),
183 "Number of instructions producing a value"),
184 ADD_STAT(consumerInst, statistics::units::Count::get(),
185 "Number of instructions consuming a value"),
187 statistics::units::Count, statistics::units::Cycle>::get(),
188 "Insts written-back per cycle"),
190 statistics::units::Count, statistics::units::Count>::get(),
191 "Average fanout of values written-back")
192{
194 .init(cpu->numThreads)
195 .flags(statistics::total);
196
198 .init(cpu->numThreads)
199 .flags(statistics::total);
200
202 .init(cpu->numThreads)
203 .flags(statistics::total);
204
206 .init(cpu->numThreads)
207 .flags(statistics::total);
208
209 wbRate
210 .flags(statistics::total);
211 wbRate = writebackCount / cpu->baseStats.numCycles;
212
214 .flags(statistics::total);
216}
217
219 : statistics::Group(cpu),
221 "Number of squashed instructions skipped in execute"),
222 ADD_STAT(numSwp, statistics::units::Count::get(),
223 "Number of swp insts executed")
224{
225 numSwp
226 .init(cpu->numThreads)
227 .flags(statistics::total);
228}
229
230void
232{
233 for (ThreadID tid = 0; tid < numThreads; tid++) {
234 toRename->iewInfo[tid].usedIQ = true;
235 toRename->iewInfo[tid].freeIQEntries =
236 instQueue.numFreeEntries(tid);
237
238 toRename->iewInfo[tid].usedLSQ = true;
239 toRename->iewInfo[tid].freeLQEntries =
240 ldstQueue.numFreeLoadEntries(tid);
241 toRename->iewInfo[tid].freeSQEntries =
242 ldstQueue.numFreeStoreEntries(tid);
243 }
244
245 // Initialize the checker's dcache port here
246 if (cpu->checker) {
247 cpu->checker->setDcachePort(&ldstQueue.getDataPort());
248 }
249
250 cpu->activateStage(CPU::IEWIdx);
251}
252
253void
255{
256 toRename->iewInfo[tid].usedIQ = true;
257 toRename->iewInfo[tid].freeIQEntries =
258 instQueue.numFreeEntries(tid);
259
260 toRename->iewInfo[tid].usedLSQ = true;
261 toRename->iewInfo[tid].freeLQEntries = ldstQueue.numFreeLoadEntries(tid);
262 toRename->iewInfo[tid].freeSQEntries = ldstQueue.numFreeStoreEntries(tid);
263
264 // Clear out any of this thread's instructions being sent to commit.
265 for (int i = -cpu->iewQueue.getPast();
266 i <= cpu->iewQueue.getFuture(); ++i) {
267 IEWStruct& iew_struct = cpu->iewQueue[i];
268 removeCommThreadInsts(tid, iew_struct);
269 iew_struct.mispredictInst[tid] = nullptr;
270 iew_struct.mispredPC[tid] = 0;
271 iew_struct.squashedSeqNum[tid] = 0;
272 iew_struct.pc[tid] = nullptr;
273 iew_struct.squash[tid] = false;
274 iew_struct.branchMispredict[tid] = false;
275 iew_struct.branchTaken[tid] = false;
276 iew_struct.includeSquashInst[tid] = false;
277 }
278
279 // Clear out any of this thread's instructions being sent from
280 // issue to execute.
281 for (int i = -issueToExecQueue.getPast();
282 i <= issueToExecQueue.getFuture(); ++i)
284
285 // Clear out any of this thread's instructions being sent to prior stages.
286 for (int i = -cpu->timeBuffer.getPast();
287 i <= cpu->timeBuffer.getFuture(); ++i) {
288 TimeStruct& time_struct = cpu->timeBuffer[i];
289 time_struct.iewInfo[tid] = {};
290 time_struct.iewBlock[tid] = false;
291 time_struct.iewUnblock[tid] = false;
292 }
293}
294
295void
297{
298 timeBuffer = tb_ptr;
299
300 // Setup wire to read information from time buffer, from commit.
302
303 // Setup wire to write information back to previous stages.
304 toRename = timeBuffer->getWire(0);
305
306 toFetch = timeBuffer->getWire(0);
307
308 // Instruction queue also needs main time buffer.
309 instQueue.setTimeBuffer(tb_ptr);
310}
311
312void
314{
315 renameQueue = rq_ptr;
316
317 // Setup wire to read information from rename queue.
319}
320
321void
323{
324 iewQueue = iq_ptr;
325
326 // Setup wire to write instructions to commit.
327 toCommit = iewQueue->getWire(0);
328}
329
330void
332{
333 activeThreads = at_ptr;
334
335 ldstQueue.setActiveThreads(at_ptr);
336 instQueue.setActiveThreads(at_ptr);
337}
338
339void
341{
342 scoreboard = sb_ptr;
343}
344
345bool
347{
348 bool drained = ldstQueue.isDrained() && instQueue.isDrained();
349
350 for (ThreadID tid = 0; tid < numThreads; tid++) {
351 if (!insts[tid].empty()) {
352 DPRINTF(Drain, "%i: Insts not empty.\n", tid);
353 drained = false;
354 }
355 if (!skidBuffer[tid].empty()) {
356 DPRINTF(Drain, "%i: Skid buffer not empty.\n", tid);
357 drained = false;
358 }
359 drained = drained && dispatchStatus[tid] == Running;
360 }
361
362 // Also check the FU pool as instructions are "stored" in FU
363 // completion events until they are done and not accounted for
364 // above
365 if (drained && !fuPool->isDrained()) {
366 DPRINTF(Drain, "FU pool still busy.\n");
367 drained = false;
368 }
369
370 return drained;
371}
372
373void
375{
376 assert(isDrained());
377
378 instQueue.drainSanityCheck();
379 ldstQueue.drainSanityCheck();
380}
381
382void
384{
385 // Reset all state.
386 _status = Active;
388 wbStatus = Idle;
389
390 instQueue.takeOverFrom();
391 ldstQueue.takeOverFrom();
392 fuPool->takeOverFrom();
393
394 startupStage();
395 cpu->activityThisCycle();
396
397 for (ThreadID tid = 0; tid < numThreads; tid++) {
398 dispatchStatus[tid] = Running;
399 fetchRedirect[tid] = false;
400 }
401
402 updateLSQNextCycle = false;
403
404 for (int i = 0; i < issueToExecQueue.getSize(); ++i) {
405 issueToExecQueue.advance();
406 }
407}
408
409void
411{
412 DPRINTF(IEW, "[tid:%i] Squashing all instructions.\n", tid);
413
414 // Tell the IQ to start squashing.
415 instQueue.squash(tid);
416
417 // Tell the LDSTQ to start squashing.
418 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
419 updatedQueues = true;
420
421 // Clear the skid buffer in case it has any data in it.
422 DPRINTF(IEW,
423 "Removing skidbuffer instructions until "
424 "[sn:%llu] [tid:%i]\n",
425 fromCommit->commitInfo[tid].doneSeqNum, tid);
426
427 while (!skidBuffer[tid].empty()) {
428 if (skidBuffer[tid].front()->isLoad()) {
429 toRename->iewInfo[tid].dispatchedToLQ++;
430 }
431 if (skidBuffer[tid].front()->isStore() ||
432 skidBuffer[tid].front()->isAtomic()) {
433 toRename->iewInfo[tid].dispatchedToSQ++;
434 }
435
436 toRename->iewInfo[tid].dispatched++;
437
438 skidBuffer[tid].pop();
439 }
440
441 emptyRenameInsts(tid);
442}
443
444void
446{
447 DPRINTF(IEW, "[tid:%i] [sn:%llu] Squashing from a specific instruction,"
448 " PC: %s "
449 "\n", tid, inst->seqNum, inst->pcState() );
450
451 if (!toCommit->squash[tid] ||
452 inst->seqNum < toCommit->squashedSeqNum[tid]) {
453 toCommit->squash[tid] = true;
454 toCommit->squashedSeqNum[tid] = inst->seqNum;
455 toCommit->branchTaken[tid] = inst->pcState().branching();
456
457 set(toCommit->pc[tid], inst->pcState());
458 inst->staticInst->advancePC(*toCommit->pc[tid]);
459
460 toCommit->mispredictInst[tid] = inst;
461 toCommit->includeSquashInst[tid] = false;
462
463 wroteToTimeBuffer = true;
464 }
465
466}
467
468void
470{
471 DPRINTF(IEW, "[tid:%i] Memory violation, squashing violator and younger "
472 "insts, PC: %s [sn:%llu].\n", tid, inst->pcState(), inst->seqNum);
473 // Need to include inst->seqNum in the following comparison to cover the
474 // corner case when a branch misprediction and a memory violation for the
475 // same instruction (e.g. load PC) are detected in the same cycle. In this
476 // case the memory violator should take precedence over the branch
477 // misprediction because it requires the violator itself to be included in
478 // the squash.
479 if (!toCommit->squash[tid] ||
480 inst->seqNum <= toCommit->squashedSeqNum[tid]) {
481 toCommit->squash[tid] = true;
482
483 toCommit->squashedSeqNum[tid] = inst->seqNum;
484 set(toCommit->pc[tid], inst->pcState());
485 toCommit->mispredictInst[tid] = NULL;
486
487 // Must include the memory violator in the squash.
488 toCommit->includeSquashInst[tid] = true;
489
490 wroteToTimeBuffer = true;
491 }
492}
493
494void
496{
497 DPRINTF(IEW, "[tid:%i] Blocking.\n", tid);
498
499 if (dispatchStatus[tid] != Blocked &&
500 dispatchStatus[tid] != Unblocking) {
501 toRename->iewBlock[tid] = true;
502 wroteToTimeBuffer = true;
503 }
504
505 // Add the current inputs to the skid buffer so they can be
506 // reprocessed when this stage unblocks.
507 skidInsert(tid);
508
509 dispatchStatus[tid] = Blocked;
510}
511
512void
514{
515 DPRINTF(IEW, "[tid:%i] Reading instructions out of the skid "
516 "buffer %u.\n",tid, tid);
517
518 // If the skid bufffer is empty, signal back to previous stages to unblock.
519 // Also switch status to running.
520 if (skidBuffer[tid].empty()) {
521 toRename->iewUnblock[tid] = true;
522 wroteToTimeBuffer = true;
523 DPRINTF(IEW, "[tid:%i] Done unblocking.\n",tid);
524 dispatchStatus[tid] = Running;
525 }
526}
527
528void
530{
531 instQueue.wakeDependents(inst);
532}
533
534void
536{
537 instQueue.rescheduleMemInst(inst);
538}
539
540void
542{
543 instQueue.replayMemInst(inst);
544}
545
546void
548{
549 instQueue.blockMemInst(inst);
550}
551
552void
554{
555 instQueue.retryMemInst(inst);
556}
557
558void
560{
561 instQueue.cacheUnblocked();
562}
563
564void
566{
567 // This function should not be called after writebackInsts in a
568 // single cycle. That will cause problems with an instruction
569 // being added to the queue to commit without being processed by
570 // writebackInsts prior to being sent to commit.
571
572 // First check the time slot that this instruction will write
573 // to. If there are free write ports at the time, then go ahead
574 // and write the instruction to that time. If there are not,
575 // keep looking back to see where's the first time there's a
576 // free slot.
577 while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
578 ++wbNumInst;
579 if (wbNumInst == wbWidth) {
580 ++wbCycle;
581 wbNumInst = 0;
582 }
583 }
584
585 DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n",
587 // Add finished instruction to queue to commit.
588 (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
589 (*iewQueue)[wbCycle].size++;
590}
591
592void
594{
595 DynInstPtr inst = NULL;
596
597 while (!insts[tid].empty()) {
598 inst = insts[tid].front();
599
600 insts[tid].pop();
601
602 DPRINTF(IEW,"[tid:%i] Inserting [sn:%lli] PC:%s into "
603 "dispatch skidBuffer %i\n",tid, inst->seqNum,
604 inst->pcState(),tid);
605
606 skidBuffer[tid].push(inst);
607 }
608
609 assert(skidBuffer[tid].size() <= skidBufferMax &&
610 "Skidbuffer Exceeded Max Size");
611}
612
613int
615{
616 int max=0;
617
618 for (ThreadID tid : *activeThreads) {
619 unsigned thread_count = skidBuffer[tid].size();
620 if (max < thread_count)
621 max = thread_count;
622 }
623
624 return max;
625}
626
627bool
629{
630 for (ThreadID tid : *activeThreads) {
631 if (!skidBuffer[tid].empty())
632 return false;
633 }
634
635 return true;
636}
637
638void
640{
641 bool any_unblocking = false;
642
643 for (ThreadID tid : *activeThreads) {
644 if (dispatchStatus[tid] == Unblocking) {
645 any_unblocking = true;
646 break;
647 }
648 }
649
650 // If there are no ready instructions waiting to be scheduled by the IQ,
651 // and there's no stores waiting to write back, and dispatch is not
652 // unblocking, then there is no internal activity for the IEW stage.
653 instQueue.iqIOStats.intInstQueueReads++;
654 if (_status == Active && !instQueue.hasReadyInsts() &&
655 !ldstQueue.willWB() && !any_unblocking) {
656 DPRINTF(IEW, "IEW switching to idle\n");
657
659
661 } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
662 ldstQueue.willWB() ||
663 any_unblocking)) {
664 // Otherwise there is internal activity. Set to active.
665 DPRINTF(IEW, "IEW switching to active\n");
666
668
669 _status = Active;
670 }
671}
672
673bool
675{
676 bool ret_val(false);
677
678 if (fromCommit->commitInfo[tid].robSquashing) {
679 DPRINTF(IEW,"[tid:%i] Stall from Commit stage detected.\n",tid);
680 ret_val = true;
681 } else if (instQueue.isFull(tid)) {
682 DPRINTF(IEW,"[tid:%i] Stall: IQ is full.\n",tid);
683 ret_val = true;
684 }
685
686 return ret_val;
687}
688
689void
691{
692 // Check if there's a squash signal, squash if there is
693 // Check stall signals, block if there is.
694 // If status was Blocked
695 // if so then go to unblocking
696 // If status was Squashing
697 // check if squashing is not high. Switch to running this cycle.
698
699 if (fromCommit->commitInfo[tid].squash) {
700 squash(tid);
701
702 if (dispatchStatus[tid] == Blocked ||
703 dispatchStatus[tid] == Unblocking) {
704 toRename->iewUnblock[tid] = true;
705 wroteToTimeBuffer = true;
706 }
707
709 fetchRedirect[tid] = false;
710 return;
711 }
712
713 if (fromCommit->commitInfo[tid].robSquashing) {
714 DPRINTF(IEW, "[tid:%i] ROB is still squashing.\n", tid);
715
717 emptyRenameInsts(tid);
718 wroteToTimeBuffer = true;
719 }
720
721 if (checkStall(tid)) {
722 block(tid);
723 dispatchStatus[tid] = Blocked;
724 return;
725 }
726
727 if (dispatchStatus[tid] == Blocked) {
728 // Status from previous cycle was blocked, but there are no more stall
729 // conditions. Switch over to unblocking.
730 DPRINTF(IEW, "[tid:%i] Done blocking, switching to unblocking.\n",
731 tid);
732
734
735 unblock(tid);
736
737 return;
738 }
739
740 if (dispatchStatus[tid] == Squashing) {
741 // Switch status to running if rename isn't being told to block or
742 // squash this cycle.
743 DPRINTF(IEW, "[tid:%i] Done squashing, switching to running.\n",
744 tid);
745
746 dispatchStatus[tid] = Running;
747
748 return;
749 }
750}
751
752void
754{
755 int insts_from_rename = fromRename->size;
756#ifdef GEM5_DEBUG
757 for (ThreadID tid = 0; tid < numThreads; tid++)
758 assert(insts[tid].empty());
759#endif
760 for (int i = 0; i < insts_from_rename; ++i) {
761 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
762 }
763}
764
765void
767{
768 DPRINTF(IEW, "[tid:%i] Removing incoming rename instructions\n", tid);
769
770 while (!insts[tid].empty()) {
771
772 if (insts[tid].front()->isLoad()) {
773 toRename->iewInfo[tid].dispatchedToLQ++;
774 }
775 if (insts[tid].front()->isStore() ||
776 insts[tid].front()->isAtomic()) {
777 toRename->iewInfo[tid].dispatchedToSQ++;
778 }
779
780 toRename->iewInfo[tid].dispatched++;
781
782 insts[tid].pop();
783 }
784}
785
786void
788{
789 cpu->wakeCPU();
790}
791
792void
794{
795 DPRINTF(Activity, "Activity this cycle.\n");
796 cpu->activityThisCycle();
797}
798
799void
801{
802 DPRINTF(Activity, "Activating stage.\n");
803 cpu->activateStage(CPU::IEWIdx);
804}
805
806void
808{
809 DPRINTF(Activity, "Deactivating stage.\n");
810 cpu->deactivateStage(CPU::IEWIdx);
811}
812
813void
815{
816 // If status is Running or idle,
817 // call dispatchInsts()
818 // If status is Unblocking,
819 // buffer any instructions coming from rename
820 // continue trying to empty skid buffer
821 // check if stall conditions have passed
822
823 if (dispatchStatus[tid] == Blocked) {
824 ++iewStats.blockCycles;
825
826 } else if (dispatchStatus[tid] == Squashing) {
827 ++iewStats.squashCycles;
828 }
829
830 // Dispatch should try to dispatch as many instructions as its bandwidth
831 // will allow, as long as it is not currently blocked.
832 if (dispatchStatus[tid] == Running ||
833 dispatchStatus[tid] == Idle) {
834 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
835 "dispatch.\n", tid);
836
837 dispatchInsts(tid);
838 } else if (dispatchStatus[tid] == Unblocking) {
839 // Make sure that the skid buffer has something in it if the
840 // status is unblocking.
841 assert(!skidsEmpty());
842
843 // If the status was unblocking, then instructions from the skid
844 // buffer were used. Remove those instructions and handle
845 // the rest of unblocking.
846 dispatchInsts(tid);
847
848 ++iewStats.unblockCycles;
849
850 if (fromRename->size != 0) {
851 // Add the current inputs to the skid buffer so they can be
852 // reprocessed when this stage unblocks.
853 skidInsert(tid);
854 }
855
856 unblock(tid);
857 }
858}
859
860void
862{
863 // Obtain instructions from skid buffer if unblocking, or queue from rename
864 // otherwise.
865 std::queue<DynInstPtr> &insts_to_dispatch =
866 dispatchStatus[tid] == Unblocking ?
867 skidBuffer[tid] : insts[tid];
868
869 int insts_to_add = insts_to_dispatch.size();
870
871 DynInstPtr inst;
872 bool add_to_iq = false;
873 int dis_num_inst = 0;
874
875 // Loop through the instructions, putting them in the instruction
876 // queue.
877 for ( ; dis_num_inst < insts_to_add &&
878 dis_num_inst < dispatchWidth;
879 ++dis_num_inst)
880 {
881 inst = insts_to_dispatch.front();
882
883 if (dispatchStatus[tid] == Unblocking) {
884 DPRINTF(IEW, "[tid:%i] Issue: Examining instruction from skid "
885 "buffer\n", tid);
886 }
887
888 // Make sure there's a valid instruction there.
889 assert(inst);
890
891 DPRINTF(IEW, "[tid:%i] Issue: Adding PC %s [sn:%lli] [tid:%i] to "
892 "IQ.\n",
893 tid, inst->pcState(), inst->seqNum, inst->threadNumber);
894
895 // Be sure to mark these instructions as ready so that the
896 // commit stage can go ahead and execute them, and mark
897 // them as issued so the IQ doesn't reprocess them.
898
899 // Check for squashed instructions.
900 if (inst->isSquashed()) {
901 DPRINTF(IEW, "[tid:%i] Issue: Squashed instruction encountered, "
902 "not adding to IQ.\n", tid);
903
904 ++iewStats.dispSquashedInsts;
905
906 insts_to_dispatch.pop();
907
908 //Tell Rename That An Instruction has been processed
909 if (inst->isLoad()) {
910 toRename->iewInfo[tid].dispatchedToLQ++;
911 }
912 if (inst->isStore() || inst->isAtomic()) {
913 toRename->iewInfo[tid].dispatchedToSQ++;
914 }
915
916 toRename->iewInfo[tid].dispatched++;
917
918 continue;
919 }
920
921 // Check for full conditions.
922 if (instQueue.isFull(tid)) {
923 DPRINTF(IEW, "[tid:%i] Issue: IQ has become full.\n", tid);
924
925 // Call function to start blocking.
926 block(tid);
927
928 // Set unblock to false. Special case where we are using
929 // skidbuffer (unblocking) instructions but then we still
930 // get full in the IQ.
931 toRename->iewUnblock[tid] = false;
932
933 ++iewStats.iqFullEvents;
934 break;
935 }
936
937 // Check LSQ if inst is LD/ST
938 if ((inst->isAtomic() && ldstQueue.sqFull(tid)) ||
939 (inst->isLoad() && ldstQueue.lqFull(tid)) ||
940 (inst->isStore() && ldstQueue.sqFull(tid))) {
941 DPRINTF(IEW, "[tid:%i] Issue: %s has become full.\n",tid,
942 inst->isLoad() ? "LQ" : "SQ");
943
944 // Call function to start blocking.
945 block(tid);
946
947 // Set unblock to false. Special case where we are using
948 // skidbuffer (unblocking) instructions but then we still
949 // get full in the IQ.
950 toRename->iewUnblock[tid] = false;
951
952 ++iewStats.lsqFullEvents;
953 break;
954 }
955
956 // hardware transactional memory
957 // CPU needs to track transactional state in program order.
958 const int numHtmStarts = ldstQueue.numHtmStarts(tid);
959 const int numHtmStops = ldstQueue.numHtmStops(tid);
960 const int htmDepth = numHtmStarts - numHtmStops;
961
962 if (htmDepth > 0) {
963 inst->setHtmTransactionalState(ldstQueue.getLatestHtmUid(tid),
964 htmDepth);
965 } else {
966 inst->clearHtmTransactionalState();
967 }
968
969
970 // Otherwise issue the instruction just fine.
971 if (inst->isAtomic()) {
972 DPRINTF(IEW, "[tid:%i] Issue: Memory instruction "
973 "encountered, adding to LSQ.\n", tid);
974
975 ldstQueue.insertStore(inst);
976
977 ++iewStats.dispStoreInsts;
978
979 // AMOs need to be set as "canCommit()"
980 // so that commit can process them when they reach the
981 // head of commit.
982 inst->setCanCommit();
983 instQueue.insertNonSpec(inst);
984 add_to_iq = false;
985
986 ++iewStats.dispNonSpecInsts;
987
988 toRename->iewInfo[tid].dispatchedToSQ++;
989 } else if (inst->isLoad()) {
990 DPRINTF(IEW, "[tid:%i] Issue: Memory instruction "
991 "encountered, adding to LSQ.\n", tid);
992
993 // Reserve a spot in the load store queue for this
994 // memory access.
995 ldstQueue.insertLoad(inst);
996
997 ++iewStats.dispLoadInsts;
998
999 add_to_iq = true;
1000
1001 toRename->iewInfo[tid].dispatchedToLQ++;
1002 } else if (inst->isStore()) {
1003 DPRINTF(IEW, "[tid:%i] Issue: Memory instruction "
1004 "encountered, adding to LSQ.\n", tid);
1005
1006 ldstQueue.insertStore(inst);
1007
1008 ++iewStats.dispStoreInsts;
1009
1010 if (inst->isStoreConditional()) {
1011 // Store conditionals need to be set as "canCommit()"
1012 // so that commit can process them when they reach the
1013 // head of commit.
1014 // @todo: This is somewhat specific to Alpha.
1015 inst->setCanCommit();
1016 instQueue.insertNonSpec(inst);
1017 add_to_iq = false;
1018
1019 ++iewStats.dispNonSpecInsts;
1020 } else {
1021 add_to_iq = true;
1022 }
1023
1024 toRename->iewInfo[tid].dispatchedToSQ++;
1025 } else if (inst->isReadBarrier() || inst->isWriteBarrier()) {
1026 // Same as non-speculative stores.
1027 inst->setCanCommit();
1028 instQueue.insertBarrier(inst);
1029 add_to_iq = false;
1030 } else if (inst->isNop()) {
1031 DPRINTF(IEW, "[tid:%i] Issue: Nop instruction encountered, "
1032 "skipping.\n", tid);
1033
1034 inst->setIssued();
1035 inst->setExecuted();
1036 inst->setCanCommit();
1037
1038 instQueue.recordProducer(inst);
1039
1040 cpu->executeStats[tid]->numNop++;
1041
1042 add_to_iq = false;
1043 } else {
1044 assert(!inst->isExecuted());
1045 add_to_iq = true;
1046 }
1047
1048 if (add_to_iq && inst->isNonSpeculative()) {
1049 DPRINTF(IEW, "[tid:%i] Issue: Nonspeculative instruction "
1050 "encountered, skipping.\n", tid);
1051
1052 // Same as non-speculative stores.
1053 inst->setCanCommit();
1054
1055 // Specifically insert it as nonspeculative.
1056 instQueue.insertNonSpec(inst);
1057
1058 ++iewStats.dispNonSpecInsts;
1059
1060 add_to_iq = false;
1061 }
1062
1063 // If the instruction queue is not full, then add the
1064 // instruction.
1065 if (add_to_iq) {
1066 instQueue.insert(inst);
1067 }
1068
1069 insts_to_dispatch.pop();
1070
1071 toRename->iewInfo[tid].dispatched++;
1072
1073 ++iewStats.dispatchedInsts;
1074
1075#if TRACING_ON
1076 inst->dispatchTick = curTick() - inst->fetchTick;
1077#endif
1078 ppDispatch->notify(inst);
1079 }
1080
1081 if (!insts_to_dispatch.empty()) {
1082 DPRINTF(IEW,"[tid:%i] Issue: Bandwidth Full. Blocking.\n", tid);
1083 block(tid);
1084 toRename->iewUnblock[tid] = false;
1085 }
1086
1087 if (dispatchStatus[tid] == Idle && dis_num_inst) {
1088 dispatchStatus[tid] = Running;
1089
1090 updatedQueues = true;
1091 }
1092
1093 dis_num_inst = 0;
1094}
1095
1096void
1098{
1099 int inst = 0;
1100
1101 std::cout << "Available Instructions: ";
1102
1103 while (fromIssue->insts[inst]) {
1104
1105 if (inst%3==0) std::cout << "\n\t";
1106
1107 std::cout << "PC: " << fromIssue->insts[inst]->pcState()
1108 << " TN: " << fromIssue->insts[inst]->threadNumber
1109 << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
1110
1111 inst++;
1112
1113 }
1114
1115 std::cout << "\n";
1116}
1117
1118void
1120{
1121 wbNumInst = 0;
1122 wbCycle = 0;
1123
1124 for (ThreadID tid : *activeThreads) {
1125 fetchRedirect[tid] = false;
1126 }
1127
1128 // Uncomment this if you want to see all available instructions.
1129 // @todo This doesn't actually work anymore, we should fix it.
1130// printAvailableInsts();
1131
1132 // Execute/writeback any instructions that are available.
1133 int insts_to_execute = fromIssue->size;
1134 int inst_num = 0;
1135 for (; inst_num < insts_to_execute;
1136 ++inst_num) {
1137
1138 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
1139
1140 DynInstPtr inst = instQueue.getInstToExecute();
1141
1142 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%llu].\n",
1143 inst->pcState(), inst->threadNumber,inst->seqNum);
1144
1145 // Notify potential listeners that this instruction has started
1146 // executing
1147 ppExecute->notify(inst);
1148
1149 // Check if the instruction is squashed; if so then skip it
1150 if (inst->isSquashed()) {
1151 DPRINTF(IEW, "Execute: Instruction was squashed. PC: %s, [tid:%i]"
1152 " [sn:%llu]\n", inst->pcState(), inst->threadNumber,
1153 inst->seqNum);
1154
1155 // Consider this instruction executed so that commit can go
1156 // ahead and retire the instruction.
1157 inst->setExecuted();
1158
1159 // Not sure if I should set this here or just let commit try to
1160 // commit any squashed instructions. I like the latter a bit more.
1161 inst->setCanCommit();
1162
1163 ++iewStats.executedInstStats.numSquashedInsts;
1164
1165 continue;
1166 }
1167
1168 Fault fault = NoFault;
1169
1170 // Execute instruction.
1171 // Note that if the instruction faults, it will be handled
1172 // at the commit stage.
1173 if (inst->isMemRef()) {
1174 DPRINTF(IEW, "Execute: Calculating address for memory "
1175 "reference.\n");
1176
1177 // Tell the LDSTQ to execute this instruction (if it is a load).
1178 if (inst->isAtomic()) {
1179 // AMOs are treated like store requests
1180 fault = ldstQueue.executeStore(inst);
1181
1182 if (inst->isTranslationDelayed() &&
1183 fault == NoFault) {
1184 // A hw page table walk is currently going on; the
1185 // instruction must be deferred.
1186 DPRINTF(IEW, "Execute: Delayed translation, deferring "
1187 "store.\n");
1188 instQueue.deferMemInst(inst);
1189 continue;
1190 }
1191 } else if (inst->isLoad()) {
1192 // Loads will mark themselves as executed, and their writeback
1193 // event adds the instruction to the queue to commit
1194 fault = ldstQueue.executeLoad(inst);
1195
1196 if (inst->isTranslationDelayed() &&
1197 fault == NoFault) {
1198 // A hw page table walk is currently going on; the
1199 // instruction must be deferred.
1200 DPRINTF(IEW, "Execute: Delayed translation, deferring "
1201 "load.\n");
1202 instQueue.deferMemInst(inst);
1203 continue;
1204 }
1205
1206 if (inst->isDataPrefetch() || inst->isInstPrefetch()) {
1207 inst->fault = NoFault;
1208 }
1209 } else if (inst->isStore()) {
1210 fault = ldstQueue.executeStore(inst);
1211
1212 if (inst->isTranslationDelayed() &&
1213 fault == NoFault) {
1214 // A hw page table walk is currently going on; the
1215 // instruction must be deferred.
1216 DPRINTF(IEW, "Execute: Delayed translation, deferring "
1217 "store.\n");
1218 instQueue.deferMemInst(inst);
1219 continue;
1220 }
1221
1222 // If the store had a fault then it may not have a mem req
1223 if (fault != NoFault || !inst->readPredicate() ||
1224 !inst->isStoreConditional()) {
1225 // If the instruction faulted, then we need to send it
1226 // along to commit without the instruction completing.
1227 // Send this instruction to commit, also make sure iew
1228 // stage realizes there is activity.
1229 inst->setExecuted();
1230 instToCommit(inst);
1232 }
1233
1234 // Store conditionals will mark themselves as
1235 // executed, and their writeback event will add the
1236 // instruction to the queue to commit.
1237 } else {
1238 panic("Unexpected memory type!\n");
1239 }
1240
1241 } else {
1242 // If the instruction has already faulted, then skip executing it.
1243 // Such case can happen when it faulted during ITLB translation.
1244 // If we execute the instruction (even if it's a nop) the fault
1245 // will be replaced and we will lose it.
1246 if (inst->getFault() == NoFault) {
1247 inst->execute();
1248 if (!inst->readPredicate())
1249 inst->forwardOldRegs();
1250 }
1251
1252 inst->setExecuted();
1253
1254 instToCommit(inst);
1255 }
1256
1257 updateExeInstStats(inst);
1258
1259 // Check if branch prediction was correct, if not then we need
1260 // to tell commit to squash in flight instructions. Only
1261 // handle this if there hasn't already been something that
1262 // redirects fetch in this group of instructions.
1263
1264 // This probably needs to prioritize the redirects if a different
1265 // scheduler is used. Currently the scheduler schedules the oldest
1266 // instruction first, so the branch resolution order will be correct.
1267 ThreadID tid = inst->threadNumber;
1268
1269 if (!fetchRedirect[tid] ||
1270 !toCommit->squash[tid] ||
1271 toCommit->squashedSeqNum[tid] > inst->seqNum) {
1272
1273 // Prevent testing for misprediction on load instructions,
1274 // that have not been executed.
1275 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad();
1276
1277 if (inst->mispredicted() && !loadNotExecuted) {
1278 fetchRedirect[tid] = true;
1279
1280 DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: "
1281 "Branch mispredict detected.\n",
1282 tid, inst->seqNum);
1283 DPRINTF(IEW, "[tid:%i] [sn:%llu] "
1284 "Predicted target was PC: %s\n",
1285 tid, inst->seqNum, inst->readPredTarg());
1286 DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: "
1287 "Redirecting fetch to PC: %s\n",
1288 tid, inst->seqNum, inst->pcState());
1289 // If incorrect, then signal the ROB that it must be squashed.
1290 squashDueToBranch(inst, tid);
1291
1292 ppMispredict->notify(inst);
1293
1294 if (inst->readPredTaken()) {
1295 iewStats.predictedTakenIncorrect++;
1296 } else {
1297 iewStats.predictedNotTakenIncorrect++;
1298 }
1299 } else if (ldstQueue.violation(tid)) {
1300 assert(inst->isMemRef());
1301 // If there was an ordering violation, then get the
1302 // DynInst that caused the violation. Note that this
1303 // clears the violation signal.
1304 DynInstPtr violator;
1305 violator = ldstQueue.getMemDepViolator(tid);
1306
1307 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s "
1308 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n",
1309 violator->pcState(), violator->seqNum,
1310 inst->pcState(), inst->seqNum, inst->physEffAddr);
1311
1312 fetchRedirect[tid] = true;
1313
1314 // Tell the instruction queue that a violation has occured.
1315 instQueue.violation(inst, violator);
1316
1317 // Squash.
1318 squashDueToMemOrder(violator, tid);
1319
1320 ++iewStats.memOrderViolationEvents;
1321 }
1322 } else {
1323 // Reset any state associated with redirects that will not
1324 // be used.
1325 if (ldstQueue.violation(tid)) {
1326 assert(inst->isMemRef());
1327
1328 DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
1329
1330 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
1331 "%s, inst PC: %s. Addr is: %#x.\n",
1332 violator->pcState(), inst->pcState(),
1333 inst->physEffAddr);
1334 DPRINTF(IEW, "Violation will not be handled because "
1335 "already squashing\n");
1336
1337 ++iewStats.memOrderViolationEvents;
1338 }
1339 }
1340 }
1341
1342 // Update and record activity if we processed any instructions.
1343 if (inst_num) {
1344 if (exeStatus == Idle) {
1346 }
1347
1348 updatedQueues = true;
1349
1350 cpu->activityThisCycle();
1351 }
1352
1353 // Need to reset this in case a writeback event needs to write into the
1354 // iew queue. That way the writeback event will write into the correct
1355 // spot in the queue.
1356 wbNumInst = 0;
1357
1358}
1359
1360void
1362{
1363 // Loop through the head of the time buffer and wake any
1364 // dependents. These instructions are about to write back. Also
1365 // mark scoreboard that this instruction is finally complete.
1366 // Either have IEW have direct access to scoreboard, or have this
1367 // as part of backwards communication.
1368 for (int inst_num = 0; inst_num < wbWidth &&
1369 toCommit->insts[inst_num]; inst_num++) {
1370 DynInstPtr inst = toCommit->insts[inst_num];
1371 ThreadID tid = inst->threadNumber;
1372
1373 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n",
1374 inst->seqNum, inst->pcState());
1375
1376 iewStats.instsToCommit[tid]++;
1377 // Notify potential listeners that execution is complete for this
1378 // instruction.
1379 ppToCommit->notify(inst);
1380
1381 // Some instructions will be sent to commit without having
1382 // executed because they need commit to handle them.
1383 // E.g. Strictly ordered loads have not actually executed when they
1384 // are first sent to commit. Instead commit must tell the LSQ
1385 // when it's ready to execute the strictly ordered load.
1386 if (!inst->isSquashed() && inst->isExecuted() &&
1387 inst->getFault() == NoFault) {
1388 int dependents = instQueue.wakeDependents(inst);
1389
1390 for (int i = 0; i < inst->numDestRegs(); i++) {
1391 // Mark register as ready if not pinned
1392 if (inst->renamedDestIdx(i)->
1393 getNumPinnedWritesToComplete() == 0) {
1394 DPRINTF(IEW,"Setting Destination Register %i (%s)\n",
1395 inst->renamedDestIdx(i)->index(),
1396 inst->renamedDestIdx(i)->className());
1397 scoreboard->setReg(inst->renamedDestIdx(i));
1398 }
1399 }
1400
1401 if (dependents) {
1402 iewStats.producerInst[tid]++;
1403 iewStats.consumerInst[tid]+= dependents;
1404 }
1405 iewStats.writebackCount[tid]++;
1406 }
1407 }
1408}
1409
1410void
1412{
1413 wbNumInst = 0;
1414 wbCycle = 0;
1415
1416 wroteToTimeBuffer = false;
1417 updatedQueues = false;
1418
1419 ldstQueue.tick();
1420
1421 sortInsts();
1422
1423 // Free function units marked as being freed this cycle.
1424 fuPool->processFreeUnits();
1425
1426 // Check stall and squash signals, dispatch any instructions.
1427 for (ThreadID tid : *activeThreads) {
1428 DPRINTF(IEW,"Issue: Processing [tid:%i]\n", tid);
1429
1431 dispatch(tid);
1432 }
1433
1434 if (exeStatus != Squashing) {
1435 executeInsts();
1436
1438
1439 // Have the instruction queue try to schedule any ready instructions.
1440 // (In actuality, this scheduling is for instructions that will
1441 // be executed next cycle.)
1442 instQueue.scheduleReadyInsts();
1443
1444 // Also should advance its own time buffers if the stage ran.
1445 // Not the best place for it, but this works (hopefully).
1446 issueToExecQueue.advance();
1447 }
1448
1449 bool broadcast_free_entries = false;
1450
1452 exeStatus = Idle;
1453 updateLSQNextCycle = false;
1454
1455 broadcast_free_entries = true;
1456 }
1457
1458 // Writeback any stores using any leftover bandwidth.
1459 ldstQueue.writebackStores();
1460
1461 // Check the committed load/store signals to see if there's a load
1462 // or store to commit. Also check if it's being told to execute a
1463 // nonspeculative instruction.
1464 // This is pretty inefficient...
1465 for (ThreadID tid : *activeThreads) {
1466 DPRINTF(IEW,"Processing [tid:%i]\n", tid);
1467
1468 // Update structures based on instructions committed.
1469 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
1470 !fromCommit->commitInfo[tid].squash &&
1471 !fromCommit->commitInfo[tid].robSquashing) {
1472
1473 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
1474
1475 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
1476
1477 updateLSQNextCycle = true;
1478 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
1479 }
1480
1481 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
1482
1483 //DPRINTF(IEW,"NonspecInst from thread %i",tid);
1484 if (fromCommit->commitInfo[tid].strictlyOrdered) {
1485 instQueue.replayMemInst(
1486 fromCommit->commitInfo[tid].strictlyOrderedLoad);
1487 fromCommit->commitInfo[tid].strictlyOrderedLoad->setAtCommit();
1488 } else {
1489 instQueue.scheduleNonSpec(
1490 fromCommit->commitInfo[tid].nonSpecSeqNum);
1491 }
1492 }
1493
1494 if (broadcast_free_entries) {
1495 toFetch->iewInfo[tid].iqCount =
1496 instQueue.getCount(tid);
1497 toFetch->iewInfo[tid].ldstqCount =
1498 ldstQueue.getCount(tid);
1499
1500 toRename->iewInfo[tid].usedIQ = true;
1501 toRename->iewInfo[tid].freeIQEntries =
1502 instQueue.numFreeEntries(tid);
1503 toRename->iewInfo[tid].usedLSQ = true;
1504
1505 toRename->iewInfo[tid].freeLQEntries =
1506 ldstQueue.numFreeLoadEntries(tid);
1507 toRename->iewInfo[tid].freeSQEntries =
1508 ldstQueue.numFreeStoreEntries(tid);
1509
1510 wroteToTimeBuffer = true;
1511 }
1512
1513 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
1514 tid, toRename->iewInfo[tid].dispatched);
1515 }
1516
1517 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). "
1518 "LQ has %i free entries. SQ has %i free entries.\n",
1519 instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
1520 ldstQueue.numFreeLoadEntries(), ldstQueue.numFreeStoreEntries());
1521
1522 updateStatus();
1523
1524 if (wroteToTimeBuffer) {
1525 DPRINTF(Activity, "Activity this cycle.\n");
1526 cpu->activityThisCycle();
1527 }
1528}
1529
1530void
1532{
1533 ThreadID tid = inst->threadNumber;
1534
1535 cpu->executeStats[tid]->numInsts++;
1536
1537#if TRACING_ON
1538 if (debug::O3PipeView) {
1539 inst->completeTick = curTick() - inst->fetchTick;
1540 }
1541#endif
1542
1543 //
1544 // Control operations
1545 //
1546 if (inst->isControl()) {
1547 cpu->executeStats[tid]->numBranches++;
1548 }
1549
1550 //
1551 // Memory operations
1552 //
1553 if (inst->isMemRef()) {
1554 cpu->executeStats[tid]->numMemRefs++;
1555
1556 if (inst->isLoad()) {
1557 cpu->executeStats[tid]->numLoadInsts++;
1558 }
1559 }
1560}
1561
1562void
1564{
1565 ThreadID tid = inst->threadNumber;
1566
1567 if (!fetchRedirect[tid] ||
1568 !toCommit->squash[tid] ||
1569 toCommit->squashedSeqNum[tid] > inst->seqNum) {
1570
1571 if (inst->mispredicted()) {
1572 fetchRedirect[tid] = true;
1573
1574 DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: "
1575 "Branch mispredict detected.\n",
1576 tid, inst->seqNum);
1577 DPRINTF(IEW, "[tid:%i] [sn:%llu] Predicted target was PC: %s\n",
1578 tid, inst->seqNum, inst->readPredTarg());
1579 DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: "
1580 "Redirecting fetch to PC: %s\n",
1581 tid, inst->seqNum, inst->pcState());
1582 // If incorrect, then signal the ROB that it must be squashed.
1583 squashDueToBranch(inst, tid);
1584
1585 if (inst->readPredTaken()) {
1586 iewStats.predictedTakenIncorrect++;
1587 } else {
1588 iewStats.predictedNotTakenIncorrect++;
1589 }
1590 }
1591 }
1592}
1593
1594} // namespace o3
1595} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
ProbePointArg generates a point for the class of Arg.
Definition probe.hh:273
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition cpu.hh:94
void printAvailableInsts()
Debug function to print instructions that are issued this cycle.
Definition iew.cc:1097
void updateStatus()
Updates overall IEW status based on all of the stages' statuses.
Definition iew.cc:639
void deactivateStage()
Tells CPU that the IEW stage is inactive and idle.
Definition iew.cc:807
TimeBuffer< IEWStruct > * iewQueue
IEW stage time buffer.
Definition iew.hh:330
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's output from backwards time buffer.
Definition iew.hh:309
StageStatus dispatchStatus[MaxThreads]
Dispatch status.
Definition iew.hh:114
std::list< ThreadID > * activeThreads
Pointer to list of active threads.
Definition iew.hh:415
void takeOverFrom()
Takes over from another CPU's thread.
Definition iew.cc:383
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets main time buffer used for backwards communication.
Definition iew.cc:296
int skidCount()
Returns the max of the number of entries in all of the skid buffers.
Definition iew.cc:614
void instToCommit(const DynInstPtr &inst)
Sends an instruction to commit through the time buffer.
Definition iew.cc:565
FUPool * fuPool
Pointer to the functional unit pool.
Definition iew.hh:364
void squashDueToBranch(const DynInstPtr &inst, ThreadID tid)
Sends commit proper information for a squash due to a branch mispredict.
Definition iew.cc:445
void squashDueToMemOrder(const DynInstPtr &inst, ThreadID tid)
Sends commit proper information for a squash due to a memory order violation.
Definition iew.cc:469
unsigned wbWidth
Writeback width.
Definition iew.hh:409
std::queue< DynInstPtr > insts[MaxThreads]
Queue of all instructions coming from rename this cycle.
Definition iew.hh:336
void block(ThreadID tid)
Sets Dispatch to blocked, and signals back to other stages to block.
Definition iew.cc:495
StageStatus exeStatus
Execute status.
Definition iew.hh:116
void clearStates(ThreadID tid)
Clear all thread-specific states.
Definition iew.cc:254
void dispatch(ThreadID tid)
Determines proper actions to take given Dispatch's status.
Definition iew.cc:814
void startupStage()
Initializes stage; sends back the number of free IQ and LSQ entries.
Definition iew.cc:231
void blockMemInst(const DynInstPtr &inst)
Moves memory instruction onto the list of cache blocked instructions.
Definition iew.cc:547
void unblock(ThreadID tid)
Unblocks Dispatch if the skid buffer is empty, and signals back to other stages to unblock.
Definition iew.cc:513
void sortInsts()
Sorts instructions coming from rename into lists separated by thread.
Definition iew.cc:753
void wakeDependents(const DynInstPtr &inst)
Wakes all dependents of a completed instruction.
Definition iew.cc:529
unsigned issueWidth
Width of issue, in instructions.
Definition iew.hh:396
void updateExeInstStats(const DynInstPtr &inst)
Updates execution stats based on the instruction.
Definition iew.cc:1531
void dispatchInsts(ThreadID tid)
Dispatches instructions to IQ and LSQ.
Definition iew.cc:861
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition iew.cc:374
TimeBuffer< IssueStruct > issueToExecQueue
Issue stage queue.
Definition iew.hh:321
void checkSignalsAndUpdate(ThreadID tid)
Processes inputs and changes state accordingly.
Definition iew.cc:690
void activateStage()
Tells CPU that the IEW stage is active and running.
Definition iew.cc:800
TimeBuffer< TimeStruct >::wire toRename
Wire to write information heading to previous stages.
Definition iew.hh:312
bool wroteToTimeBuffer
Records if IEW has written to the time buffer this cycle, so that the CPU can deschedule itself if th...
Definition iew.hh:351
CPU * cpu
CPU pointer.
Definition iew.hh:346
void activityThisCycle()
Reports to the CPU that there is activity this cycle.
Definition iew.cc:793
void setScoreboard(Scoreboard *sb_ptr)
Sets pointer to the scoreboard.
Definition iew.cc:340
Scoreboard * scoreboard
Scoreboard pointer.
Definition iew.hh:342
std::queue< DynInstPtr > skidBuffer[MaxThreads]
Skid buffer between rename and IEW.
Definition iew.hh:339
TimeBuffer< IssueStruct >::wire fromIssue
Wire to read information from the issue stage time queue.
Definition iew.hh:324
Cycles renameToIEWDelay
Rename to IEW delay.
Definition iew.hh:383
TimeBuffer< TimeStruct > * timeBuffer
Pointer to main time buffer used for backwards communication.
Definition iew.hh:303
void writebackInsts()
Writebacks instructions.
Definition iew.cc:1361
void wakeCPU()
Tells the CPU to wakeup if it has descheduled itself due to no activity.
Definition iew.cc:787
void squash(ThreadID tid)
Squashes instructions in IEW for a specific thread.
Definition iew.cc:410
void setIEWQueue(TimeBuffer< IEWStruct > *iq_ptr)
Sets time buffer to pass on instructions to commit.
Definition iew.cc:322
ProbePointArg< DynInstPtr > * ppExecute
To probe when instruction execution begins.
Definition iew.hh:124
void rescheduleMemInst(const DynInstPtr &inst)
Tells memory dependence unit that a memory instruction needs to be rescheduled.
Definition iew.cc:535
ThreadID numThreads
Number of active threads.
Definition iew.hh:412
unsigned skidBufferMax
Maximum size of the skid buffer.
Definition iew.hh:418
Status _status
Overall stage status.
Definition iew.hh:112
TimeBuffer< RenameStruct >::wire fromRename
Wire to get rename's output from rename queue.
Definition iew.hh:318
ProbePointArg< DynInstPtr > * ppMispredict
Probe points.
Definition iew.hh:121
TimeBuffer< TimeStruct >::wire toFetch
Wire to write information heading to previous stages.
Definition iew.hh:306
gem5::o3::IEW::IEWStats iewStats
bool isDrained() const
Has the stage drained?
Definition iew.cc:346
InstructionQueue instQueue
Instruction queue.
Definition iew.hh:358
bool fetchRedirect[MaxThreads]
Records if there is a fetch redirect on this cycle for each thread.
Definition iew.hh:372
TimeBuffer< RenameStruct > * renameQueue
Rename instruction queue interface.
Definition iew.hh:315
IEW(CPU *_cpu, const BaseO3CPUParams &params)
Constructs a IEW with the given parameters.
Definition iew.cc:67
unsigned dispatchWidth
Width of dispatch, in instructions.
Definition iew.hh:393
ProbePointArg< DynInstPtr > * ppDispatch
Definition iew.hh:122
void retryMemInst(const DynInstPtr &inst)
Moves memory instruction onto the list of retry memory instructions.
Definition iew.cc:553
std::string name() const
Returns the name of the IEW stage.
Definition iew.cc:118
void tick()
Ticks IEW stage, causing Dispatch, the IQ, the LSQ, Execute, and Writeback to run for one cycle.
Definition iew.cc:1411
ProbePointArg< DynInstPtr > * ppToCommit
To probe when instruction execution is complete.
Definition iew.hh:126
bool updatedQueues
Records if the queues have been changed (inserted or issued insts), so that IEW knows to broadcast th...
Definition iew.hh:377
void checkMisprediction(const DynInstPtr &inst)
Check misprediction.
Definition iew.cc:1563
LSQ ldstQueue
Load / store queue.
Definition iew.hh:361
Cycles issueToExecuteDelay
Issue to execute delay.
Definition iew.hh:390
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
Definition iew.cc:331
bool skidsEmpty()
Returns if all of the skid buffers are empty.
Definition iew.cc:628
bool updateLSQNextCycle
Records if the LSQ needs to be updated on the next cycle, so that IEW knows if there will be activity...
Definition iew.hh:368
void emptyRenameInsts(ThreadID tid)
Removes instructions from rename from a thread's instruction list.
Definition iew.cc:766
void replayMemInst(const DynInstPtr &inst)
Re-executes all rescheduled memory instructions.
Definition iew.cc:541
Cycles commitToIEWDelay
Commit to IEW delay.
Definition iew.hh:380
unsigned wbCycle
Cycle number within the queue of instructions being written back.
Definition iew.hh:406
void skidInsert(ThreadID tid)
Inserts unused instructions of a thread into the skid buffer.
Definition iew.cc:593
void cacheUnblocked()
Notifies that the cache has become unblocked.
Definition iew.cc:559
TimeBuffer< IEWStruct >::wire toCommit
Wire to write infromation heading to commit.
Definition iew.hh:333
void regProbePoints()
Registers probes.
Definition iew.cc:124
bool checkStall(ThreadID tid)
Checks if any of the stall conditions are currently true.
Definition iew.cc:674
void executeInsts()
Executes instructions.
Definition iew.cc:1119
unsigned wbNumInst
Index into queue of instructions being written back.
Definition iew.hh:399
void setRenameQueue(TimeBuffer< RenameStruct > *rq_ptr)
Sets time buffer for getting instructions coming from rename.
Definition iew.cc:313
StageStatus wbStatus
Writeback status.
Definition iew.hh:118
Implements a simple scoreboard to track which registers are ready.
Definition scoreboard.hh:55
STL list class.
Definition stl.hh:51
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
static constexpr int MaxThreads
Definition limits.hh:38
void removeCommThreadInsts(ThreadID tid, CommStruct &comm_struct)
Remove instructions belonging to given thread from the given comm struct's instruction array.
Definition comm.hh:235
RefCountingPtr< DynInst > DynInstPtr
static constexpr int MaxWidth
Definition limits.hh:37
Units for Stats.
Definition units.hh:113
const FlagsType total
Print the total.
Definition info.hh:59
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
constexpr decltype(nullptr) NoFault
Definition types.hh:253
Struct that defines the information passed from IEW to commit.
Definition comm.hh:89
bool includeSquashInst[MaxThreads]
Definition comm.hh:101
bool branchTaken[MaxThreads]
Definition comm.hh:100
InstSeqNum squashedSeqNum[MaxThreads]
Definition comm.hh:95
std::unique_ptr< PCStateBase > pc[MaxThreads]
Definition comm.hh:96
bool branchMispredict[MaxThreads]
Definition comm.hh:99
Addr mispredPC[MaxThreads]
Definition comm.hh:94
DynInstPtr mispredictInst[MaxThreads]
Definition comm.hh:93
bool squash[MaxThreads]
Definition comm.hh:98
statistics::Vector numSwp
Number of executed software prefetches.
Definition iew.hh:465
statistics::Scalar numSquashedInsts
Stat for total number of squashed instructions skipped at execute.
Definition iew.hh:463
statistics::Scalar dispatchedInsts
Stat for total number of instructions dispatched.
Definition iew.hh:434
statistics::Formula wbFanout
Average number of woken instructions per writeback.
Definition iew.hh:479
statistics::Scalar squashCycles
Stat for total number of squashing cycles.
Definition iew.hh:428
statistics::Vector consumerInst
Number of instructions that wake up from producers.
Definition iew.hh:475
statistics::Scalar predictedNotTakenIncorrect
Stat for total number of incorrect predicted not taken branches.
Definition iew.hh:452
statistics::Scalar dispLoadInsts
Stat for total number of dispatched load instructions.
Definition iew.hh:438
statistics::Scalar dispNonSpecInsts
Stat for total number of dispatched non speculative insts.
Definition iew.hh:442
statistics::Scalar idleCycles
Stat for total number of idle cycles.
Definition iew.hh:426
statistics::Vector instsToCommit
Number of instructions sent to commit.
Definition iew.hh:469
gem5::o3::IEW::IEWStats::ExecutedInstStats executedInstStats
statistics::Formula wbRate
Number of instructions per cycle written back.
Definition iew.hh:477
statistics::Scalar dispSquashedInsts
Stat for total number of squashed instructions dispatch skips.
Definition iew.hh:436
statistics::Scalar predictedTakenIncorrect
Stat for total number of incorrect predicted taken branches.
Definition iew.hh:450
statistics::Scalar blockCycles
Stat for total number of blocking cycles.
Definition iew.hh:430
statistics::Vector writebackCount
Number of instructions that writeback.
Definition iew.hh:471
statistics::Scalar memOrderViolationEvents
Stat for total number of memory ordering violation events.
Definition iew.hh:448
statistics::Vector producerInst
Number of instructions that wake consumers.
Definition iew.hh:473
IEWStats(CPU *cpu)
Definition iew.cc:144
statistics::Scalar iqFullEvents
Stat for number of times the IQ becomes full.
Definition iew.hh:444
statistics::Scalar unblockCycles
Stat for total number of unblocking cycles.
Definition iew.hh:432
statistics::Scalar lsqFullEvents
Stat for number of times the LSQ becomes full.
Definition iew.hh:446
statistics::Formula branchMispredicts
Stat for total number of mispredicted branches detected at execute.
Definition iew.hh:455
statistics::Scalar dispStoreInsts
Stat for total number of dispatched store instructions.
Definition iew.hh:440
Struct that defines all backwards communication.
Definition comm.hh:113
bool iewBlock[MaxThreads]
Definition comm.hh:224
bool iewUnblock[MaxThreads]
Definition comm.hh:225
IewComm iewInfo[MaxThreads]
Definition comm.hh:152

Generated on Mon May 26 2025 09:19:08 for gem5 by doxygen 1.13.2