48#include "debug/Activity.hh"
49#include "debug/Decode.hh"
50#include "debug/O3PipeView.hh"
51#include "params/BaseO3CPU.hh"
75 fatal(
"decodeWidth (%d) is larger than compiled limit (%d),\n"
76 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
100 stalls[tid].rename =
false;
103 for (
int i = -
cpu->decodeQueue.getPast();
110 for (
int i = -
cpu->timeBuffer.getPast();
128 stalls[tid].rename =
false;
135 return cpu->name() +
".decode";
141 "Number of cycles decode is idle"),
143 "Number of cycles decode is blocked"),
145 "Number of cycles decode is running"),
147 "Number of cycles decode is unblocking"),
149 "Number of cycles decode is squashing"),
151 "Number of times decode resolved a branch"),
153 "Number of times decode detected a branch misprediction"),
155 "Number of times decode detected an instruction incorrectly "
156 "predicted as a control"),
158 "Number of instructions handled by decode"),
160 "Number of squashed instructions handled by decode")
216 assert(
insts[tid].empty());
235 bool ret_val =
false;
238 DPRINTF(
Decode,
"[tid:%i] Stall fom Rename stage detected.\n", tid);
267 if (
toFetch->decodeUnblock[tid]) {
268 toFetch->decodeUnblock[tid] =
false;
270 toFetch->decodeBlock[tid] =
true;
286 toFetch->decodeUnblock[tid] =
true;
301 DPRINTF(
Decode,
"[tid:%i] [sn:%llu] Squashing due to incorrect branch "
302 "prediction detected at decode.\n", tid, inst->seqNum);
305 toFetch->decodeInfo[tid].branchMispredict =
true;
306 toFetch->decodeInfo[tid].predIncorrect =
true;
307 toFetch->decodeInfo[tid].mispredictInst = inst;
308 toFetch->decodeInfo[tid].squash =
true;
309 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
310 set(
toFetch->decodeInfo[tid].nextPC, *inst->branchTarget());
319 toFetch->decodeInfo[tid].branchTaken = inst->readPredTaken() ||
320 inst->isUncondCtrl();
322 toFetch->decodeInfo[tid].squashInst = inst;
329 toFetch->decodeUnblock[tid] = 1;
336 if (
fromFetch->insts[
i]->threadNumber == tid &&
337 fromFetch->insts[
i]->seqNum > squash_seq_num) {
344 while (!
insts[tid].empty()) {
353 cpu->removeInstsUntil(squash_seq_num, tid);
364 toFetch->decodeUnblock[tid] = 1;
373 toFetch->decodeUnblock[tid] = 1;
381 unsigned squash_count = 0;
384 if (
fromFetch->insts[
i]->threadNumber == tid) {
392 while (!
insts[tid].empty()) {
408 while (!
insts[tid].empty()) {
409 inst =
insts[tid].front();
413 assert(tid == inst->threadNumber);
417 DPRINTF(
Decode,
"Inserting [tid:%d][sn:%lli] PC: %s into decode "
418 "skidBuffer %i\n", inst->threadNumber, inst->seqNum,
441 bool any_unblocking =
false;
445 any_unblocking =
true;
451 if (any_unblocking) {
455 DPRINTF(Activity,
"Activating stage.\n");
464 DPRINTF(Activity,
"Deactivating stage.\n");
475 for (
int i = 0;
i < insts_from_fetch; ++
i) {
484 stalls[tid].rename =
true;
488 assert(
stalls[tid].rename);
489 stalls[tid].rename =
false;
510 DPRINTF(
Decode,
"[tid:%i] Squashing instructions due to squash "
511 "from commit.\n", tid);
523 DPRINTF(
Decode,
"[tid:%i] Done blocking, switching to unblocking.\n",
536 DPRINTF(
Decode,
"[tid:%i] Done squashing, switching to running.\n",
554 bool status_change =
false;
565 decode(status_change, tid);
573 DPRINTF(Activity,
"Activity this cycle.\n");
575 cpu->activityThisCycle();
590 ++
stats.blockedCycles;
592 ++
stats.squashCycles;
599 DPRINTF(
Decode,
"[tid:%i] Not blocked, so attempting to run "
619 status_change =
unblock(tid) || status_change;
631 if (insts_available == 0) {
638 DPRINTF(
Decode,
"[tid:%i] Unblocking, removing insts from skid "
640 ++
stats.unblockCycles;
645 std::queue<DynInstPtr>
649 DPRINTF(
Decode,
"[tid:%i] Sending instruction to rename.\n",tid);
652 assert(!insts_to_decode.empty());
654 DynInstPtr inst = std::move(insts_to_decode.front());
656 insts_to_decode.pop();
658 DPRINTF(
Decode,
"[tid:%i] Processing instruction [sn:%lli] with "
659 "PC %s\n", tid, inst->seqNum, inst->pcState());
661 if (inst->isSquashed()) {
663 "squashed, skipping.\n",
664 tid, inst->seqNum, inst->pcState());
666 ++
stats.squashedInsts;
677 if (inst->numSrcRegs() == 0) {
688 ++
stats.decodedInsts;
692 if (debug::O3PipeView) {
693 inst->decodeTick =
curTick() - inst->fetchTick;
699 if (inst->readPredTaken() && !inst->isControl()) {
700 panic(
"Instruction predicted as a branch!");
702 ++
stats.controlMispred;
706 squash(inst, inst->threadNumber);
714 if (inst->isDirectCtrl() &&
715 (inst->isUncondCtrl() || inst->readPredTaken()))
717 ++
stats.branchResolved;
719 std::unique_ptr<PCStateBase> target = inst->branchTarget();
720 if (*target != inst->readPredTarg()) {
721 ++
stats.branchMispred;
725 squash(inst, inst->threadNumber);
728 "[tid:%i] [sn:%llu] "
729 "Updating predictions: Wrong predicted target: %s \
731 tid, inst->seqNum, inst->readPredTarg(), *target);
733 inst->setPredTarg(*target);
741 if (!insts_to_decode.empty()) {
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
DecodeStatus _status
Decode status.
std::queue< DynInstPtr > skidBuffer[MaxThreads]
Skid buffer between fetch and decode.
bool wroteToTimeBuffer
Variable that tracks if decode has written to the time buffer this cycle.
bool unblock(ThreadID tid)
Switches decode to unblocking if the skid buffer is empty, and signals back that decode has unblocked...
bool squashAfterDelaySlot[MaxThreads]
Tells when their is a pending delay slot inst.
void readStallSignals(ThreadID tid)
Reads all stall signals from the backwards communication timebuffer.
gem5::o3::Decode::DecodeStats stats
DynInstPtr squashInst[MaxThreads]
Instruction used for squashing branch (used for MIPS)
Cycles iewToDecodeDelay
IEW to decode delay.
void decodeInsts(ThreadID tid)
Processes instructions from fetch and passes them on to rename.
Stalls stalls[MaxThreads]
Tracks which stages are telling decode to stall.
TimeBuffer< TimeStruct >::wire toFetch
Wire to write information heading to previous stages.
unsigned skidBufferMax
Maximum size of the skid buffer.
Cycles commitToDecodeDelay
Commit to decode delay.
void decode(bool &status_change, ThreadID tid)
Determines what to do based on decode's current status.
bool fetchInstsValid()
Returns if there any instructions from fetch on this cycle.
bool checkSignalsAndUpdate(ThreadID tid)
Checks all input signals and updates decode's status appropriately.
TimeBuffer< DecodeStruct >::wire toRename
Wire used to write any information heading to rename.
Cycles renameToDecodeDelay
Rename to decode delay.
Cycles fetchToDecodeDelay
Fetch to decode delay.
std::queue< DynInstPtr > insts[MaxThreads]
Queue of all instructions coming from fetch this cycle.
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Sets pointer to time buffer coming from fetch.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main backwards communication time buffer pointer.
ThreadStatus decodeStatus[MaxThreads]
Per-thread status.
void sortInsts()
Separates instructions from fetch into individual lists of instructions sorted by thread.
unsigned toRenameIndex
Index of instructions being sent to rename.
void setDecodeQueue(TimeBuffer< DecodeStruct > *dq_ptr)
Sets pointer to time buffer used to communicate to the next stage.
TimeBuffer< DecodeStruct > * decodeQueue
Decode instruction queue.
void squash(const DynInstPtr &inst, ThreadID tid)
Squashes if there is a PC-relative branch that was predicted incorrectly.
void updateStatus()
Updates overall decode status based on all of the threads' statuses.
bool skidsEmpty()
Returns if all of the skid buffers are empty.
unsigned decodeWidth
The width of decode, in instructions.
bool isDrained() const
Has the stage drained?
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's information from backwards time buffer.
ThreadID numThreads
number of Active Threads
TimeBuffer< TimeStruct > * timeBuffer
Time buffer interface.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
TimeBuffer< FetchStruct >::wire fromFetch
Wire to get fetch's output from fetch queue.
TimeBuffer< TimeStruct >::wire fromRename
Wire to get rename's output from backwards time buffer.
Addr bdelayDoneSeqNum[MaxThreads]
SeqNum of Squashing Branch Delay Instruction (used for MIPS)
TimeBuffer< TimeStruct >::wire fromIEW
Wire to get iew's information from backwards time buffer.
void clearStates(ThreadID tid)
Clear all thread-specific states.
void drainSanityCheck() const
Perform sanity checks after a drain.
std::list< ThreadID > * activeThreads
List of active thread ids.
void tick()
Ticks decode, processing all input signals and decoding as many instructions as possible.
Decode(CPU *_cpu, const BaseO3CPUParams ¶ms)
Decode constructor.
bool block(ThreadID tid)
Switches decode to blocking, and signals back that decode has become blocked.
std::string name() const
Returns the name of decode.
void skidInsert(ThreadID tid)
Inserts a thread's instructions into the skid buffer, to be decoded once decode unblocks.
TimeBuffer< FetchStruct > * fetchQueue
Fetch instruction queue interface.
bool checkStall(ThreadID tid) const
Checks all stall signals, and returns if any are true.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
static constexpr int MaxThreads
void removeCommThreadInsts(ThreadID tid, CommStruct &comm_struct)
Remove instructions belonging to given thread from the given comm struct's instruction array.
RefCountingPtr< DynInst > DynInstPtr
static constexpr int MaxWidth
Copyright (c) 2024 Arm Limited All rights reserved.
int16_t ThreadID
Thread index/ID type.
Tick curTick()
The universal simulation clock.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Struct that defines the information passed from decode to rename.
statistics::Scalar branchResolved
Stat for number of times a branch is resolved at decode.
statistics::Scalar squashCycles
Stat for total number of squashing cycles.
statistics::Scalar runCycles
Stat for total number of normal running cycles.
statistics::Scalar squashedInsts
Stat for total number of squashed instructions.
statistics::Scalar idleCycles
Stat for total number of idle cycles.
statistics::Scalar branchMispred
Stat for number of times a branch mispredict is detected.
statistics::Scalar decodedInsts
Stat for total number of decoded instructions.
statistics::Scalar blockedCycles
Stat for total number of blocked cycles.
statistics::Scalar controlMispred
Stat for number of times decode detected a non-control instruction incorrectly predicted as a branch.
statistics::Scalar unblockCycles
Stat for total number of unblocking cycles.
Struct that defines all backwards communication.
bool decodeBlock[MaxThreads]
DecodeComm decodeInfo[MaxThreads]
bool decodeUnblock[MaxThreads]