gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
rob.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#include "cpu/o3/rob.hh"
42
43#include <list>
44
45#include "base/logging.hh"
46#include "cpu/o3/dyn_inst.hh"
47#include "cpu/o3/limits.hh"
48#include "debug/Fetch.hh"
49#include "debug/ROB.hh"
50#include "params/BaseO3CPU.hh"
51
52namespace gem5
53{
54
55namespace o3
56{
57
58ROB::ROB(CPU *_cpu, const BaseO3CPUParams &params)
59 : robPolicy(params.smtROBPolicy),
60 cpu(_cpu),
61 numEntries(params.numROBEntries),
64 numThreads(params.numThreads),
65 stats(_cpu)
66{
67 //Figure out rob policy
68 if (robPolicy == SMTQueuePolicy::Dynamic) {
69 //Set Max Entries to Total ROB Capacity
70 for (ThreadID tid = 0; tid < numThreads; tid++) {
72 }
73
74 } else if (robPolicy == SMTQueuePolicy::Partitioned) {
75 DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
76
77 //@todo:make work if part_amt doesnt divide evenly.
78 int part_amt = numEntries / numThreads;
79
80 //Divide ROB up evenly
81 for (ThreadID tid = 0; tid < numThreads; tid++) {
82 maxEntries[tid] = part_amt;
83 }
84
85 } else if (robPolicy == SMTQueuePolicy::Threshold) {
86 DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
87
88 int threshold = params.smtROBThreshold;;
89
90 //Divide up by threshold amount
91 for (ThreadID tid = 0; tid < numThreads; tid++) {
92 maxEntries[tid] = threshold;
93 }
94 }
95
96 for (ThreadID tid = numThreads; tid < MaxThreads; tid++) {
97 maxEntries[tid] = 0;
98 }
99
100 resetState();
101}
102
103void
105{
106 for (ThreadID tid = 0; tid < MaxThreads; tid++) {
107 threadEntries[tid] = 0;
108 squashIt[tid] = instList[tid].end();
109 squashedSeqNum[tid] = 0;
110 doneSquashing[tid] = true;
111 }
112 numInstsInROB = 0;
113
114 // Initialize the "universal" ROB head & tail point to invalid
115 // pointers
116 head = instList[0].end();
117 tail = instList[0].end();
118}
119
120std::string
122{
123 return cpu->name() + ".rob";
124}
125
126void
128{
129 DPRINTF(ROB, "Setting active threads list pointer.\n");
130 activeThreads = at_ptr;
131}
132
133void
135{
136 for (ThreadID tid = 0; tid < numThreads; tid++)
137 assert(instList[tid].empty());
138 assert(isEmpty());
139}
140
141void
143{
144 resetState();
145}
146
147void
149{
150 if (robPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) {
151 auto active_threads = activeThreads->size();
152
153 for (ThreadID tid : *activeThreads) {
154 if (robPolicy == SMTQueuePolicy::Partitioned) {
155 maxEntries[tid] = numEntries / active_threads;
156 } else if (robPolicy == SMTQueuePolicy::Threshold &&
157 active_threads == 1) {
158 maxEntries[tid] = numEntries;
159 }
160 }
161 }
162}
163
164int
166{
167 if (robPolicy == SMTQueuePolicy::Partitioned) {
168 return numEntries / num_threads;
169 } else {
170 return 0;
171 }
172}
173
174int
176{
177 int total = 0;
178
179 for (ThreadID tid = 0; tid < numThreads; tid++)
180 total += countInsts(tid);
181
182 return total;
183}
184
185size_t
187{
188 return instList[tid].size();
189}
190
191void
193{
194 assert(inst);
195
196 stats.writes++;
197
198 DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
199
200 assert(numInstsInROB != numEntries);
201
202 ThreadID tid = inst->threadNumber;
203
204 instList[tid].push_back(inst);
205
206 //Set Up head iterator if this is the 1st instruction in the ROB
207 if (numInstsInROB == 0) {
208 head = instList[tid].begin();
209 assert((*head) == inst);
210 }
211
212 //Must Decrement for iterator to actually be valid since __.end()
213 //actually points to 1 after the last inst
214 tail = instList[tid].end();
215 tail--;
216
217 inst->setInROB();
218
220 ++threadEntries[tid];
221
222 assert((*tail) == inst);
223
224 DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid,
225 threadEntries[tid]);
226}
227
228void
230{
231 stats.writes++;
232
233 assert(numInstsInROB > 0);
234
235 // Get the head ROB instruction by copying it and remove it from the list
236 InstIt head_it = instList[tid].begin();
237
238 DynInstPtr head_inst = std::move(*head_it);
239 instList[tid].erase(head_it);
240
241 assert(head_inst->readyToCommit());
242
243 DPRINTF(ROB, "[tid:%i] Retiring head instruction, "
244 "instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(),
245 head_inst->seqNum);
246
248 --threadEntries[tid];
249
250 head_inst->clearInROB();
251 head_inst->setCommitted();
252
253 //Update "Global" Head of ROB
254 updateHead();
255
256 // @todo: A special case is needed if the instruction being
257 // retired is the only instruction in the ROB; otherwise the tail
258 // iterator will become invalidated.
259 cpu->removeFrontInst(head_inst);
260}
261
262bool
264{
265 stats.reads++;
266 if (threadEntries[tid] != 0) {
267 return instList[tid].front()->readyToCommit();
268 }
269
270 return false;
271}
272
273bool
275{
276 //@todo: set ActiveThreads through ROB or CPU
277 for (ThreadID tid : *activeThreads) {
278 if (isHeadReady(tid)) {
279 return true;
280 }
281 }
282
283 return false;
284}
285
286unsigned
291
292unsigned
294{
295 return maxEntries[tid] - threadEntries[tid];
296}
297
298void
300{
301 stats.writes++;
302 DPRINTF(ROB, "[tid:%i] Squashing instructions until [sn:%llu].\n",
303 tid, squashedSeqNum[tid]);
304
305 assert(squashIt[tid] != instList[tid].end());
306
307 if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
308 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
309 tid);
310
311 squashIt[tid] = instList[tid].end();
312
313 doneSquashing[tid] = true;
314 return;
315 }
316
317 bool robTailUpdate = false;
318
319 unsigned int numInstsToSquash = squashWidth;
320
321 // If the CPU is exiting, squash all of the instructions
322 // it is told to, even if that exceeds the squashWidth.
323 // Set the number to the number of entries (the max).
324 if (cpu->isThreadExiting(tid))
325 {
326 numInstsToSquash = numEntries;
327 }
328
329 for (int numSquashed = 0;
330 numSquashed < numInstsToSquash &&
331 squashIt[tid] != instList[tid].end() &&
332 (*squashIt[tid])->seqNum > squashedSeqNum[tid];
333 ++numSquashed)
334 {
335 DPRINTF(ROB, "[tid:%i] Squashing instruction PC %s, seq num %i.\n",
336 (*squashIt[tid])->threadNumber,
337 (*squashIt[tid])->pcState(),
338 (*squashIt[tid])->seqNum);
339
340 // Mark the instruction as squashed, and ready to commit so that
341 // it can drain out of the pipeline.
342 (*squashIt[tid])->setSquashed();
343
344 (*squashIt[tid])->setCanCommit();
345
346
347 if (squashIt[tid] == instList[tid].begin()) {
348 DPRINTF(ROB, "Reached head of instruction list while "
349 "squashing.\n");
350
351 squashIt[tid] = instList[tid].end();
352
353 doneSquashing[tid] = true;
354
355 return;
356 }
357
358 InstIt tail_thread = instList[tid].end();
359 tail_thread--;
360
361 if ((*squashIt[tid]) == (*tail_thread))
362 robTailUpdate = true;
363
364 squashIt[tid]--;
365 }
366
367
368 // Check if ROB is done squashing.
369 if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
370 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
371 tid);
372
373 squashIt[tid] = instList[tid].end();
374
375 doneSquashing[tid] = true;
376 }
377
378 if (robTailUpdate) {
379 updateTail();
380 }
381}
382
383
384void
386{
387 InstSeqNum lowest_num = 0;
388 bool first_valid = true;
389
390 // @todo: set ActiveThreads through ROB or CPU
391 for (ThreadID tid : *activeThreads) {
392 if (instList[tid].empty())
393 continue;
394
395 if (first_valid) {
396 head = instList[tid].begin();
397 lowest_num = (*head)->seqNum;
398 first_valid = false;
399 continue;
400 }
401
402 InstIt head_thread = instList[tid].begin();
403
404 DynInstPtr head_inst = (*head_thread);
405
406 assert(head_inst != 0);
407
408 if (head_inst->seqNum < lowest_num) {
409 head = head_thread;
410 lowest_num = head_inst->seqNum;
411 }
412 }
413
414 if (first_valid) {
415 head = instList[0].end();
416 }
417
418}
419
420void
422{
423 tail = instList[0].end();
424 bool first_valid = true;
425
426 for (ThreadID tid : *activeThreads) {
427 if (instList[tid].empty()) {
428 continue;
429 }
430
431 // If this is the first valid then assign w/out
432 // comparison
433 if (first_valid) {
434 tail = instList[tid].end();
435 tail--;
436 first_valid = false;
437 continue;
438 }
439
440 // Assign new tail if this thread's tail is younger
441 // than our current "tail high"
442 InstIt tail_thread = instList[tid].end();
443 tail_thread--;
444
445 if ((*tail_thread)->seqNum > (*tail)->seqNum) {
446 tail = tail_thread;
447 }
448 }
449}
450
451
452void
454{
455 if (isEmpty(tid)) {
456 DPRINTF(ROB, "Does not need to squash due to being empty "
457 "[sn:%llu]\n",
458 squash_num);
459
460 return;
461 }
462
463 DPRINTF(ROB, "Starting to squash within the ROB.\n");
464
465 robStatus[tid] = ROBSquashing;
466
467 doneSquashing[tid] = false;
468
469 squashedSeqNum[tid] = squash_num;
470
471 if (!instList[tid].empty()) {
472 InstIt tail_thread = instList[tid].end();
473 tail_thread--;
474
475 squashIt[tid] = tail_thread;
476
477 doSquash(tid);
478 }
479}
480
481const DynInstPtr&
483{
484 if (threadEntries[tid] != 0) {
485 InstIt head_thread = instList[tid].begin();
486
487 assert((*head_thread)->isInROB());
488
489 return *head_thread;
490 } else {
491 return dummyInst;
492 }
493}
494
497{
498 InstIt tail_thread = instList[tid].end();
499 tail_thread--;
500
501 return *tail_thread;
502}
503
505 : statistics::Group(parent, "rob"),
506 ADD_STAT(reads, statistics::units::Count::get(),
507 "The number of ROB reads"),
508 ADD_STAT(writes, statistics::units::Count::get(),
509 "The number of ROB writes")
510{
511}
512
515{
516 for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) {
517 if ((*it)->seqNum == squash_inst) {
518 return *it;
519 }
520 }
521 return NULL;
522}
523
524} // namespace o3
525} // 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:94
Fetch class handles both single threaded and SMT fetch.
Definition fetch.hh:80
bool canCommit()
Is there any commitable head instruction across all threads ready.
Definition rob.cc:274
int countInsts()
This is more of a debugging function than anything.
Definition rob.cc:175
void insertInst(const DynInstPtr &inst)
Function to insert an instruction into the ROB.
Definition rob.cc:192
gem5::o3::ROB::ROBStats stats
unsigned numFreeEntries()
Returns the number of total free entries in the ROB.
Definition rob.cc:287
void updateTail()
Updates the tail instruction with the new youngest instruction.
Definition rob.cc:421
InstIt tail
Iterator pointing to the instruction which is the last instruction in the ROB.
Definition rob.hh:299
void resetEntries()
Re-adjust ROB partitioning.
Definition rob.cc:148
void squash(InstSeqNum squash_num, ThreadID tid)
Squashes all instructions younger than the given sequence number for the specific thread.
Definition rob.cc:453
bool isHeadReady(ThreadID tid)
Is the oldest instruction across all threads ready.
Definition rob.cc:263
ROB(CPU *_cpu, const BaseO3CPUParams &params)
ROB constructor.
Definition rob.cc:58
void retireHead(ThreadID tid)
Retires the head instruction, removing it from the ROB.
Definition rob.cc:229
std::list< DynInstPtr > instList[MaxThreads]
ROB List of Instructions.
Definition rob.hh:289
std::string name() const
Definition rob.cc:121
DynInstPtr findInst(ThreadID tid, InstSeqNum squash_inst)
Returns a pointer to the instruction with the given sequence if it is in the ROB.
Definition rob.cc:514
@ ROBSquashing
Definition rob.hh:82
InstSeqNum squashedSeqNum[MaxThreads]
The sequence number of the squashed instruction.
Definition rob.hh:324
std::list< ThreadID > * activeThreads
Active Threads in CPU.
Definition rob.hh:277
void updateHead()
Updates the head instruction with the new oldest instruction.
Definition rob.cc:385
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition rob.cc:134
Status robStatus[MaxThreads]
Per-thread ROB status.
Definition rob.hh:87
void doSquash(ThreadID tid)
Executes the squash, marking squashed instructions.
Definition rob.cc:299
const DynInstPtr & readHeadInst(ThreadID tid)
Returns pointer to the head instruction within the ROB.
Definition rob.cc:482
unsigned maxEntries[MaxThreads]
Max Insts a Thread Can Have in the ROB.
Definition rob.hh:286
InstIt head
Iterator pointing to the instruction which is the first instruction in in the ROB.
Definition rob.hh:303
int entryAmount(ThreadID num_threads)
Number of entries needed For 'num_threads' amount of threads.
Definition rob.cc:165
SMTQueuePolicy robPolicy
ROB resource sharing policy for SMT mode.
Definition rob.hh:90
DynInstPtr readTailInst(ThreadID tid)
Returns pointer to the tail instruction within the ROB.
Definition rob.cc:496
InstIt squashIt[MaxThreads]
Iterator used for walking through the list of instructions when squashing.
Definition rob.hh:313
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to the list of active threads.
Definition rob.cc:127
unsigned numEntries
Number of instructions in the ROB.
Definition rob.hh:280
void resetState()
Reset the ROB state.
Definition rob.cc:104
ThreadID numThreads
Number of active threads.
Definition rob.hh:330
bool doneSquashing[MaxThreads]
Is the ROB done squashing.
Definition rob.hh:327
CPU * cpu
Pointer to the CPU.
Definition rob.hh:274
unsigned squashWidth
Number of instructions that can be squashed in a single cycle.
Definition rob.hh:292
std::list< DynInstPtr >::iterator InstIt
Definition rob.hh:75
bool isEmpty() const
Returns if the ROB is empty.
Definition rob.hh:194
void takeOverFrom()
Takes over another CPU's thread.
Definition rob.cc:142
DynInstPtr dummyInst
Dummy instruction returned if there are no insts left.
Definition rob.hh:320
int numInstsInROB
Number of instructions in the ROB.
Definition rob.hh:317
unsigned threadEntries[MaxThreads]
Entries Per Thread.
Definition rob.hh:283
Statistics container.
Definition group.hh:93
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
static constexpr int MaxThreads
Definition limits.hh:38
RefCountingPtr< DynInst > DynInstPtr
Units for Stats.
Definition units.hh:113
const FlagsType total
Print the total.
Definition info.hh:59
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
uint64_t InstSeqNum
Definition inst_seq.hh:40
ROBStats(statistics::Group *parent)
Definition rob.cc:504
statistics::Scalar reads
Definition rob.hh:338
statistics::Scalar writes
Definition rob.hh:340

Generated on Mon May 26 2025 09:19:08 for gem5 by doxygen 1.13.2