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

Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17