rob_impl.hh (2665:a124942bacb8) rob_impl.hh (2670:9107b8bd08cd)
1/*
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the

--- 12 unchanged lines hidden (view full) ---

23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the

--- 12 unchanged lines hidden (view full) ---

23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
31#ifndef __CPU_O3_CPU_ROB_IMPL_HH__
32#define __CPU_O3_CPU_ROB_IMPL_HH__
33
34#include "config/full_system.hh"
35#include "cpu/o3/rob.hh"
36
31#include "config/full_system.hh"
32#include "cpu/o3/rob.hh"
33
34using namespace std;
35
37template <class Impl>
36template <class Impl>
38ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
37ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
38 string _smtROBPolicy, unsigned _smtROBThreshold,
39 unsigned _numThreads)
39 : numEntries(_numEntries),
40 squashWidth(_squashWidth),
41 numInstsInROB(0),
40 : numEntries(_numEntries),
41 squashWidth(_squashWidth),
42 numInstsInROB(0),
42 squashedSeqNum(0)
43 squashedSeqNum(0),
44 numThreads(_numThreads)
43{
45{
44 doneSquashing = true;
46 for (int tid=0; tid < numThreads; tid++) {
47 doneSquashing[tid] = true;
48 threadEntries[tid] = 0;
49 }
50
51 string policy = _smtROBPolicy;
52
53 //Convert string to lowercase
54 std::transform(policy.begin(), policy.end(), policy.begin(),
55 (int(*)(int)) tolower);
56
57 //Figure out rob policy
58 if (policy == "dynamic") {
59 robPolicy = Dynamic;
60
61 //Set Max Entries to Total ROB Capacity
62 for (int i = 0; i < numThreads; i++) {
63 maxEntries[i]=numEntries;
64 }
65
66 } else if (policy == "partitioned") {
67 robPolicy = Partitioned;
68 DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
69
70 //@todo:make work if part_amt doesnt divide evenly.
71 int part_amt = numEntries / numThreads;
72
73 //Divide ROB up evenly
74 for (int i = 0; i < numThreads; i++) {
75 maxEntries[i]=part_amt;
76 }
77
78 } else if (policy == "threshold") {
79 robPolicy = Threshold;
80 DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
81
82 int threshold = _smtROBThreshold;;
83
84 //Divide up by threshold amount
85 for (int i = 0; i < numThreads; i++) {
86 maxEntries[i]=threshold;
87 }
88 } else {
89 assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
90 "Partitioned, Threshold}");
91 }
45}
46
47template <class Impl>
92}
93
94template <class Impl>
95std::string
96ROB<Impl>::name() const
97{
98 return cpu->name() + ".rob";
99}
100
101template <class Impl>
48void
49ROB<Impl>::setCPU(FullCPU *cpu_ptr)
50{
51 cpu = cpu_ptr;
52
102void
103ROB<Impl>::setCPU(FullCPU *cpu_ptr)
104{
105 cpu = cpu_ptr;
106
53 // Set the tail to the beginning of the CPU instruction list so that
54 // upon the first instruction being inserted into the ROB, the tail
55 // iterator can simply be incremented.
56 tail = cpu->instList.begin();
107 // Set the per-thread iterators to the end of the instruction list.
108 for (int i=0; i < numThreads;i++) {
109 squashIt[i] = instList[i].end();
110 }
57
111
58 // Set the squash iterator to the end of the instruction list.
59 squashIt = cpu->instList.end();
112 // Initialize the "universal" ROB head & tail point to invalid
113 // pointers
114 head = instList[0].end();
115 tail = instList[0].end();
60}
61
62template <class Impl>
116}
117
118template <class Impl>
63int
64ROB<Impl>::countInsts()
119void
120ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
65{
121{
66 // Start at 1; if the tail matches cpu->instList.begin(), then there is
67 // one inst in the ROB.
68 int return_val = 1;
122 DPRINTF(ROB, "Setting active threads list pointer.\n");
123 activeThreads = at_ptr;
124}
69
125
70 // There are quite a few special cases. Do not use this function other
71 // than for debugging purposes.
72 if (cpu->instList.begin() == cpu->instList.end()) {
73 // In this case there are no instructions in the list. The ROB
74 // must be empty.
75 return 0;
76 } else if (tail == cpu->instList.end()) {
77 // In this case, the tail is not yet pointing to anything valid.
78 // The ROB must be empty.
79 return 0;
126template <class Impl>
127void
128ROB<Impl>::switchOut()
129{
130 for (int tid = 0; tid < numThreads; tid++) {
131 instList[tid].clear();
80 }
132 }
133}
81
134
82 // Iterate through the ROB from the head to the tail, counting the
83 // entries.
84 for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
85 {
86 assert(i != cpu->instList.end());
87 ++return_val;
135template <class Impl>
136void
137ROB<Impl>::takeOverFrom()
138{
139 for (int tid=0; tid < numThreads; tid++) {
140 doneSquashing[tid] = true;
141 threadEntries[tid] = 0;
142 squashIt[tid] = instList[tid].end();
88 }
143 }
144 numInstsInROB = 0;
89
145
90 return return_val;
146 // Initialize the "universal" ROB head & tail point to invalid
147 // pointers
148 head = instList[0].end();
149 tail = instList[0].end();
150}
91
151
92 // Because the head won't be tracked properly until the ROB gets the
93 // first instruction, and any time that the ROB is empty and has not
94 // yet gotten the instruction, this function doesn't work.
95// return numInstsInROB;
152template <class Impl>
153void
154ROB<Impl>::resetEntries()
155{
156 if (robPolicy != Dynamic || numThreads > 1) {
157 int active_threads = (*activeThreads).size();
158
159 list<unsigned>::iterator threads = (*activeThreads).begin();
160 list<unsigned>::iterator list_end = (*activeThreads).end();
161
162 while (threads != list_end) {
163 if (robPolicy == Partitioned) {
164 maxEntries[*threads++] = numEntries / active_threads;
165 } else if (robPolicy == Threshold && active_threads == 1) {
166 maxEntries[*threads++] = numEntries;
167 }
168 }
169 }
96}
97
98template <class Impl>
170}
171
172template <class Impl>
173int
174ROB<Impl>::entryAmount(int num_threads)
175{
176 if (robPolicy == Partitioned) {
177 return numEntries / num_threads;
178 } else {
179 return 0;
180 }
181}
182
183template <class Impl>
184int
185ROB<Impl>::countInsts()
186{
187 int total=0;
188
189 for (int i=0;i < numThreads;i++)
190 total += countInsts(i);
191
192 return total;
193}
194
195template <class Impl>
196int
197ROB<Impl>::countInsts(unsigned tid)
198{
199 return instList[tid].size();
200}
201
202template <class Impl>
99void
100ROB<Impl>::insertInst(DynInstPtr &inst)
101{
203void
204ROB<Impl>::insertInst(DynInstPtr &inst)
205{
102 // Make sure we have the right number of instructions.
103 assert(numInstsInROB == countInsts());
104 // Make sure the instruction is valid.
206 //assert(numInstsInROB == countInsts());
105 assert(inst);
106
207 assert(inst);
208
107 DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
209 DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
108
210
109 // If the ROB is full then exit.
110 assert(numInstsInROB != numEntries);
111
211 assert(numInstsInROB != numEntries);
212
112 ++numInstsInROB;
213 int tid = inst->threadNumber;
113
214
114 // Increment the tail iterator, moving it one instruction back.
115 // There is a special case if the ROB was empty prior to this insertion,
116 // in which case the tail will be pointing at instList.end(). If that
117 // happens, then reset the tail to the beginning of the list.
118 if (tail != cpu->instList.end()) {
119 ++tail;
120 } else {
121 tail = cpu->instList.begin();
215 instList[tid].push_back(inst);
216
217 //Set Up head iterator if this is the 1st instruction in the ROB
218 if (numInstsInROB == 0) {
219 head = instList[tid].begin();
220 assert((*head) == inst);
122 }
123
221 }
222
124 // Make sure the tail iterator is actually pointing at the instruction
125 // added.
126 assert((*tail) == inst);
223 //Must Decrement for iterator to actually be valid since __.end()
224 //actually points to 1 after the last inst
225 tail = instList[tid].end();
226 tail--;
127
227
128 DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
228 inst->setInROB();
129
229
230 ++numInstsInROB;
231 ++threadEntries[tid];
232
233 assert((*tail) == inst);
234
235 DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
130}
131
132// Whatever calls this function needs to ensure that it properly frees up
133// registers prior to this function.
236}
237
238// Whatever calls this function needs to ensure that it properly frees up
239// registers prior to this function.
240/*
134template <class Impl>
135void
136ROB<Impl>::retireHead()
137{
241template <class Impl>
242void
243ROB<Impl>::retireHead()
244{
138 assert(numInstsInROB == countInsts());
245 //assert(numInstsInROB == countInsts());
139 assert(numInstsInROB > 0);
140
246 assert(numInstsInROB > 0);
247
248 int tid = (*head)->threadNumber;
249
250 retireHead(tid);
251
252 if (numInstsInROB == 0) {
253 tail = instList[tid].end();
254 }
255}
256*/
257
258template <class Impl>
259void
260ROB<Impl>::retireHead(unsigned tid)
261{
262 //assert(numInstsInROB == countInsts());
263 assert(numInstsInROB > 0);
264
141 // Get the head ROB instruction.
265 // Get the head ROB instruction.
142 DynInstPtr head_inst = cpu->instList.front();
266 InstIt head_it = instList[tid].begin();
143
267
144 // Make certain this can retire.
268 DynInstPtr head_inst = (*head_it);
269
145 assert(head_inst->readyToCommit());
146
270 assert(head_inst->readyToCommit());
271
147 DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
148 "instruction PC %#x, seq num %i\n", head_inst->readPC(),
272 DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
273 "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
149 head_inst->seqNum);
150
274 head_inst->seqNum);
275
151 // Keep track of how many instructions are in the ROB.
152 --numInstsInROB;
276 --numInstsInROB;
277 --threadEntries[tid];
153
278
154 // Tell CPU to remove the instruction from the list of instructions.
155 // A special case is needed if the instruction being retired is the
156 // only instruction in the ROB; otherwise the tail iterator will become
157 // invalidated.
279 head_inst->removeInROB();
280 head_inst->setCommitted();
281
282 instList[tid].erase(head_it);
283
284 //Update "Global" Head of ROB
285 updateHead();
286
287 // @todo: A special case is needed if the instruction being
288 // retired is the only instruction in the ROB; otherwise the tail
289 // iterator will become invalidated.
158 cpu->removeFrontInst(head_inst);
290 cpu->removeFrontInst(head_inst);
291}
292/*
293template <class Impl>
294bool
295ROB<Impl>::isHeadReady()
296{
297 if (numInstsInROB != 0) {
298 return (*head)->readyToCommit();
299 }
159
300
160 if (numInstsInROB == 0) {
161 tail = cpu->instList.end();
301 return false;
302}
303*/
304template <class Impl>
305bool
306ROB<Impl>::isHeadReady(unsigned tid)
307{
308 if (threadEntries[tid] != 0) {
309 return instList[tid].front()->readyToCommit();
162 }
310 }
311
312 return false;
163}
164
165template <class Impl>
166bool
313}
314
315template <class Impl>
316bool
167ROB<Impl>::isHeadReady()
317ROB<Impl>::canCommit()
168{
318{
169 if (numInstsInROB != 0) {
170 return cpu->instList.front()->readyToCommit();
319 //@todo: set ActiveThreads through ROB or CPU
320 list<unsigned>::iterator threads = (*activeThreads).begin();
321
322 while (threads != (*activeThreads).end()) {
323 unsigned tid = *threads++;
324
325 if (isHeadReady(tid)) {
326 return true;
327 }
171 }
172
173 return false;
174}
175
176template <class Impl>
177unsigned
178ROB<Impl>::numFreeEntries()
179{
328 }
329
330 return false;
331}
332
333template <class Impl>
334unsigned
335ROB<Impl>::numFreeEntries()
336{
180 assert(numInstsInROB == countInsts());
337 //assert(numInstsInROB == countInsts());
181
182 return numEntries - numInstsInROB;
183}
184
185template <class Impl>
338
339 return numEntries - numInstsInROB;
340}
341
342template <class Impl>
343unsigned
344ROB<Impl>::numFreeEntries(unsigned tid)
345{
346 return maxEntries[tid] - threadEntries[tid];
347}
348
349template <class Impl>
186void
350void
187ROB::doSquash()
351ROB<Impl>::doSquash(unsigned tid)
188{
352{
189 DPRINTF(ROB, "ROB: Squashing instructions.\n");
353 DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
354 tid, squashedSeqNum);
190
355
191 assert(squashIt != cpu->instList.end());
356 assert(squashIt[tid] != instList[tid].end());
192
357
358 if ((*squashIt[tid])->seqNum < squashedSeqNum) {
359 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
360 tid);
361
362 squashIt[tid] = instList[tid].end();
363
364 doneSquashing[tid] = true;
365 return;
366 }
367
368 bool robTailUpdate = false;
369
193 for (int numSquashed = 0;
370 for (int numSquashed = 0;
194 numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
371 numSquashed < squashWidth &&
372 squashIt[tid] != instList[tid].end() &&
373 (*squashIt[tid])->seqNum > squashedSeqNum;
195 ++numSquashed)
196 {
374 ++numSquashed)
375 {
197 // Ensure that the instruction is younger.
198 assert((*squashIt)->seqNum > squashedSeqNum);
376 DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
377 (*squashIt[tid])->threadNumber,
378 (*squashIt[tid])->readPC(),
379 (*squashIt[tid])->seqNum);
199
380
200 DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
201 (*squashIt)->readPC(), (*squashIt)->seqNum);
202
203 // Mark the instruction as squashed, and ready to commit so that
204 // it can drain out of the pipeline.
381 // Mark the instruction as squashed, and ready to commit so that
382 // it can drain out of the pipeline.
205 (*squashIt)->setSquashed();
383 (*squashIt[tid])->setSquashed();
206
384
207 (*squashIt)->setCanCommit();
385 (*squashIt[tid])->setCanCommit();
208
386
209 // Special case for when squashing due to a syscall. It's possible
210 // that the squash happened after the head instruction was already
211 // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
212 // will never be false. Normally the squash would never be able
213 // to go past the head of the ROB; in this case it might, so it
214 // must be handled otherwise it will segfault.
215#if !FULL_SYSTEM
216 if (squashIt == cpu->instList.begin()) {
217 DPRINTF(ROB, "ROB: Reached head of instruction list while "
387
388 if (squashIt[tid] == instList[tid].begin()) {
389 DPRINTF(ROB, "Reached head of instruction list while "
218 "squashing.\n");
219
390 "squashing.\n");
391
220 squashIt = cpu->instList.end();
392 squashIt[tid] = instList[tid].end();
221
393
222 doneSquashing = true;
394 doneSquashing[tid] = true;
223
224 return;
225 }
395
396 return;
397 }
226#endif
227
398
228 // Move the tail iterator to the next instruction.
229 squashIt--;
399 InstIt tail_thread = instList[tid].end();
400 tail_thread--;
401
402 if ((*squashIt[tid]) == (*tail_thread))
403 robTailUpdate = true;
404
405 squashIt[tid]--;
230 }
231
232
233 // Check if ROB is done squashing.
406 }
407
408
409 // Check if ROB is done squashing.
234 if ((*squashIt)->seqNum == squashedSeqNum) {
235 DPRINTF(ROB, "ROB: Done squashing instructions.\n");
410 if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
411 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
412 tid);
236
413
237 squashIt = cpu->instList.end();
414 squashIt[tid] = instList[tid].end();
238
415
239 doneSquashing = true;
416 doneSquashing[tid] = true;
240 }
417 }
418
419 if (robTailUpdate) {
420 updateTail();
421 }
241}
242
422}
423
424
243template <class Impl>
244void
425template <class Impl>
426void
245ROB<Impl>::squash(InstSeqNum squash_num)
427ROB<Impl>::updateHead()
246{
428{
247 DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
248 doneSquashing = false;
429 DynInstPtr head_inst;
430 InstSeqNum lowest_num = 0;
431 bool first_valid = true;
249
432
433 // @todo: set ActiveThreads through ROB or CPU
434 list<unsigned>::iterator threads = (*activeThreads).begin();
435
436 while (threads != (*activeThreads).end()) {
437 unsigned thread_num = *threads++;
438
439 if (instList[thread_num].empty())
440 continue;
441
442 if (first_valid) {
443 head = instList[thread_num].begin();
444 lowest_num = (*head)->seqNum;
445 first_valid = false;
446 continue;
447 }
448
449 InstIt head_thread = instList[thread_num].begin();
450
451 DynInstPtr head_inst = (*head_thread);
452
453 assert(head_inst != 0);
454
455 if (head_inst->seqNum < lowest_num) {
456 head = head_thread;
457 lowest_num = head_inst->seqNum;
458 }
459 }
460
461 if (first_valid) {
462 head = instList[0].end();
463 }
464
465}
466
467template <class Impl>
468void
469ROB<Impl>::updateTail()
470{
471 tail = instList[0].end();
472 bool first_valid = true;
473
474 list<unsigned>::iterator threads = (*activeThreads).begin();
475
476 while (threads != (*activeThreads).end()) {
477 unsigned tid = *threads++;
478
479 if (instList[tid].empty()) {
480 continue;
481 }
482
483 // If this is the first valid then assign w/out
484 // comparison
485 if (first_valid) {
486 tail = instList[tid].end();
487 tail--;
488 first_valid = false;
489 continue;
490 }
491
492 // Assign new tail if this thread's tail is younger
493 // than our current "tail high"
494 InstIt tail_thread = instList[tid].end();
495 tail_thread--;
496
497 if ((*tail_thread)->seqNum > (*tail)->seqNum) {
498 tail = tail_thread;
499 }
500 }
501}
502
503
504template <class Impl>
505void
506ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
507{
508 if (isEmpty()) {
509 DPRINTF(ROB, "Does not need to squash due to being empty "
510 "[sn:%i]\n",
511 squash_num);
512
513 return;
514 }
515
516 DPRINTF(ROB, "Starting to squash within the ROB.\n");
517
518 robStatus[tid] = ROBSquashing;
519
520 doneSquashing[tid] = false;
521
250 squashedSeqNum = squash_num;
251
522 squashedSeqNum = squash_num;
523
252 assert(tail != cpu->instList.end());
524 if (!instList[tid].empty()) {
525 InstIt tail_thread = instList[tid].end();
526 tail_thread--;
253
527
254 squashIt = tail;
528 squashIt[tid] = tail_thread;
255
529
256 doSquash();
530 doSquash(tid);
531 }
257}
532}
533/*
534template <class Impl>
535typename Impl::DynInstPtr
536ROB<Impl>::readHeadInst()
537{
538 if (numInstsInROB != 0) {
539 assert((*head)->isInROB()==true);
540 return *head;
541 } else {
542 return dummyInst;
543 }
544}
545*/
546template <class Impl>
547typename Impl::DynInstPtr
548ROB<Impl>::readHeadInst(unsigned tid)
549{
550 if (threadEntries[tid] != 0) {
551 InstIt head_thread = instList[tid].begin();
258
552
553 assert((*head_thread)->isInROB()==true);
554
555 return *head_thread;
556 } else {
557 return dummyInst;
558 }
559}
560/*
259template <class Impl>
260uint64_t
261ROB<Impl>::readHeadPC()
262{
561template <class Impl>
562uint64_t
563ROB<Impl>::readHeadPC()
564{
263 assert(numInstsInROB == countInsts());
565 //assert(numInstsInROB == countInsts());
264
566
265 DynInstPtr head_inst = cpu->instList.front();
567 DynInstPtr head_inst = *head;
266
267 return head_inst->readPC();
268}
269
270template <class Impl>
271uint64_t
568
569 return head_inst->readPC();
570}
571
572template <class Impl>
573uint64_t
574ROB<Impl>::readHeadPC(unsigned tid)
575{
576 //assert(numInstsInROB == countInsts());
577 InstIt head_thread = instList[tid].begin();
578
579 return (*head_thread)->readPC();
580}
581
582
583template <class Impl>
584uint64_t
272ROB<Impl>::readHeadNextPC()
273{
585ROB<Impl>::readHeadNextPC()
586{
274 assert(numInstsInROB == countInsts());
587 //assert(numInstsInROB == countInsts());
275
588
276 DynInstPtr head_inst = cpu->instList.front();
589 DynInstPtr head_inst = *head;
277
278 return head_inst->readNextPC();
279}
280
281template <class Impl>
590
591 return head_inst->readNextPC();
592}
593
594template <class Impl>
595uint64_t
596ROB<Impl>::readHeadNextPC(unsigned tid)
597{
598 //assert(numInstsInROB == countInsts());
599 InstIt head_thread = instList[tid].begin();
600
601 return (*head_thread)->readNextPC();
602}
603
604template <class Impl>
282InstSeqNum
283ROB<Impl>::readHeadSeqNum()
284{
605InstSeqNum
606ROB<Impl>::readHeadSeqNum()
607{
285 // Return the last sequence number that has not been squashed. Other
286 // stages can use it to squash any instructions younger than the current
287 // tail.
288 DynInstPtr head_inst = cpu->instList.front();
608 //assert(numInstsInROB == countInsts());
609 DynInstPtr head_inst = *head;
289
290 return head_inst->seqNum;
291}
292
293template <class Impl>
610
611 return head_inst->seqNum;
612}
613
614template <class Impl>
615InstSeqNum
616ROB<Impl>::readHeadSeqNum(unsigned tid)
617{
618 InstIt head_thread = instList[tid].begin();
619
620 return ((*head_thread)->seqNum);
621}
622
623template <class Impl>
624typename Impl::DynInstPtr
625ROB<Impl>::readTailInst()
626{
627 //assert(numInstsInROB == countInsts());
628 //assert(tail != instList[0].end());
629
630 return (*tail);
631}
632*/
633template <class Impl>
634typename Impl::DynInstPtr
635ROB<Impl>::readTailInst(unsigned tid)
636{
637 //assert(tail_thread[tid] != instList[tid].end());
638
639 InstIt tail_thread = instList[tid].end();
640 tail_thread--;
641
642 return *tail_thread;
643}
644
645/*
646template <class Impl>
294uint64_t
295ROB<Impl>::readTailPC()
296{
647uint64_t
648ROB<Impl>::readTailPC()
649{
297 assert(numInstsInROB == countInsts());
650 //assert(numInstsInROB == countInsts());
298
651
299 assert(tail != cpu->instList.end());
652 //assert(tail != instList[0].end());
300
301 return (*tail)->readPC();
302}
303
304template <class Impl>
653
654 return (*tail)->readPC();
655}
656
657template <class Impl>
658uint64_t
659ROB<Impl>::readTailPC(unsigned tid)
660{
661 //assert(tail_thread[tid] != instList[tid].end());
662
663 InstIt tail_thread = instList[tid].end();
664 tail_thread--;
665
666 return (*tail_thread)->readPC();
667}
668
669template <class Impl>
305InstSeqNum
306ROB<Impl>::readTailSeqNum()
307{
308 // Return the last sequence number that has not been squashed. Other
309 // stages can use it to squash any instructions younger than the current
310 // tail.
311 return (*tail)->seqNum;
312}
313
670InstSeqNum
671ROB<Impl>::readTailSeqNum()
672{
673 // Return the last sequence number that has not been squashed. Other
674 // stages can use it to squash any instructions younger than the current
675 // tail.
676 return (*tail)->seqNum;
677}
678
314#endif // __CPU_O3_CPU_ROB_IMPL_HH__
679template <class Impl>
680InstSeqNum
681ROB<Impl>::readTailSeqNum(unsigned tid)
682{
683 // Return the last sequence number that has not been squashed. Other
684 // stages can use it to squash any instructions younger than the current
685 // tail.
686 // assert(tail_thread[tid] != instList[tid].end());
687
688 InstIt tail_thread = instList[tid].end();
689 tail_thread--;
690
691 return (*tail_thread)->seqNum;
692}
693*/