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

Generated on Fri Feb 28 2020 16:26:59 for gem5 by doxygen 1.8.13