gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
decode.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, 2014, 2025 Arm Limited
3 * Copyright (c) 2022-2023 The University of Edinburgh
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#include "cpu/o3/decode.hh"
43
45#include "base/trace.hh"
46#include "cpu/inst_seq.hh"
47#include "cpu/o3/dyn_inst.hh"
48#include "cpu/o3/limits.hh"
49#include "debug/Activity.hh"
50#include "debug/Decode.hh"
51#include "params/BaseO3CPU.hh"
52#include "sim/full_system.hh"
53
54// clang complains about std::set being overloaded with Packet::set if
55// we open up the entire namespace std
56using std::list;
57
58namespace gem5
59{
60
61namespace o3
62{
63
64// clang-format off
65std::string Decode::DecodeStats::statusStrings[ThreadStatusMax] = {
66 "Running",
67 "Idle",
68 "StartSquash",
69 "Squashing",
70 "Blocked",
71 "Unblocking",
72};
73
74std::string Decode::DecodeStats::statusDefinitions[ThreadStatusMax] = {
75 "Number of cycles decode is running",
76 "Number of cycles decode is idle",
77 "Not Used",
78 "Number of cycles decode is squashing",
79 "Number of cycles decode is blocking",
80 "Number of cycles decode is unblocking",
81};
82// clang-format on
83
84Decode::Decode(CPU *_cpu, const BaseO3CPUParams &params)
85 : cpu(_cpu),
91 numThreads(params.numThreads),
92 stats(_cpu)
93{
95 fatal("decodeWidth (%d) is larger than compiled limit (%d),\n"
96 "\tincrease MaxWidth in src/cpu/o3/limits.hh\n",
97 decodeWidth, static_cast<int>(MaxWidth));
98
99 // @todo: Make into a parameter
100 skidBufferMax = (fetchToDecodeDelay + 1) * params.decodeWidth;
101 for (int tid = 0; tid < MaxThreads; tid++) {
102 stalls[tid] = {false};
103 decodeStatus[tid] = Idle;
104 bdelayDoneSeqNum[tid] = 0;
105 squashInst[tid] = nullptr;
106 squashAfterDelaySlot[tid] = 0;
107 }
108}
109
110void
115
116void
118{
119 decodeStatus[tid] = Idle;
120 stalls[tid].rename = false;
121
122 // Clear out any of this thread's instructions being sent to rename.
123 for (int i = -cpu->decodeQueue.getPast();
124 i <= cpu->decodeQueue.getFuture(); ++i) {
125 DecodeStruct& decode_struct = cpu->decodeQueue[i];
126 removeCommThreadInsts(tid, decode_struct);
127 }
128
129 // Clear out any of this thread's instructions being sent to fetch.
130 for (int i = -cpu->timeBuffer.getPast();
131 i <= cpu->timeBuffer.getFuture(); ++i) {
132 TimeStruct& time_struct = cpu->timeBuffer[i];
133 time_struct.decodeInfo[tid] = {};
134 time_struct.decodeBlock[tid] = false;
135 time_struct.decodeUnblock[tid] = false;
136 }
137}
138
139void
141{
143
144 // Setup status, make sure stall signals are clear.
145 for (ThreadID tid = 0; tid < numThreads; ++tid) {
146 decodeStatus[tid] = Idle;
147
148 stalls[tid].rename = false;
149 }
150}
151
152std::string
154{
155 return cpu->name() + ".decode";
156}
157
159 : statistics::Group(cpu, "decode"),
160 ADD_STAT(status, statistics::units::Cycle::get(),
161 "Number of cycles decode is idle"),
162 ADD_STAT(branchResolved, statistics::units::Count::get(),
163 "Number of times decode resolved a branch"),
164 ADD_STAT(branchMispred, statistics::units::Count::get(),
165 "Number of times decode detected a branch misprediction"),
166 ADD_STAT(controlMispred, statistics::units::Count::get(),
167 "Number of times decode detected an instruction incorrectly "
168 "predicted as a control"),
169 ADD_STAT(decodedInsts, statistics::units::Count::get(),
170 "Number of instructions handled by decode"),
171 ADD_STAT(squashedInsts, statistics::units::Count::get(),
172 "Number of squashed instructions handled by decode")
173{
175 for (int i = 0; i < ThreadStatusMax; ++i) {
176 status.subname(i, statusStrings[i]);
177 status.subdesc(i, statusDefinitions[i]);
178 }
184}
185
186void
188{
189 timeBuffer = tb_ptr;
190
191 // Setup wire to write information back to fetch.
192 toFetch = timeBuffer->getWire(0);
193
194 // Create wires to get information from proper places in time buffer.
198}
199
200void
202{
203 decodeQueue = dq_ptr;
204
205 // Setup wire to write information to proper place in decode queue.
206 toRename = decodeQueue->getWire(0);
207}
208
209void
211{
212 fetchQueue = fq_ptr;
213
214 // Setup wire to read information from fetch queue.
216}
217
218void
223
224void
226{
227 for (ThreadID tid = 0; tid < numThreads; ++tid) {
228 assert(insts[tid].empty());
229 assert(skidBuffer[tid].empty());
230 }
231}
232
233bool
235{
236 for (ThreadID tid = 0; tid < numThreads; ++tid) {
237 if (!insts[tid].empty() || !skidBuffer[tid].empty() ||
238 (decodeStatus[tid] != Running && decodeStatus[tid] != Idle))
239 return false;
240 }
241 return true;
242}
243
244bool
246{
247 bool ret_val = false;
248
249 if (stalls[tid].rename) {
250 DPRINTF(Decode,"[tid:%i] Stall fom Rename stage detected.\n", tid);
251 ret_val = true;
252 }
253
254 return ret_val;
255}
256
257bool
259{
260 return fromFetch->size > 0;
261}
262
263bool
265{
266 DPRINTF(Decode, "[tid:%i] Blocking.\n", tid);
267
268 // Add the current inputs to the skid buffer so they can be
269 // reprocessed when this stage unblocks.
270 skidInsert(tid);
271
272 // If the decode status is blocked or unblocking then decode has not yet
273 // signalled fetch to unblock. In that case, there is no need to tell
274 // fetch to block.
275 if (decodeStatus[tid] != Blocked) {
276 // Set the status to Blocked.
277 decodeStatus[tid] = Blocked;
278
279 if (toFetch->decodeUnblock[tid]) {
280 toFetch->decodeUnblock[tid] = false;
281 } else {
282 toFetch->decodeBlock[tid] = true;
283 wroteToTimeBuffer = true;
284 }
285
286 return true;
287 }
288
289 return false;
290}
291
292bool
294{
295 // Decode is done unblocking only if the skid buffer is empty.
296 if (skidBuffer[tid].empty()) {
297 DPRINTF(Decode, "[tid:%i] Done unblocking.\n", tid);
298 toFetch->decodeUnblock[tid] = true;
299 wroteToTimeBuffer = true;
300
301 decodeStatus[tid] = Running;
302 return true;
303 }
304
305 DPRINTF(Decode, "[tid:%i] Currently unblocking.\n", tid);
306
307 return false;
308}
309
310void
311Decode::squash(const DynInstPtr &inst, bool control_miss, ThreadID tid)
312{
313 DPRINTF(Decode, "[tid:%i] [sn:%llu] Squashing due to incorrect branch "
314 "prediction detected at decode.\n", tid, inst->seqNum);
315
316 // Send back mispredict information.
317 toFetch->decodeInfo[tid].branchMispredict = true;
318 toFetch->decodeInfo[tid].controlMispredict = control_miss;
319 toFetch->decodeInfo[tid].mispredictInst = inst;
320 toFetch->decodeInfo[tid].squash = true;
321 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
322 set(toFetch->decodeInfo[tid].nextPC, *inst->branchTarget());
323
324 // Looking at inst->pcState().branching()
325 // may yield unexpected results if the branch
326 // was predicted taken but aliased in the BTB
327 // with a branch jumping to the next instruction (mistarget)
328 // Using PCState::branching() will send execution on the
329 // fallthrough and this will not be caught at execution (since
330 // branch was correctly predicted taken)
331 toFetch->decodeInfo[tid].branchTaken = inst->readPredTaken() ||
332 inst->isUncondCtrl();
333
334 toFetch->decodeInfo[tid].squashInst = inst;
335
336 InstSeqNum squash_seq_num = inst->seqNum;
337
338 // Might have to tell fetch to unblock.
339 if (decodeStatus[tid] == Blocked ||
340 decodeStatus[tid] == Unblocking) {
341 toFetch->decodeUnblock[tid] = 1;
342 }
343
344 // Set status to squashing.
345 decodeStatus[tid] = Squashing;
346
347 for (int i=0; i<fromFetch->size; i++) {
348 if (fromFetch->insts[i]->threadNumber == tid &&
349 fromFetch->insts[i]->seqNum > squash_seq_num) {
350 fromFetch->insts[i]->setSquashed();
351 }
352 }
353
354 // Clear the instruction list and skid buffer in case they have any
355 // insts in them.
356 while (!insts[tid].empty()) {
357 insts[tid].pop();
358 }
359
360 while (!skidBuffer[tid].empty()) {
361 skidBuffer[tid].pop();
362 }
363
364 // Squash instructions up until this one
365 cpu->removeInstsUntil(squash_seq_num, tid);
366}
367
368unsigned
370{
371 DPRINTF(Decode, "[tid:%i] Squashing.\n",tid);
372
373 if (decodeStatus[tid] == Blocked ||
374 decodeStatus[tid] == Unblocking) {
375 if (FullSystem) {
376 toFetch->decodeUnblock[tid] = 1;
377 } else {
378 // In syscall emulation, we can have both a block and a squash due
379 // to a syscall in the same cycle. This would cause both signals
380 // to be high. This shouldn't happen in full system.
381 // @todo: Determine if this still happens.
382 if (toFetch->decodeBlock[tid])
383 toFetch->decodeBlock[tid] = 0;
384 else
385 toFetch->decodeUnblock[tid] = 1;
386 }
387 }
388
389 // Set status to squashing.
390 decodeStatus[tid] = Squashing;
391
392 // Go through incoming instructions from fetch and squash them.
393 unsigned squash_count = 0;
394
395 for (int i=0; i<fromFetch->size; i++) {
396 if (fromFetch->insts[i]->threadNumber == tid) {
397 fromFetch->insts[i]->setSquashed();
398 squash_count++;
399 }
400 }
401
402 // Clear the instruction list and skid buffer in case they have any
403 // insts in them.
404 while (!insts[tid].empty()) {
405 insts[tid].pop();
406 }
407
408 while (!skidBuffer[tid].empty()) {
409 skidBuffer[tid].pop();
410 }
411
412 return squash_count;
413}
414
415void
417{
418 DynInstPtr inst = NULL;
419
420 while (!insts[tid].empty()) {
421 inst = insts[tid].front();
422
423 insts[tid].pop();
424
425 assert(tid == inst->threadNumber);
426
427 skidBuffer[tid].push(inst);
428
429 DPRINTF(Decode, "Inserting [tid:%d][sn:%lli] PC: %s into decode "
430 "skidBuffer %i\n", inst->threadNumber, inst->seqNum,
431 inst->pcState(), skidBuffer[tid].size());
432 }
433
434 // @todo: Eventually need to enforce this by not letting a thread
435 // fetch past its skidbuffer
436 assert(skidBuffer[tid].size() <= skidBufferMax);
437}
438
439bool
441{
442 for (ThreadID tid : *activeThreads) {
443 if (!skidBuffer[tid].empty())
444 return false;
445 }
446
447 return true;
448}
449
450void
452{
453 bool any_unblocking = false;
454
455 for (ThreadID tid : *activeThreads) {
456 if (decodeStatus[tid] == Unblocking) {
457 any_unblocking = true;
458 break;
459 }
460 }
461
462 // Decode will have activity if it's unblocking.
463 if (any_unblocking) {
464 if (_status == Inactive) {
465 _status = Active;
466
467 DPRINTF(Activity, "Activating stage.\n");
468
469 cpu->activateStage(CPU::DecodeIdx);
470 }
471 } else {
472 // If it's not unblocking, then decode will not have any internal
473 // activity. Switch it to inactive.
474 if (_status == Active) {
476 DPRINTF(Activity, "Deactivating stage.\n");
477
478 cpu->deactivateStage(CPU::DecodeIdx);
479 }
480 }
481}
482
483void
485{
486 int insts_from_fetch = fromFetch->size;
487 for (int i = 0; i < insts_from_fetch; ++i) {
488 insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
489 }
490}
491
492void
494{
495 if (fromRename->renameBlock[tid]) {
496 stalls[tid].rename = true;
497 }
498
499 if (fromRename->renameUnblock[tid]) {
500 assert(stalls[tid].rename);
501 stalls[tid].rename = false;
502 }
503}
504
505bool
507{
508 // Check if there's a squash signal, squash if there is.
509 // Check stall signals, block if necessary.
510 // If status was blocked
511 // Check if stall conditions have passed
512 // if so then go to unblocking
513 // If status was Squashing
514 // check if squashing is not high. Switch to running this cycle.
515
516 // Update the per thread stall statuses.
517 readStallSignals(tid);
518
519 // Check squash signals from commit.
520 if (fromCommit->commitInfo[tid].squash) {
521
522 DPRINTF(Decode, "[tid:%i] Squashing instructions due to squash "
523 "from commit.\n", tid);
524
525 squash(tid);
526
527 return true;
528 }
529
530 if (checkStall(tid)) {
531 return block(tid);
532 }
533
534 if (decodeStatus[tid] == Blocked) {
535 DPRINTF(Decode, "[tid:%i] Done blocking, switching to unblocking.\n",
536 tid);
537
539
540 unblock(tid);
541
542 return true;
543 }
544
545 if (decodeStatus[tid] == Squashing) {
546 // Switch status to running if decode isn't being told to block or
547 // squash this cycle.
548 DPRINTF(Decode, "[tid:%i] Done squashing, switching to running.\n",
549 tid);
550
551 decodeStatus[tid] = Running;
552
553 return false;
554 }
555
556 // If we've reached this point, we have not gotten any signals that
557 // cause decode to change its status. Decode remains the same as before.
558 return false;
559}
560
561void
563{
564 wroteToTimeBuffer = false;
565
566 bool status_change = false;
567
568 toRenameIndex = 0;
569
570 sortInsts();
571
572 //Check stall and squash signals.
573 for (ThreadID tid : *activeThreads) {
574 DPRINTF(Decode,"Processing [tid:%i]\n",tid);
575 status_change = checkSignalsAndUpdate(tid) || status_change;
576
577 decode(status_change, tid);
578 }
579
580 if (status_change) {
581 updateStatus();
582 }
583
584 if (wroteToTimeBuffer) {
585 DPRINTF(Activity, "Activity this cycle.\n");
586
587 cpu->activityThisCycle();
588 }
589}
590
591void
592Decode::decode(bool &status_change, ThreadID tid)
593{
594 // If status is Running or idle,
595 // call decodeInsts()
596 // If status is Unblocking,
597 // buffer any instructions coming from fetch
598 // continue trying to empty skid buffer
599 // check if stall conditions have passed
600
601 if (decodeStatus[tid] == Blocked) {
602 ++stats.status[Blocked];
603 } else if (decodeStatus[tid] == Squashing) {
604 ++stats.status[Squashing];
605 }
606
607 // Decode should try to decode as many instructions as its bandwidth
608 // will allow, as long as it is not currently blocked.
609 if (decodeStatus[tid] == Running ||
610 decodeStatus[tid] == Idle) {
611 DPRINTF(Decode, "[tid:%i] Not blocked, so attempting to run "
612 "stage.\n",tid);
613
614 decodeInsts(tid);
615 } else if (decodeStatus[tid] == Unblocking) {
616 // Make sure that the skid buffer has something in it if the
617 // status is unblocking.
618 assert(!skidsEmpty());
619
620 // If the status was unblocking, then instructions from the skid
621 // buffer were used. Remove those instructions and handle
622 // the rest of unblocking.
623 decodeInsts(tid);
624
625 if (fetchInstsValid()) {
626 // Add the current inputs to the skid buffer so they can be
627 // reprocessed when this stage unblocks.
628 skidInsert(tid);
629 }
630
631 status_change = unblock(tid) || status_change;
632 }
633}
634
635void
637{
638 // Instructions can come either from the skid buffer or the list of
639 // instructions coming from fetch, depending on decode's status.
640 int insts_available = decodeStatus[tid] == Unblocking ?
641 skidBuffer[tid].size() : insts[tid].size();
642
643 if (insts_available == 0) {
644 DPRINTF(Decode, "[tid:%i] Nothing to do, breaking out"
645 " early.\n",tid);
646 // Should I change the status to idle?
647 ++stats.status[Idle];
648 return;
649 } else if (decodeStatus[tid] == Unblocking) {
650 DPRINTF(Decode, "[tid:%i] Unblocking, removing insts from skid "
651 "buffer.\n",tid);
652 ++stats.status[Unblocking];
653 } else if (decodeStatus[tid] == Running) {
654 ++stats.status[Running];
655 }
656
657 std::queue<DynInstPtr>
658 &insts_to_decode = decodeStatus[tid] == Unblocking ?
659 skidBuffer[tid] : insts[tid];
660
661 DPRINTF(Decode, "[tid:%i] Sending instruction to rename.\n",tid);
662
663 while (insts_available > 0 && toRenameIndex < decodeWidth) {
664 assert(!insts_to_decode.empty());
665
666 DynInstPtr inst = std::move(insts_to_decode.front());
667
668 insts_to_decode.pop();
669
670 DPRINTF(Decode, "[tid:%i] Processing instruction [sn:%lli] with "
671 "PC %s\n", tid, inst->seqNum, inst->pcState());
672
673 if (inst->isSquashed()) {
674 DPRINTF(Decode, "[tid:%i] Instruction %i with PC %s is "
675 "squashed, skipping.\n",
676 tid, inst->seqNum, inst->pcState());
677
678 ++stats.squashedInsts;
679
680 --insts_available;
681
682 continue;
683 }
684
685 // Also check if instructions have no source registers. Mark
686 // them as ready to issue at any time. Not sure if this check
687 // should exist here or at a later stage; however it doesn't matter
688 // too much for function correctness.
689 if (inst->numSrcRegs() == 0) {
690 inst->setCanIssue();
691 }
692
693 // This current instruction is valid, so add it into the decode
694 // queue. The next instruction may not be valid, so check to
695 // see if branches were predicted correctly.
696 toRename->insts[toRenameIndex] = inst;
697
698 ++(toRename->size);
700 ++stats.decodedInsts;
701 --insts_available;
702
703 inst->decodeTick = curTick() - inst->fetchTick;
704
705 // Ensure that if it was predicted as a branch, it really is a
706 // branch.
707 if (inst->readPredTaken() && !inst->isControl()) {
708 panic("Instruction predicted as a branch!");
709
710 ++stats.controlMispred;
711
712 // Might want to set some sort of boolean and just do
713 // a check at the end
714 squash(inst, true, inst->threadNumber);
715
716 break;
717 }
718
719 // Go ahead and compute any PC-relative branches.
720 // This includes direct unconditional control and
721 // direct conditional control that is predicted taken.
722 if (inst->isDirectCtrl() &&
723 (inst->isUncondCtrl() || inst->readPredTaken()))
724 {
725 ++stats.branchResolved;
726
727 std::unique_ptr<PCStateBase> target = inst->branchTarget();
728 if (*target != inst->readPredTarg()) {
729 ++stats.branchMispred;
730
731 // Might want to set some sort of boolean and just do
732 // a check at the end
733 squash(inst, false, inst->threadNumber);
734
736 "[tid:%i] [sn:%llu] "
737 "Updating predictions: Wrong predicted target: %s \
738 PredPC: %s\n",
739 tid, inst->seqNum, inst->readPredTarg(), *target);
740 //The micro pc after an instruction level branch should be 0
741 inst->setPredTarg(*target);
742 break;
743 }
744 }
745 }
746
747 // If we didn't process all instructions, then we will need to block
748 // and put all those instructions into the skid buffer.
749 if (!insts_to_decode.empty()) {
750 block(tid);
751 }
752
753 // Record that decode has written to the time buffer for activity
754 // tracking.
755 if (toRenameIndex) {
756 wroteToTimeBuffer = true;
757 }
758}
759
760} // namespace o3
761} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition cpu.hh:97
DecodeStatus _status
Decode status.
Definition decode.hh:95
std::queue< DynInstPtr > skidBuffer[MaxThreads]
Skid buffer between fetch and decode.
Definition decode.hh:247
bool wroteToTimeBuffer
Variable that tracks if decode has written to the time buffer this cycle.
Definition decode.hh:252
bool unblock(ThreadID tid)
Switches decode to unblocking if the skid buffer is empty, and signals back that decode has unblocked...
Definition decode.cc:293
bool squashAfterDelaySlot[MaxThreads]
Tells when their is a pending delay slot inst.
Definition decode.hh:300
void readStallSignals(ThreadID tid)
Reads all stall signals from the backwards communication timebuffer.
Definition decode.cc:493
gem5::o3::Decode::DecodeStats stats
DynInstPtr squashInst[MaxThreads]
Instruction used for squashing branch (used for MIPS)
Definition decode.hh:294
CPU * cpu
CPU interface.
Definition decode.hh:213
Cycles iewToDecodeDelay
IEW to decode delay.
Definition decode.hh:267
void decodeInsts(ThreadID tid)
Processes instructions from fetch and passes them on to rename.
Definition decode.cc:636
Stalls stalls[MaxThreads]
Tracks which stages are telling decode to stall.
Definition decode.hh:261
TimeBuffer< TimeStruct >::wire toFetch
Wire to write information heading to previous stages.
Definition decode.hh:229
unsigned skidBufferMax
Maximum size of the skid buffer.
Definition decode.hh:288
Cycles commitToDecodeDelay
Commit to decode delay.
Definition decode.hh:270
void decode(bool &status_change, ThreadID tid)
Determines what to do based on decode's current status.
Definition decode.cc:592
bool fetchInstsValid()
Returns if there any instructions from fetch on this cycle.
Definition decode.cc:258
void squash(const DynInstPtr &inst, bool control_miss, ThreadID tid)
Squashes if there is a PC-relative branch that was predicted incorrectly.
Definition decode.cc:311
bool checkSignalsAndUpdate(ThreadID tid)
Checks all input signals and updates decode's status appropriately.
Definition decode.cc:506
void startupStage()
Definition decode.cc:111
TimeBuffer< DecodeStruct >::wire toRename
Wire used to write any information heading to rename.
Definition decode.hh:235
Cycles renameToDecodeDelay
Rename to decode delay.
Definition decode.hh:264
Cycles fetchToDecodeDelay
Fetch to decode delay.
Definition decode.hh:273
std::queue< DynInstPtr > insts[MaxThreads]
Queue of all instructions coming from fetch this cycle.
Definition decode.hh:244
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Sets pointer to time buffer coming from fetch.
Definition decode.cc:210
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main backwards communication time buffer pointer.
Definition decode.cc:187
ThreadStatus decodeStatus[MaxThreads]
Per-thread status.
Definition decode.hh:98
void sortInsts()
Separates instructions from fetch into individual lists of instructions sorted by thread.
Definition decode.cc:484
unsigned toRenameIndex
Index of instructions being sent to rename.
Definition decode.hh:279
void setDecodeQueue(TimeBuffer< DecodeStruct > *dq_ptr)
Sets pointer to time buffer used to communicate to the next stage.
Definition decode.cc:201
TimeBuffer< DecodeStruct > * decodeQueue
Decode instruction queue.
Definition decode.hh:232
void updateStatus()
Updates overall decode status based on all of the threads' statuses.
Definition decode.cc:451
bool skidsEmpty()
Returns if all of the skid buffers are empty.
Definition decode.cc:440
unsigned decodeWidth
The width of decode, in instructions.
Definition decode.hh:276
bool isDrained() const
Has the stage drained?
Definition decode.cc:234
TimeBuffer< TimeStruct >::wire fromCommit
Wire to get commit's information from backwards time buffer.
Definition decode.hh:225
ThreadID numThreads
number of Active Threads
Definition decode.hh:282
TimeBuffer< TimeStruct > * timeBuffer
Time buffer interface.
Definition decode.hh:216
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
Definition decode.cc:219
void resetStage()
Definition decode.cc:140
TimeBuffer< FetchStruct >::wire fromFetch
Wire to get fetch's output from fetch queue.
Definition decode.hh:241
TimeBuffer< TimeStruct >::wire fromRename
Wire to get rename's output from backwards time buffer.
Definition decode.hh:219
Addr bdelayDoneSeqNum[MaxThreads]
SeqNum of Squashing Branch Delay Instruction (used for MIPS)
Definition decode.hh:291
TimeBuffer< TimeStruct >::wire fromIEW
Wire to get iew's information from backwards time buffer.
Definition decode.hh:222
void clearStates(ThreadID tid)
Clear all thread-specific states.
Definition decode.cc:117
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition decode.cc:225
std::list< ThreadID > * activeThreads
List of active thread ids.
Definition decode.hh:285
void tick()
Ticks decode, processing all input signals and decoding as many instructions as possible.
Definition decode.cc:562
Decode(CPU *_cpu, const BaseO3CPUParams &params)
Decode constructor.
Definition decode.cc:84
bool block(ThreadID tid)
Switches decode to blocking, and signals back that decode has become blocked.
Definition decode.cc:264
std::string name() const
Returns the name of decode.
Definition decode.cc:153
void skidInsert(ThreadID tid)
Inserts a thread's instructions into the skid buffer, to be decoded once decode unblocks.
Definition decode.cc:416
TimeBuffer< FetchStruct > * fetchQueue
Fetch instruction queue interface.
Definition decode.hh:238
bool checkStall(ThreadID tid) const
Checks all stall signals, and returns if any are true.
Definition decode.cc:245
STL list class.
Definition stl.hh:51
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
static constexpr int MaxThreads
Definition limits.hh:38
void removeCommThreadInsts(ThreadID tid, CommStruct &comm_struct)
Remove instructions belonging to given thread from the given comm struct's instruction array.
Definition comm.hh:248
RefCountingPtr< DynInst > DynInstPtr
static constexpr int MaxWidth
Definition limits.hh:37
Units for Stats.
Definition units.hh:113
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition info.hh:61
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
uint64_t InstSeqNum
Definition inst_seq.hh:40
Struct that defines the information passed from decode to rename.
Definition comm.hh:74
static std::string statusStrings[ThreadStatusMax]
Definition decode.hh:304
statistics::Scalar branchResolved
Stat for number of times a branch is resolved at decode.
Definition decode.hh:312
static std::string statusDefinitions[ThreadStatusMax]
Definition decode.hh:305
statistics::Vector status
Stat for total number of cycles spent in each decode state.
Definition decode.hh:310
statistics::Scalar squashedInsts
Stat for total number of squashed instructions.
Definition decode.hh:322
statistics::Scalar branchMispred
Stat for number of times a branch mispredict is detected.
Definition decode.hh:314
statistics::Scalar decodedInsts
Stat for total number of decoded instructions.
Definition decode.hh:320
statistics::Scalar controlMispred
Stat for number of times decode detected a non-control instruction incorrectly predicted as a branch.
Definition decode.hh:318
Struct that defines all backwards communication.
Definition comm.hh:114
bool decodeBlock[MaxThreads]
Definition comm.hh:233
DecodeComm decodeInfo[MaxThreads]
Definition comm.hh:140
bool decodeUnblock[MaxThreads]
Definition comm.hh:234

Generated on Mon Oct 27 2025 04:13:00 for gem5 by doxygen 1.14.0