43 #ifndef __CPU_O3_DECODE_IMPL_HH__ 44 #define __CPU_O3_DECODE_IMPL_HH__ 46 #include "arch/types.hh" 48 #include "config/the_isa.hh" 51 #include "debug/Activity.hh" 52 #include "debug/Decode.hh" 53 #include "debug/O3PipeView.hh" 54 #include "params/DerivO3CPU.hh" 64 renameToDecodeDelay(params->renameToDecodeDelay),
65 iewToDecodeDelay(params->iewToDecodeDelay),
66 commitToDecodeDelay(params->commitToDecodeDelay),
67 fetchToDecodeDelay(params->fetchToDecodeDelay),
68 decodeWidth(params->decodeWidth),
69 numThreads(params->numThreads)
72 fatal(
"decodeWidth (%d) is larger than compiled limit (%d),\n" 73 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
78 for (
int tid = 0; tid < Impl::MaxThreads; tid++) {
116 template <
class Impl>
120 return cpu->name() +
".decode";
123 template <
class Impl>
129 .
desc(
"Number of cycles decode is idle")
133 .
desc(
"Number of cycles decode is blocked")
137 .
desc(
"Number of cycles decode is running")
141 .
desc(
"Number of cycles decode is unblocking")
145 .
desc(
"Number of cycles decode is squashing")
149 .
desc(
"Number of times decode resolved a branch")
153 .
desc(
"Number of times decode detected a branch misprediction")
157 .
desc(
"Number of times decode detected an instruction incorrectly" 158 " predicted as a control")
162 .
desc(
"Number of instructions handled by decode")
166 .
desc(
"Number of squashed instructions handled by decode")
212 template <
class Impl>
217 assert(
insts[tid].empty());
222 template <
class Impl>
238 bool ret_val =
false;
241 DPRINTF(Decode,
"[tid:%i] Stall fom Rename stage detected.\n", tid);
259 DPRINTF(Decode,
"[tid:%i] Blocking.\n", tid);
272 if (
toFetch->decodeUnblock[tid]) {
273 toFetch->decodeUnblock[tid] =
false;
275 toFetch->decodeBlock[tid] =
true;
291 DPRINTF(Decode,
"[tid:%i] Done unblocking.\n", tid);
292 toFetch->decodeUnblock[tid] =
true;
299 DPRINTF(Decode,
"[tid:%i] Currently unblocking.\n", tid);
308 DPRINTF(Decode,
"[tid:%i] [sn:%llu] Squashing due to incorrect branch " 309 "prediction detected at decode.\n", tid, inst->seqNum);
312 toFetch->decodeInfo[tid].branchMispredict =
true;
313 toFetch->decodeInfo[tid].predIncorrect =
true;
314 toFetch->decodeInfo[tid].mispredictInst = inst;
315 toFetch->decodeInfo[tid].squash =
true;
316 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
317 toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
318 toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
319 toFetch->decodeInfo[tid].squashInst = inst;
320 if (
toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
321 toFetch->decodeInfo[tid].branchTaken =
true;
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);
360 DPRINTF(Decode,
"[tid:%i] Squashing.\n",tid);
365 toFetch->decodeUnblock[tid] = 1;
374 toFetch->decodeUnblock[tid] = 1;
382 unsigned squash_count = 0;
385 if (
fromFetch->insts[
i]->threadNumber == tid) {
393 while (!
insts[tid].empty()) {
410 while (!
insts[tid].empty()) {
411 inst =
insts[tid].front();
415 assert(tid == inst->threadNumber);
419 DPRINTF(Decode,
"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n",
420 inst->threadNumber, inst->seqNum, inst->pcState(),
skidBuffer[tid].size());
435 while (threads != end) {
448 bool any_unblocking =
false;
453 while (threads != end) {
457 any_unblocking =
true;
463 if (any_unblocking) {
467 DPRINTF(Activity,
"Activating stage.\n");
469 cpu->activateStage(O3CPU::DecodeIdx);
476 DPRINTF(Activity,
"Deactivating stage.\n");
478 cpu->deactivateStage(O3CPU::DecodeIdx);
483 template <
class Impl>
488 for (
int i = 0;
i < insts_from_fetch; ++
i) {
502 assert(
stalls[tid].rename);
507 template <
class Impl>
525 DPRINTF(Decode,
"[tid:%i] Squashing instructions due to squash " 526 "from commit.\n", tid);
538 DPRINTF(Decode,
"[tid:%i] Done blocking, switching to unblocking.\n",
551 DPRINTF(Decode,
"[tid:%i] Done squashing, switching to running.\n",
570 bool status_change =
false;
580 while (threads != end) {
583 DPRINTF(Decode,
"Processing [tid:%i]\n",tid);
586 decode(status_change, tid);
594 DPRINTF(Activity,
"Activity this cycle.\n");
596 cpu->activityThisCycle();
621 DPRINTF(Decode,
"[tid:%i] Not blocked, so attempting to run " 641 status_change =
unblock(tid) || status_change;
645 template <
class Impl>
654 if (insts_available == 0) {
655 DPRINTF(Decode,
"[tid:%i] Nothing to do, breaking out" 661 DPRINTF(Decode,
"[tid:%i] Unblocking, removing insts from skid " 668 std::queue<DynInstPtr>
672 DPRINTF(Decode,
"[tid:%i] Sending instruction to rename.\n",tid);
675 assert(!insts_to_decode.empty());
677 DynInstPtr inst = std::move(insts_to_decode.front());
679 insts_to_decode.pop();
681 DPRINTF(Decode,
"[tid:%i] Processing instruction [sn:%lli] with " 682 "PC %s\n", tid, inst->seqNum, inst->pcState());
684 if (inst->isSquashed()) {
685 DPRINTF(Decode,
"[tid:%i] Instruction %i with PC %s is " 686 "squashed, skipping.\n",
687 tid, inst->seqNum, inst->pcState());
700 if (inst->numSrcRegs() == 0) {
716 inst->decodeTick =
curTick() - inst->fetchTick;
722 if (inst->readPredTaken() && !inst->isControl()) {
723 panic(
"Instruction predicted as a branch!");
729 squash(inst, inst->threadNumber);
737 if (inst->isDirectCtrl() &&
738 (inst->isUncondCtrl() || inst->readPredTaken()))
742 if (!(inst->branchTarget() == inst->readPredTarg())) {
747 squash(inst, inst->threadNumber);
751 "[tid:%i] [sn:%llu] " 752 "Updating predictions: PredPC: %s\n",
753 tid, inst->seqNum, target);
755 inst->setPredTarg(target);
763 if (!insts_to_decode.empty()) {
774 #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.
GenericISA::SimplePCState< MachInst > PCState
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.
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.