Go to the documentation of this file.
41 #ifndef __CPU_O3_DECODE_IMPL_HH__
42 #define __CPU_O3_DECODE_IMPL_HH__
44 #include "arch/types.hh"
46 #include "config/the_isa.hh"
49 #include "debug/Activity.hh"
50 #include "debug/Decode.hh"
51 #include "debug/O3PipeView.hh"
52 #include "params/DerivO3CPU.hh"
62 renameToDecodeDelay(params.renameToDecodeDelay),
63 iewToDecodeDelay(params.iewToDecodeDelay),
64 commitToDecodeDelay(params.commitToDecodeDelay),
65 fetchToDecodeDelay(params.fetchToDecodeDelay),
66 decodeWidth(params.decodeWidth),
67 numThreads(params.numThreads),
71 fatal(
"decodeWidth (%d) is larger than compiled limit (%d),\n"
72 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
77 for (
int tid = 0; tid < Impl::MaxThreads; tid++) {
97 decodeStatus[tid] = Idle;
98 stalls[tid].rename =
false;
108 for (
ThreadID tid = 0; tid < numThreads; ++tid) {
109 decodeStatus[tid] = Idle;
111 stalls[tid].rename =
false;
115 template <
class Impl>
119 return cpu->name() +
".decode";
122 template <
class Impl>
124 :
Stats::Group(cpu,
"decode"),
127 "Number of cycles decode is blocked"),
130 "Number of cycles decode is unblocking"),
132 "Number of cycles decode is squashing"),
134 "Number of times decode resolved a branch"),
136 "Number of times decode detected a branch misprediction"),
138 "Number of times decode detected an instruction incorrectly "
139 "predicted as a control"),
141 "Number of instructions handled by decode"),
143 "Number of squashed instructions handled by decode")
199 template <
class Impl>
204 assert(
insts[tid].empty());
209 template <
class Impl>
225 bool ret_val =
false;
228 DPRINTF(Decode,
"[tid:%i] Stall fom Rename stage detected.\n", tid);
246 DPRINTF(Decode,
"[tid:%i] Blocking.\n", tid);
259 if (
toFetch->decodeUnblock[tid]) {
260 toFetch->decodeUnblock[tid] =
false;
262 toFetch->decodeBlock[tid] =
true;
278 DPRINTF(Decode,
"[tid:%i] Done unblocking.\n", tid);
279 toFetch->decodeUnblock[tid] =
true;
286 DPRINTF(Decode,
"[tid:%i] Currently unblocking.\n", tid);
295 DPRINTF(Decode,
"[tid:%i] [sn:%llu] Squashing due to incorrect branch "
296 "prediction detected at decode.\n", tid, inst->seqNum);
299 toFetch->decodeInfo[tid].branchMispredict =
true;
300 toFetch->decodeInfo[tid].predIncorrect =
true;
301 toFetch->decodeInfo[tid].mispredictInst = inst;
302 toFetch->decodeInfo[tid].squash =
true;
303 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
304 toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
305 toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
306 toFetch->decodeInfo[tid].squashInst = inst;
307 if (
toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
308 toFetch->decodeInfo[tid].branchTaken =
true;
316 toFetch->decodeUnblock[tid] = 1;
323 if (
fromFetch->insts[
i]->threadNumber == tid &&
324 fromFetch->insts[
i]->seqNum > squash_seq_num) {
331 while (!
insts[tid].empty()) {
340 cpu->removeInstsUntil(squash_seq_num, tid);
347 DPRINTF(Decode,
"[tid:%i] Squashing.\n",tid);
352 toFetch->decodeUnblock[tid] = 1;
361 toFetch->decodeUnblock[tid] = 1;
369 unsigned squash_count = 0;
372 if (
fromFetch->insts[
i]->threadNumber == tid) {
380 while (!
insts[tid].empty()) {
397 while (!
insts[tid].empty()) {
398 inst =
insts[tid].front();
402 assert(tid == inst->threadNumber);
406 DPRINTF(Decode,
"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n",
407 inst->threadNumber, inst->seqNum, inst->pcState(),
skidBuffer[tid].size());
422 while (threads != end) {
435 bool any_unblocking =
false;
440 while (threads != end) {
444 any_unblocking =
true;
450 if (any_unblocking) {
454 DPRINTF(Activity,
"Activating stage.\n");
456 cpu->activateStage(O3CPU::DecodeIdx);
463 DPRINTF(Activity,
"Deactivating stage.\n");
465 cpu->deactivateStage(O3CPU::DecodeIdx);
470 template <
class Impl>
475 for (
int i = 0;
i < insts_from_fetch; ++
i) {
489 assert(
stalls[tid].rename);
494 template <
class Impl>
512 DPRINTF(Decode,
"[tid:%i] Squashing instructions due to squash "
513 "from commit.\n", tid);
525 DPRINTF(Decode,
"[tid:%i] Done blocking, switching to unblocking.\n",
538 DPRINTF(Decode,
"[tid:%i] Done squashing, switching to running.\n",
557 bool status_change =
false;
567 while (threads != end) {
570 DPRINTF(Decode,
"Processing [tid:%i]\n",tid);
573 decode(status_change, tid);
581 DPRINTF(Activity,
"Activity this cycle.\n");
583 cpu->activityThisCycle();
608 DPRINTF(Decode,
"[tid:%i] Not blocked, so attempting to run "
628 status_change =
unblock(tid) || status_change;
632 template <
class Impl>
641 if (insts_available == 0) {
642 DPRINTF(Decode,
"[tid:%i] Nothing to do, breaking out"
648 DPRINTF(Decode,
"[tid:%i] Unblocking, removing insts from skid "
655 std::queue<DynInstPtr>
659 DPRINTF(Decode,
"[tid:%i] Sending instruction to rename.\n",tid);
662 assert(!insts_to_decode.empty());
664 DynInstPtr inst = std::move(insts_to_decode.front());
666 insts_to_decode.pop();
668 DPRINTF(Decode,
"[tid:%i] Processing instruction [sn:%lli] with "
669 "PC %s\n", tid, inst->seqNum, inst->pcState());
671 if (inst->isSquashed()) {
672 DPRINTF(Decode,
"[tid:%i] Instruction %i with PC %s is "
673 "squashed, skipping.\n",
674 tid, inst->seqNum, inst->pcState());
687 if (inst->numSrcRegs() == 0) {
703 inst->decodeTick =
curTick() - inst->fetchTick;
709 if (inst->readPredTaken() && !inst->isControl()) {
710 panic(
"Instruction predicted as a branch!");
716 squash(inst, inst->threadNumber);
724 if (inst->isDirectCtrl() &&
725 (inst->isUncondCtrl() || inst->readPredTaken()))
729 if (!(inst->branchTarget() == inst->readPredTarg())) {
734 squash(inst, inst->threadNumber);
738 "[tid:%i] [sn:%llu] "
739 "Updating predictions: Wrong predicted target: %s \
741 tid, inst->seqNum, inst->readPredTarg(), target);
743 inst->setPredTarg(target);
751 if (!insts_to_decode.empty()) {
762 #endif//__CPU_O3_DECODE_IMPL_HH__
void squash(const DynInstPtr &inst, ThreadID tid)
Squashes if there is a PC-relative branch that was predicted incorrectly.
Stats::Scalar squashCycles
Stat for total number of squashing cycles.
#define fatal(...)
This implements a cprintf based fatal() function.
Addr bdelayDoneSeqNum[Impl::MaxThreads]
SeqNum of Squashing Branch Delay Instruction (used for MIPS)
TimeBuffer< TimeStruct > * timeBuffer
Time buffer interface.
DefaultDecode(O3CPU *_cpu, const DerivO3CPUParams ¶ms)
DefaultDecode constructor.
Cycles renameToDecodeDelay
Rename to decode delay.
bool checkStall(ThreadID tid) const
Checks all stall signals, and returns if any are true.
Stats::Scalar decodedInsts
Stat for total number of decoded instructions.
bool checkSignalsAndUpdate(ThreadID tid)
Checks all input signals and updates decode's status appropriately.
int16_t ThreadID
Thread index/ID type.
std::queue< DynInstPtr > insts[Impl::MaxThreads]
Queue of all instructions coming from fetch this cycle.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
static scfx_rep_node * list
ThreadStatus decodeStatus[Impl::MaxThreads]
Per-thread status.
Stats::Scalar runCycles
Stat for total number of normal running cycles.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Cycles iewToDecodeDelay
IEW to decode delay.
bool squashAfterDelaySlot[Impl::MaxThreads]
Tells when their is a pending delay slot inst.
TimeBuffer< TimeStruct >::wire fromRename
Wire to get rename's output from backwards time buffer.
Impl::DynInstPtr DynInstPtr
std::string name() const
Returns the name of decode.
void drainSanityCheck() const
Perform sanity checks after a drain.
unsigned toRenameIndex
Index of instructions being sent to rename.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main backwards communication time buffer pointer.
Stats::Scalar unblockCycles
Stat for total number of unblocking cycles.
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's information from backwards time buffer.
void skidInsert(ThreadID tid)
Inserts a thread's instructions into the skid buffer, to be decoded once decode unblocks.
bool block(ThreadID tid)
Switches decode to blocking, and signals back that decode has become blocked.
Derived & prereq(const Stat &prereq)
Set the prerequisite stat and marks this stat to print at the end of simulation.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Stats::Scalar blockedCycles
Stat for total number of blocked cycles.
Stats::Scalar controlMispred
Stat for number of times decode detected a non-control instruction incorrectly predicted as a branch.
std::list< ThreadID > * activeThreads
List of active thread ids.
std::queue< DynInstPtr > skidBuffer[Impl::MaxThreads]
Skid buffer between fetch and decode.
Stats::Scalar idleCycles
Stat for total number of idle cycles.
TimeBuffer< TimeStruct >::wire toFetch
Wire to write information heading to previous stages.
Stats::Scalar branchMispred
Stat for number of times a branch mispredict is detected.
O3CPU * cpu
CPU interface.
Stalls stalls[Impl::MaxThreads]
Tracks which stages are telling decode to stall.
DecodeStatus _status
Decode status.
TimeBuffer< FetchStruct >::wire fromFetch
Wire to get fetch's output from fetch queue.
bool fetchInstsValid()
Returns if there any instructions from fetch on this cycle.
void clearStates(ThreadID tid)
Clear all thread-specific states.
TimeBuffer< DecodeStruct >::wire toRename
Wire used to write any information heading to rename.
void updateStatus()
Updates overall decode status based on all of the threads' statuses.
void sortInsts()
Separates instructions from fetch into individual lists of instructions sorted by thread.
void decodeInsts(ThreadID tid)
Processes instructions from fetch and passes them on to rename.
void tick()
Ticks decode, processing all input signals and decoding as many instructions as possible.
Stats::Scalar squashedInsts
Stat for total number of squashed instructions.
unsigned decodeWidth
The width of decode, in instructions.
DefaultDecode::DecodeStats stats
bool skidsEmpty()
Returns if all of the skid buffers are empty.
GenericISA::DelaySlotPCState< MachInst > PCState
TimeBuffer< DecodeStruct > * decodeQueue
Decode instruction queue.
bool wroteToTimeBuffer
Variable that tracks if decode has written to the time buffer this cycle.
TimeBuffer< FetchStruct > * fetchQueue
Fetch instruction queue interface.
DynInstPtr squashInst[Impl::MaxThreads]
Instruction used for squashing branch (used for MIPS)
#define UNIT_CYCLE
Convenience macros to declare the unit of a stat.
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Sets pointer to time buffer coming from fetch.
void setDecodeQueue(TimeBuffer< DecodeStruct > *dq_ptr)
Sets pointer to time buffer used to communicate to the next stage.
Tick curTick()
The universal simulation clock.
bool isDrained() const
Has the stage drained?
Stats::Scalar branchResolved
Stat for number of times a branch is resolved at decode.
void decode(bool &status_change, ThreadID tid)
Determines what to do based on decode's current status.
ThreadID numThreads
number of Active Threads
bool unblock(ThreadID tid)
Switches decode to unblocking if the skid buffer is empty, and signals back that decode has unblocked...
unsigned skidBufferMax
Maximum size of the skid buffer.
Cycles commitToDecodeDelay
Commit to decode delay.
TimeBuffer< TimeStruct >::wire fromIEW
Wire to get iew's information from backwards time buffer.
#define panic(...)
This implements a cprintf based panic() function.
Cycles fetchToDecodeDelay
Fetch to decode delay.
void readStallSignals(ThreadID tid)
Reads all stall signals from the backwards communication timebuffer.
Generated on Tue Jun 22 2021 15:28:26 for gem5 by doxygen 1.8.17