rob_impl.hh (2654:9559cfa91b9d) rob_impl.hh (2665:a124942bacb8)
1/*
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
2 * Copyright (c) 2004-2005 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

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

19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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.
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

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

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