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)
70 fatal(
"decodeWidth (%d) is larger than compiled limit (%d),\n" 71 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
76 for (
int tid = 0; tid < Impl::MaxThreads; tid++) {
114 template <
class Impl>
118 return cpu->name() +
".decode";
121 template <
class Impl>
127 .
desc(
"Number of cycles decode is idle")
131 .
desc(
"Number of cycles decode is blocked")
135 .
desc(
"Number of cycles decode is running")
139 .
desc(
"Number of cycles decode is unblocking")
143 .
desc(
"Number of cycles decode is squashing")
147 .
desc(
"Number of times decode resolved a branch")
151 .
desc(
"Number of times decode detected a branch misprediction")
155 .
desc(
"Number of times decode detected an instruction incorrectly" 156 " predicted as a control")
160 .
desc(
"Number of instructions handled by decode")
164 .
desc(
"Number of squashed instructions handled by decode")
210 template <
class Impl>
215 assert(
insts[tid].empty());
220 template <
class Impl>
236 bool ret_val =
false;
239 DPRINTF(Decode,
"[tid:%i] Stall fom Rename stage detected.\n", tid);
257 DPRINTF(Decode,
"[tid:%i] Blocking.\n", tid);
270 if (
toFetch->decodeUnblock[tid]) {
271 toFetch->decodeUnblock[tid] =
false;
273 toFetch->decodeBlock[tid] =
true;
289 DPRINTF(Decode,
"[tid:%i] Done unblocking.\n", tid);
290 toFetch->decodeUnblock[tid] =
true;
297 DPRINTF(Decode,
"[tid:%i] Currently unblocking.\n", tid);
306 DPRINTF(Decode,
"[tid:%i] [sn:%llu] Squashing due to incorrect branch " 307 "prediction detected at decode.\n", tid, inst->seqNum);
310 toFetch->decodeInfo[tid].branchMispredict =
true;
311 toFetch->decodeInfo[tid].predIncorrect =
true;
312 toFetch->decodeInfo[tid].mispredictInst = inst;
313 toFetch->decodeInfo[tid].squash =
true;
314 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
315 toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
316 toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
317 toFetch->decodeInfo[tid].squashInst = inst;
318 if (
toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
319 toFetch->decodeInfo[tid].branchTaken =
true;
327 toFetch->decodeUnblock[tid] = 1;
334 if (
fromFetch->insts[
i]->threadNumber == tid &&
335 fromFetch->insts[
i]->seqNum > squash_seq_num) {
342 while (!
insts[tid].empty()) {
351 cpu->removeInstsUntil(squash_seq_num, tid);
358 DPRINTF(Decode,
"[tid:%i] Squashing.\n",tid);
363 toFetch->decodeUnblock[tid] = 1;
372 toFetch->decodeUnblock[tid] = 1;
380 unsigned squash_count = 0;
383 if (
fromFetch->insts[
i]->threadNumber == tid) {
391 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 skidBuffer %i\n",
418 inst->threadNumber, inst->seqNum, inst->pcState(),
skidBuffer[tid].size());
433 while (threads != end) {
446 bool any_unblocking =
false;
451 while (threads != end) {
455 any_unblocking =
true;
461 if (any_unblocking) {
465 DPRINTF(Activity,
"Activating stage.\n");
467 cpu->activateStage(O3CPU::DecodeIdx);
474 DPRINTF(Activity,
"Deactivating stage.\n");
476 cpu->deactivateStage(O3CPU::DecodeIdx);
481 template <
class Impl>
486 for (
int i = 0;
i < insts_from_fetch; ++
i) {
500 assert(
stalls[tid].rename);
505 template <
class Impl>
523 DPRINTF(Decode,
"[tid:%i] Squashing instructions due to squash " 524 "from commit.\n", tid);
536 DPRINTF(Decode,
"[tid:%i] Done blocking, switching to unblocking.\n",
549 DPRINTF(Decode,
"[tid:%i] Done squashing, switching to running.\n",
568 bool status_change =
false;
578 while (threads != end) {
581 DPRINTF(Decode,
"Processing [tid:%i]\n",tid);
584 decode(status_change, tid);
592 DPRINTF(Activity,
"Activity this cycle.\n");
594 cpu->activityThisCycle();
619 DPRINTF(Decode,
"[tid:%i] Not blocked, so attempting to run " 639 status_change =
unblock(tid) || status_change;
643 template <
class Impl>
652 if (insts_available == 0) {
653 DPRINTF(Decode,
"[tid:%i] Nothing to do, breaking out" 659 DPRINTF(Decode,
"[tid:%i] Unblocking, removing insts from skid " 666 std::queue<DynInstPtr>
670 DPRINTF(Decode,
"[tid:%i] Sending instruction to rename.\n",tid);
673 assert(!insts_to_decode.empty());
675 DynInstPtr inst = std::move(insts_to_decode.front());
677 insts_to_decode.pop();
679 DPRINTF(Decode,
"[tid:%i] Processing instruction [sn:%lli] with " 680 "PC %s\n", tid, inst->seqNum, inst->pcState());
682 if (inst->isSquashed()) {
683 DPRINTF(Decode,
"[tid:%i] Instruction %i with PC %s is " 684 "squashed, skipping.\n",
685 tid, inst->seqNum, inst->pcState());
698 if (inst->numSrcRegs() == 0) {
714 inst->decodeTick =
curTick() - inst->fetchTick;
720 if (inst->readPredTaken() && !inst->isControl()) {
721 panic(
"Instruction predicted as a branch!");
727 squash(inst, inst->threadNumber);
735 if (inst->isDirectCtrl() &&
736 (inst->isUncondCtrl() || inst->readPredTaken()))
740 if (!(inst->branchTarget() == inst->readPredTarg())) {
745 squash(inst, inst->threadNumber);
749 "[tid:%i] [sn:%llu] " 750 "Updating predictions: PredPC: %s\n",
751 tid, inst->seqNum, target);
753 inst->setPredTarg(target);
761 if (!insts_to_decode.empty()) {
772 #endif//__CPU_O3_DECODE_IMPL_HH__ #define panic(...)
This implements a cprintf based panic() function.
TimeBuffer< TimeStruct > * timeBuffer
Time buffer interface.
Cycles fetchToDecodeDelay
Fetch to decode delay.
void decode(bool &status_change, ThreadID tid)
Determines what to do based on decode's current status.
ThreadID numThreads
number of Active Threads
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.
bool wroteToTimeBuffer
Variable that tracks if decode has written to the time buffer this cycle.
void sortInsts()
Separates instructions from fetch into individual lists of instructions sorted by thread...
#define fatal(...)
This implements a cprintf based fatal() function.
DynInstPtr squashInst[Impl::MaxThreads]
Instruction used for squashing branch (used for MIPS)
Stalls stalls[Impl::MaxThreads]
Tracks which stages are telling decode to stall.
bool squashAfterDelaySlot[Impl::MaxThreads]
Tells when their is a pending delay slot inst.
Cycles iewToDecodeDelay
IEW to decode delay.
Stats::Scalar decodeBlockedCycles
Stat for total number of blocked cycles.
TimeBuffer< DecodeStruct >::wire toRename
Wire used to write any information heading to rename.
void tick()
Ticks decode, processing all input signals and decoding as many instructions as possible.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
DefaultDecode constructor.
bool isDrained() const
Has the stage drained?
bool skidsEmpty()
Returns if all of the skid buffers are empty.
void skidInsert(ThreadID tid)
Inserts a thread's instructions into the skid buffer, to be decoded once decode unblocks.
unsigned decodeWidth
The width of decode, in instructions.
TimeBuffer< TimeStruct >::wire fromIEW
Wire to get iew's information from backwards time buffer.
Stats::Scalar decodeUnblockCycles
Stat for total number of unblocking cycles.
void regStats()
Registers statistics.
ThreadStatus decodeStatus[Impl::MaxThreads]
Per-thread status.
unsigned skidBufferMax
Maximum size of the skid buffer.
TimeBuffer< TimeStruct >::wire fromRename
Wire to get rename's output from backwards time buffer.
Tick curTick()
The current simulated tick.
std::list< ThreadID > * activeThreads
List of active thread ids.
Stats::Scalar decodeSquashCycles
Stat for total number of squashing cycles.
void clearStates(ThreadID tid)
Clear all thread-specific states.
Stats::Scalar decodeControlMispred
Stat for number of times decode detected a non-control instruction incorrectly predicted as a branch...
void squash(const DynInstPtr &inst, ThreadID tid)
Squashes if there is a PC-relative branch that was predicted incorrectly.
Derived & prereq(const Stat &prereq)
Set the prerequisite stat and marks this stat to print at the end of simulation.
TimeBuffer< DecodeStruct > * decodeQueue
Decode instruction queue.
void drainSanityCheck() const
Perform sanity checks after a drain.
Addr bdelayDoneSeqNum[Impl::MaxThreads]
SeqNum of Squashing Branch Delay Instruction (used for MIPS)
Stats::Scalar decodeBranchResolved
Stat for number of times a branch is resolved at decode.
void readStallSignals(ThreadID tid)
Reads all stall signals from the backwards communication timebuffer.
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's information from backwards time buffer.
Impl::DynInstPtr DynInstPtr
Stats::Scalar decodeIdleCycles
Stat for total number of idle cycles.
O3CPU * cpu
CPU interface.
bool checkStall(ThreadID tid) const
Checks all stall signals, and returns if any are true.
static scfx_rep_node * list
Stats::Scalar decodeSquashedInsts
Stat for total number of squashed instructions.
bool block(ThreadID tid)
Switches decode to blocking, and signals back that decode has become blocked.
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
void decodeInsts(ThreadID tid)
Processes instructions from fetch and passes them on to rename.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
int16_t ThreadID
Thread index/ID type.
TimeBuffer< TimeStruct >::wire toFetch
Wire to write information heading to previous stages.
std::queue< DynInstPtr > insts[Impl::MaxThreads]
Queue of all instructions coming from fetch this cycle.
std::queue< DynInstPtr > skidBuffer[Impl::MaxThreads]
Skid buffer between fetch and decode.
Stats::Scalar decodeBranchMispred
Stat for number of times a branch mispredict is detected.
bool checkSignalsAndUpdate(ThreadID tid)
Checks all input signals and updates decode's status appropriately.
DecodeStatus _status
Decode status.
Cycles commitToDecodeDelay
Commit to decode delay.
Stats::Scalar decodeRunCycles
Stat for total number of normal running cycles.
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Sets pointer to time buffer coming from fetch.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
bool unblock(ThreadID tid)
Switches decode to unblocking if the skid buffer is empty, and signals back that decode has unblocked...
TimeBuffer< FetchStruct >::wire fromFetch
Wire to get fetch's output from fetch queue.
GenericISA::DelaySlotPCState< MachInst > PCState
Stats::Scalar decodeDecodedInsts
Stat for total number of decoded instructions.
void updateStatus()
Updates overall decode status based on all of the threads' statuses.
TimeBuffer< FetchStruct > * fetchQueue
Fetch instruction queue interface.
std::string name() const
Returns the name of decode.
Cycles renameToDecodeDelay
Rename to decode delay.
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main backwards communication time buffer pointer.
bool fetchInstsValid()
Returns if there any instructions from fetch on this cycle.