gem5 v24.0.0.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),
62 squashWidth(params.squashWidth),
63 numInstsInROB(0),
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
155
156 while (threads != end) {
157 ThreadID tid = *threads++;
158
159 if (robPolicy == SMTQueuePolicy::Partitioned) {
160 maxEntries[tid] = numEntries / active_threads;
161 } else if (robPolicy == SMTQueuePolicy::Threshold &&
162 active_threads == 1) {
163 maxEntries[tid] = numEntries;
164 }
165 }
166 }
167}
168
169int
171{
172 if (robPolicy == SMTQueuePolicy::Partitioned) {
173 return numEntries / num_threads;
174 } else {
175 return 0;
176 }
177}
178
179int
181{
182 int total = 0;
183
184 for (ThreadID tid = 0; tid < numThreads; tid++)
185 total += countInsts(tid);
186
187 return total;
188}
189
190size_t
192{
193 return instList[tid].size();
194}
195
196void
198{
199 assert(inst);
200
201 stats.writes++;
202
203 DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
204
205 assert(numInstsInROB != numEntries);
206
207 ThreadID tid = inst->threadNumber;
208
209 instList[tid].push_back(inst);
210
211 //Set Up head iterator if this is the 1st instruction in the ROB
212 if (numInstsInROB == 0) {
213 head = instList[tid].begin();
214 assert((*head) == inst);
215 }
216
217 //Must Decrement for iterator to actually be valid since __.end()
218 //actually points to 1 after the last inst
219 tail = instList[tid].end();
220 tail--;
221
222 inst->setInROB();
223
225 ++threadEntries[tid];
226
227 assert((*tail) == inst);
228
229 DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid,
230 threadEntries[tid]);
231}
232
233void
235{
236 stats.writes++;
237
238 assert(numInstsInROB > 0);
239
240 // Get the head ROB instruction by copying it and remove it from the list
241 InstIt head_it = instList[tid].begin();
242
243 DynInstPtr head_inst = std::move(*head_it);
244 instList[tid].erase(head_it);
245
246 assert(head_inst->readyToCommit());
247
248 DPRINTF(ROB, "[tid:%i] Retiring head instruction, "
249 "instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(),
250 head_inst->seqNum);
251
253 --threadEntries[tid];
254
255 head_inst->clearInROB();
256 head_inst->setCommitted();
257
258 //Update "Global" Head of ROB
259 updateHead();
260
261 // @todo: A special case is needed if the instruction being
262 // retired is the only instruction in the ROB; otherwise the tail
263 // iterator will become invalidated.
264 cpu->removeFrontInst(head_inst);
265}
266
267bool
269{
270 stats.reads++;
271 if (threadEntries[tid] != 0) {
272 return instList[tid].front()->readyToCommit();
273 }
274
275 return false;
276}
277
278bool
280{
281 //@todo: set ActiveThreads through ROB or CPU
284
285 while (threads != end) {
286 ThreadID tid = *threads++;
287
288 if (isHeadReady(tid)) {
289 return true;
290 }
291 }
292
293 return false;
294}
295
296unsigned
301
302unsigned
304{
305 return maxEntries[tid] - threadEntries[tid];
306}
307
308void
310{
311 stats.writes++;
312 DPRINTF(ROB, "[tid:%i] Squashing instructions until [sn:%llu].\n",
313 tid, squashedSeqNum[tid]);
314
315 assert(squashIt[tid] != instList[tid].end());
316
317 if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
318 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
319 tid);
320
321 squashIt[tid] = instList[tid].end();
322
323 doneSquashing[tid] = true;
324 return;
325 }
326
327 bool robTailUpdate = false;
328
329 unsigned int numInstsToSquash = squashWidth;
330
331 // If the CPU is exiting, squash all of the instructions
332 // it is told to, even if that exceeds the squashWidth.
333 // Set the number to the number of entries (the max).
334 if (cpu->isThreadExiting(tid))
335 {
336 numInstsToSquash = numEntries;
337 }
338
339 for (int numSquashed = 0;
340 numSquashed < numInstsToSquash &&
341 squashIt[tid] != instList[tid].end() &&
342 (*squashIt[tid])->seqNum > squashedSeqNum[tid];
343 ++numSquashed)
344 {
345 DPRINTF(ROB, "[tid:%i] Squashing instruction PC %s, seq num %i.\n",
346 (*squashIt[tid])->threadNumber,
347 (*squashIt[tid])->pcState(),
348 (*squashIt[tid])->seqNum);
349
350 // Mark the instruction as squashed, and ready to commit so that
351 // it can drain out of the pipeline.
352 (*squashIt[tid])->setSquashed();
353
354 (*squashIt[tid])->setCanCommit();
355
356
357 if (squashIt[tid] == instList[tid].begin()) {
358 DPRINTF(ROB, "Reached head of instruction list while "
359 "squashing.\n");
360
361 squashIt[tid] = instList[tid].end();
362
363 doneSquashing[tid] = true;
364
365 return;
366 }
367
368 InstIt tail_thread = instList[tid].end();
369 tail_thread--;
370
371 if ((*squashIt[tid]) == (*tail_thread))
372 robTailUpdate = true;
373
374 squashIt[tid]--;
375 }
376
377
378 // Check if ROB is done squashing.
379 if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
380 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
381 tid);
382
383 squashIt[tid] = instList[tid].end();
384
385 doneSquashing[tid] = true;
386 }
387
388 if (robTailUpdate) {
389 updateTail();
390 }
391}
392
393
394void
396{
397 InstSeqNum lowest_num = 0;
398 bool first_valid = true;
399
400 // @todo: set ActiveThreads through ROB or CPU
403
404 while (threads != end) {
405 ThreadID tid = *threads++;
406
407 if (instList[tid].empty())
408 continue;
409
410 if (first_valid) {
411 head = instList[tid].begin();
412 lowest_num = (*head)->seqNum;
413 first_valid = false;
414 continue;
415 }
416
417 InstIt head_thread = instList[tid].begin();
418
419 DynInstPtr head_inst = (*head_thread);
420
421 assert(head_inst != 0);
422
423 if (head_inst->seqNum < lowest_num) {
424 head = head_thread;
425 lowest_num = head_inst->seqNum;
426 }
427 }
428
429 if (first_valid) {
430 head = instList[0].end();
431 }
432
433}
434
435void
437{
438 tail = instList[0].end();
439 bool first_valid = true;
440
443
444 while (threads != end) {
445 ThreadID tid = *threads++;
446
447 if (instList[tid].empty()) {
448 continue;
449 }
450
451 // If this is the first valid then assign w/out
452 // comparison
453 if (first_valid) {
454 tail = instList[tid].end();
455 tail--;
456 first_valid = false;
457 continue;
458 }
459
460 // Assign new tail if this thread's tail is younger
461 // than our current "tail high"
462 InstIt tail_thread = instList[tid].end();
463 tail_thread--;
464
465 if ((*tail_thread)->seqNum > (*tail)->seqNum) {
466 tail = tail_thread;
467 }
468 }
469}
470
471
472void
474{
475 if (isEmpty(tid)) {
476 DPRINTF(ROB, "Does not need to squash due to being empty "
477 "[sn:%llu]\n",
478 squash_num);
479
480 return;
481 }
482
483 DPRINTF(ROB, "Starting to squash within the ROB.\n");
484
485 robStatus[tid] = ROBSquashing;
486
487 doneSquashing[tid] = false;
488
489 squashedSeqNum[tid] = squash_num;
490
491 if (!instList[tid].empty()) {
492 InstIt tail_thread = instList[tid].end();
493 tail_thread--;
494
495 squashIt[tid] = tail_thread;
496
497 doSquash(tid);
498 }
499}
500
501const DynInstPtr&
503{
504 if (threadEntries[tid] != 0) {
505 InstIt head_thread = instList[tid].begin();
506
507 assert((*head_thread)->isInROB());
508
509 return *head_thread;
510 } else {
511 return dummyInst;
512 }
513}
514
517{
518 InstIt tail_thread = instList[tid].end();
519 tail_thread--;
520
521 return *tail_thread;
522}
523
525 : statistics::Group(parent, "rob"),
526 ADD_STAT(reads, statistics::units::Count::get(),
527 "The number of ROB reads"),
528 ADD_STAT(writes, statistics::units::Count::get(),
529 "The number of ROB writes")
530{
531}
532
535{
536 for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) {
537 if ((*it)->seqNum == squash_inst) {
538 return *it;
539 }
540 }
541 return NULL;
542}
543
544} // namespace o3
545} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
virtual std::string name() const
Definition named.hh:47
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition cpu.hh:94
bool isThreadExiting(ThreadID tid) const
Is the thread trying to exit?
Definition cpu.cc:1397
void removeFrontInst(const DynInstPtr &inst)
Remove an instruction from the front end of the list.
Definition cpu.cc:1160
Fetch class handles both single threaded and SMT fetch.
Definition fetch.hh:79
ROB class.
Definition rob.hh:72
bool canCommit()
Is there any commitable head instruction across all threads ready.
Definition rob.cc:279
int countInsts()
This is more of a debugging function than anything.
Definition rob.cc:180
void insertInst(const DynInstPtr &inst)
Function to insert an instruction into the ROB.
Definition rob.cc:197
gem5::o3::ROB::ROBStats stats
unsigned numFreeEntries()
Returns the number of total free entries in the ROB.
Definition rob.cc:297
void updateTail()
Updates the tail instruction with the new youngest instruction.
Definition rob.cc:436
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:473
bool isHeadReady(ThreadID tid)
Is the oldest instruction across all threads ready.
Definition rob.cc:268
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:234
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:534
@ 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:395
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:309
const DynInstPtr & readHeadInst(ThreadID tid)
Returns pointer to the head instruction within the ROB.
Definition rob.cc:502
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:170
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:516
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
const FlagsType total
Print the total.
Definition info.hh:59
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria 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:524
statistics::Scalar reads
Definition rob.hh:338
statistics::Scalar writes
Definition rob.hh:340

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0