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

Generated on Mon Oct 27 2025 04:13:00 for gem5 by doxygen 1.14.0