rename_impl.hh (9527:68154bc0e0ea) rename_impl.hh (9531:1114ead790eb)
1/*
2 * Copyright (c) 2010-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 * Authors: Kevin Lim
41 * Korey Sewell
42 */
43
44#include <list>
45
46#include "arch/isa_traits.hh"
47#include "arch/registers.hh"
48#include "config/the_isa.hh"
49#include "cpu/o3/rename.hh"
50#include "debug/Activity.hh"
51#include "debug/Rename.hh"
52#include "debug/O3PipeView.hh"
53#include "params/DerivO3CPU.hh"
54
55using namespace std;
56
57template <class Impl>
58DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
59 : cpu(_cpu),
60 iewToRenameDelay(params->iewToRenameDelay),
61 decodeToRenameDelay(params->decodeToRenameDelay),
62 commitToRenameDelay(params->commitToRenameDelay),
63 renameWidth(params->renameWidth),
64 commitWidth(params->commitWidth),
65 numThreads(params->numThreads),
66 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs)
67{
68 // @todo: Make into a parameter.
69 skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth;
70}
71
72template <class Impl>
73std::string
74DefaultRename<Impl>::name() const
75{
76 return cpu->name() + ".rename";
77}
78
79template <class Impl>
80void
81DefaultRename<Impl>::regStats()
82{
83 renameSquashCycles
84 .name(name() + ".SquashCycles")
85 .desc("Number of cycles rename is squashing")
86 .prereq(renameSquashCycles);
87 renameIdleCycles
88 .name(name() + ".IdleCycles")
89 .desc("Number of cycles rename is idle")
90 .prereq(renameIdleCycles);
91 renameBlockCycles
92 .name(name() + ".BlockCycles")
93 .desc("Number of cycles rename is blocking")
94 .prereq(renameBlockCycles);
95 renameSerializeStallCycles
96 .name(name() + ".serializeStallCycles")
97 .desc("count of cycles rename stalled for serializing inst")
98 .flags(Stats::total);
99 renameRunCycles
100 .name(name() + ".RunCycles")
101 .desc("Number of cycles rename is running")
102 .prereq(renameIdleCycles);
103 renameUnblockCycles
104 .name(name() + ".UnblockCycles")
105 .desc("Number of cycles rename is unblocking")
106 .prereq(renameUnblockCycles);
107 renameRenamedInsts
108 .name(name() + ".RenamedInsts")
109 .desc("Number of instructions processed by rename")
110 .prereq(renameRenamedInsts);
111 renameSquashedInsts
112 .name(name() + ".SquashedInsts")
113 .desc("Number of squashed instructions processed by rename")
114 .prereq(renameSquashedInsts);
115 renameROBFullEvents
116 .name(name() + ".ROBFullEvents")
117 .desc("Number of times rename has blocked due to ROB full")
118 .prereq(renameROBFullEvents);
119 renameIQFullEvents
120 .name(name() + ".IQFullEvents")
121 .desc("Number of times rename has blocked due to IQ full")
122 .prereq(renameIQFullEvents);
123 renameLSQFullEvents
124 .name(name() + ".LSQFullEvents")
125 .desc("Number of times rename has blocked due to LSQ full")
126 .prereq(renameLSQFullEvents);
127 renameFullRegistersEvents
128 .name(name() + ".FullRegisterEvents")
129 .desc("Number of times there has been no free registers")
130 .prereq(renameFullRegistersEvents);
131 renameRenamedOperands
132 .name(name() + ".RenamedOperands")
133 .desc("Number of destination operands rename has renamed")
134 .prereq(renameRenamedOperands);
135 renameRenameLookups
136 .name(name() + ".RenameLookups")
137 .desc("Number of register rename lookups that rename has made")
138 .prereq(renameRenameLookups);
139 renameCommittedMaps
140 .name(name() + ".CommittedMaps")
141 .desc("Number of HB maps that are committed")
142 .prereq(renameCommittedMaps);
143 renameUndoneMaps
144 .name(name() + ".UndoneMaps")
145 .desc("Number of HB maps that are undone due to squashing")
146 .prereq(renameUndoneMaps);
147 renamedSerializing
148 .name(name() + ".serializingInsts")
149 .desc("count of serializing insts renamed")
150 .flags(Stats::total)
151 ;
152 renamedTempSerializing
153 .name(name() + ".tempSerializingInsts")
154 .desc("count of temporary serializing insts renamed")
155 .flags(Stats::total)
156 ;
157 renameSkidInsts
158 .name(name() + ".skidInsts")
159 .desc("count of insts added to the skid buffer")
160 .flags(Stats::total)
161 ;
162 intRenameLookups
163 .name(name() + ".int_rename_lookups")
164 .desc("Number of integer rename lookups")
165 .prereq(intRenameLookups);
166 fpRenameLookups
167 .name(name() + ".fp_rename_lookups")
168 .desc("Number of floating rename lookups")
169 .prereq(fpRenameLookups);
170}
171
172template <class Impl>
173void
174DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
175{
176 timeBuffer = tb_ptr;
177
178 // Setup wire to read information from time buffer, from IEW stage.
179 fromIEW = timeBuffer->getWire(-iewToRenameDelay);
180
181 // Setup wire to read infromation from time buffer, from commit stage.
182 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
183
184 // Setup wire to write information to previous stages.
185 toDecode = timeBuffer->getWire(0);
186}
187
188template <class Impl>
189void
190DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
191{
192 renameQueue = rq_ptr;
193
194 // Setup wire to write information to future stages.
195 toIEW = renameQueue->getWire(0);
196}
197
198template <class Impl>
199void
200DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
201{
202 decodeQueue = dq_ptr;
203
204 // Setup wire to get information from decode.
205 fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
206}
207
208template <class Impl>
209void
210DefaultRename<Impl>::startupStage()
211{
212 resetStage();
213}
214
215template <class Impl>
216void
217DefaultRename<Impl>::resetStage()
218{
219 _status = Inactive;
220
221 resumeSerialize = false;
222 resumeUnblocking = false;
223
224 // Grab the number of free entries directly from the stages.
225 for (ThreadID tid = 0; tid < numThreads; tid++) {
226 renameStatus[tid] = Idle;
227
228 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
229 freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
230 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
231 emptyROB[tid] = true;
232
233 stalls[tid].iew = false;
234 stalls[tid].commit = false;
235 serializeInst[tid] = NULL;
236
237 instsInProgress[tid] = 0;
238
239 serializeOnNextInst[tid] = false;
240 }
241}
242
243template<class Impl>
244void
245DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
246{
247 activeThreads = at_ptr;
248}
249
250
251template <class Impl>
252void
253DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
254{
255 for (ThreadID tid = 0; tid < numThreads; tid++)
256 renameMap[tid] = &rm_ptr[tid];
257}
258
259template <class Impl>
260void
261DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
262{
263 freeList = fl_ptr;
264}
265
266template<class Impl>
267void
268DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
269{
270 scoreboard = _scoreboard;
271}
272
273template <class Impl>
274bool
275DefaultRename<Impl>::isDrained() const
276{
277 for (ThreadID tid = 0; tid < numThreads; tid++) {
278 if (instsInProgress[tid] != 0 ||
279 !historyBuffer[tid].empty() ||
280 !skidBuffer[tid].empty() ||
281 !insts[tid].empty())
282 return false;
283 }
284 return true;
285}
286
287template <class Impl>
288void
289DefaultRename<Impl>::takeOverFrom()
290{
291 resetStage();
292}
293
294template <class Impl>
295void
296DefaultRename<Impl>::drainSanityCheck() const
297{
298 for (ThreadID tid = 0; tid < numThreads; tid++) {
299 assert(historyBuffer[tid].empty());
300 assert(insts[tid].empty());
301 assert(skidBuffer[tid].empty());
302 assert(instsInProgress[tid] == 0);
303 }
304}
305
306template <class Impl>
307void
308DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid)
309{
310 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
311
312 // Clear the stall signal if rename was blocked or unblocking before.
313 // If it still needs to block, the blocking should happen the next
314 // cycle and there should be space to hold everything due to the squash.
315 if (renameStatus[tid] == Blocked ||
316 renameStatus[tid] == Unblocking) {
317 toDecode->renameUnblock[tid] = 1;
318
319 resumeSerialize = false;
320 serializeInst[tid] = NULL;
321 } else if (renameStatus[tid] == SerializeStall) {
322 if (serializeInst[tid]->seqNum <= squash_seq_num) {
323 DPRINTF(Rename, "Rename will resume serializing after squash\n");
324 resumeSerialize = true;
325 assert(serializeInst[tid]);
326 } else {
327 resumeSerialize = false;
328 toDecode->renameUnblock[tid] = 1;
329
330 serializeInst[tid] = NULL;
331 }
332 }
333
334 // Set the status to Squashing.
335 renameStatus[tid] = Squashing;
336
337 // Squash any instructions from decode.
338 unsigned squashCount = 0;
339
340 for (int i=0; i<fromDecode->size; i++) {
341 if (fromDecode->insts[i]->threadNumber == tid &&
342 fromDecode->insts[i]->seqNum > squash_seq_num) {
343 fromDecode->insts[i]->setSquashed();
344 wroteToTimeBuffer = true;
345 squashCount++;
346 }
347
348 }
349
350 // Clear the instruction list and skid buffer in case they have any
351 // insts in them.
352 insts[tid].clear();
353
354 // Clear the skid buffer in case it has any data in it.
355 skidBuffer[tid].clear();
356
357 doSquash(squash_seq_num, tid);
358}
359
360template <class Impl>
361void
362DefaultRename<Impl>::tick()
363{
364 wroteToTimeBuffer = false;
365
366 blockThisCycle = false;
367
368 bool status_change = false;
369
370 toIEWIndex = 0;
371
372 sortInsts();
373
374 list<ThreadID>::iterator threads = activeThreads->begin();
375 list<ThreadID>::iterator end = activeThreads->end();
376
377 // Check stall and squash signals.
378 while (threads != end) {
379 ThreadID tid = *threads++;
380
381 DPRINTF(Rename, "Processing [tid:%i]\n", tid);
382
383 status_change = checkSignalsAndUpdate(tid) || status_change;
384
385 rename(status_change, tid);
386 }
387
388 if (status_change) {
389 updateStatus();
390 }
391
392 if (wroteToTimeBuffer) {
393 DPRINTF(Activity, "Activity this cycle.\n");
394 cpu->activityThisCycle();
395 }
396
397 threads = activeThreads->begin();
398
399 while (threads != end) {
400 ThreadID tid = *threads++;
401
402 // If we committed this cycle then doneSeqNum will be > 0
403 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
404 !fromCommit->commitInfo[tid].squash &&
405 renameStatus[tid] != Squashing) {
406
407 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
408 tid);
409 }
410 }
411
412 // @todo: make into updateProgress function
413 for (ThreadID tid = 0; tid < numThreads; tid++) {
414 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
415
416 assert(instsInProgress[tid] >=0);
417 }
418
419}
420
421template<class Impl>
422void
423DefaultRename<Impl>::rename(bool &status_change, ThreadID tid)
424{
425 // If status is Running or idle,
426 // call renameInsts()
427 // If status is Unblocking,
428 // buffer any instructions coming from decode
429 // continue trying to empty skid buffer
430 // check if stall conditions have passed
431
432 if (renameStatus[tid] == Blocked) {
433 ++renameBlockCycles;
434 } else if (renameStatus[tid] == Squashing) {
435 ++renameSquashCycles;
436 } else if (renameStatus[tid] == SerializeStall) {
437 ++renameSerializeStallCycles;
438 // If we are currently in SerializeStall and resumeSerialize
439 // was set, then that means that we are resuming serializing
440 // this cycle. Tell the previous stages to block.
441 if (resumeSerialize) {
442 resumeSerialize = false;
443 block(tid);
444 toDecode->renameUnblock[tid] = false;
445 }
446 } else if (renameStatus[tid] == Unblocking) {
447 if (resumeUnblocking) {
448 block(tid);
449 resumeUnblocking = false;
450 toDecode->renameUnblock[tid] = false;
451 }
452 }
453
454 if (renameStatus[tid] == Running ||
455 renameStatus[tid] == Idle) {
456 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
457 "stage.\n", tid);
458
459 renameInsts(tid);
460 } else if (renameStatus[tid] == Unblocking) {
461 renameInsts(tid);
462
463 if (validInsts()) {
464 // Add the current inputs to the skid buffer so they can be
465 // reprocessed when this stage unblocks.
466 skidInsert(tid);
467 }
468
469 // If we switched over to blocking, then there's a potential for
470 // an overall status change.
471 status_change = unblock(tid) || status_change || blockThisCycle;
472 }
473}
474
475template <class Impl>
476void
477DefaultRename<Impl>::renameInsts(ThreadID tid)
478{
479 // Instructions can be either in the skid buffer or the queue of
480 // instructions coming from decode, depending on the status.
481 int insts_available = renameStatus[tid] == Unblocking ?
482 skidBuffer[tid].size() : insts[tid].size();
483
484 // Check the decode queue to see if instructions are available.
485 // If there are no available instructions to rename, then do nothing.
486 if (insts_available == 0) {
487 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
488 tid);
489 // Should I change status to idle?
490 ++renameIdleCycles;
491 return;
492 } else if (renameStatus[tid] == Unblocking) {
493 ++renameUnblockCycles;
494 } else if (renameStatus[tid] == Running) {
495 ++renameRunCycles;
496 }
497
498 DynInstPtr inst;
499
500 // Will have to do a different calculation for the number of free
501 // entries.
502 int free_rob_entries = calcFreeROBEntries(tid);
503 int free_iq_entries = calcFreeIQEntries(tid);
504 int free_lsq_entries = calcFreeLSQEntries(tid);
505 int min_free_entries = free_rob_entries;
506
507 FullSource source = ROB;
508
509 if (free_iq_entries < min_free_entries) {
510 min_free_entries = free_iq_entries;
511 source = IQ;
512 }
513
514 if (free_lsq_entries < min_free_entries) {
515 min_free_entries = free_lsq_entries;
516 source = LSQ;
517 }
518
519 // Check if there's any space left.
520 if (min_free_entries <= 0) {
521 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
522 "entries.\n"
523 "ROB has %i free entries.\n"
524 "IQ has %i free entries.\n"
525 "LSQ has %i free entries.\n",
526 tid,
527 free_rob_entries,
528 free_iq_entries,
529 free_lsq_entries);
530
531 blockThisCycle = true;
532
533 block(tid);
534
535 incrFullStat(source);
536
537 return;
538 } else if (min_free_entries < insts_available) {
539 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
540 "%i insts available, but only %i insts can be "
541 "renamed due to ROB/IQ/LSQ limits.\n",
542 tid, insts_available, min_free_entries);
543
544 insts_available = min_free_entries;
545
546 blockThisCycle = true;
547
548 incrFullStat(source);
549 }
550
551 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
552 skidBuffer[tid] : insts[tid];
553
554 DPRINTF(Rename, "[tid:%u]: %i available instructions to "
555 "send iew.\n", tid, insts_available);
556
557 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
558 "dispatched to IQ last cycle.\n",
559 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
560
561 // Handle serializing the next instruction if necessary.
562 if (serializeOnNextInst[tid]) {
563 if (emptyROB[tid] && instsInProgress[tid] == 0) {
564 // ROB already empty; no need to serialize.
565 serializeOnNextInst[tid] = false;
566 } else if (!insts_to_rename.empty()) {
567 insts_to_rename.front()->setSerializeBefore();
568 }
569 }
570
571 int renamed_insts = 0;
572
573 while (insts_available > 0 && toIEWIndex < renameWidth) {
574 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
575
576 assert(!insts_to_rename.empty());
577
578 inst = insts_to_rename.front();
579
580 insts_to_rename.pop_front();
581
582 if (renameStatus[tid] == Unblocking) {
583 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
584 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
585 }
586
587 if (inst->isSquashed()) {
588 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
589 "squashed, skipping.\n", tid, inst->seqNum,
590 inst->pcState());
591
592 ++renameSquashedInsts;
593
594 // Decrement how many instructions are available.
595 --insts_available;
596
597 continue;
598 }
599
600 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
601 "PC %s.\n", tid, inst->seqNum, inst->pcState());
602
1/*
2 * Copyright (c) 2010-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 * Authors: Kevin Lim
41 * Korey Sewell
42 */
43
44#include <list>
45
46#include "arch/isa_traits.hh"
47#include "arch/registers.hh"
48#include "config/the_isa.hh"
49#include "cpu/o3/rename.hh"
50#include "debug/Activity.hh"
51#include "debug/Rename.hh"
52#include "debug/O3PipeView.hh"
53#include "params/DerivO3CPU.hh"
54
55using namespace std;
56
57template <class Impl>
58DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params)
59 : cpu(_cpu),
60 iewToRenameDelay(params->iewToRenameDelay),
61 decodeToRenameDelay(params->decodeToRenameDelay),
62 commitToRenameDelay(params->commitToRenameDelay),
63 renameWidth(params->renameWidth),
64 commitWidth(params->commitWidth),
65 numThreads(params->numThreads),
66 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs)
67{
68 // @todo: Make into a parameter.
69 skidBufferMax = (2 * (decodeToRenameDelay * params->decodeWidth)) + renameWidth;
70}
71
72template <class Impl>
73std::string
74DefaultRename<Impl>::name() const
75{
76 return cpu->name() + ".rename";
77}
78
79template <class Impl>
80void
81DefaultRename<Impl>::regStats()
82{
83 renameSquashCycles
84 .name(name() + ".SquashCycles")
85 .desc("Number of cycles rename is squashing")
86 .prereq(renameSquashCycles);
87 renameIdleCycles
88 .name(name() + ".IdleCycles")
89 .desc("Number of cycles rename is idle")
90 .prereq(renameIdleCycles);
91 renameBlockCycles
92 .name(name() + ".BlockCycles")
93 .desc("Number of cycles rename is blocking")
94 .prereq(renameBlockCycles);
95 renameSerializeStallCycles
96 .name(name() + ".serializeStallCycles")
97 .desc("count of cycles rename stalled for serializing inst")
98 .flags(Stats::total);
99 renameRunCycles
100 .name(name() + ".RunCycles")
101 .desc("Number of cycles rename is running")
102 .prereq(renameIdleCycles);
103 renameUnblockCycles
104 .name(name() + ".UnblockCycles")
105 .desc("Number of cycles rename is unblocking")
106 .prereq(renameUnblockCycles);
107 renameRenamedInsts
108 .name(name() + ".RenamedInsts")
109 .desc("Number of instructions processed by rename")
110 .prereq(renameRenamedInsts);
111 renameSquashedInsts
112 .name(name() + ".SquashedInsts")
113 .desc("Number of squashed instructions processed by rename")
114 .prereq(renameSquashedInsts);
115 renameROBFullEvents
116 .name(name() + ".ROBFullEvents")
117 .desc("Number of times rename has blocked due to ROB full")
118 .prereq(renameROBFullEvents);
119 renameIQFullEvents
120 .name(name() + ".IQFullEvents")
121 .desc("Number of times rename has blocked due to IQ full")
122 .prereq(renameIQFullEvents);
123 renameLSQFullEvents
124 .name(name() + ".LSQFullEvents")
125 .desc("Number of times rename has blocked due to LSQ full")
126 .prereq(renameLSQFullEvents);
127 renameFullRegistersEvents
128 .name(name() + ".FullRegisterEvents")
129 .desc("Number of times there has been no free registers")
130 .prereq(renameFullRegistersEvents);
131 renameRenamedOperands
132 .name(name() + ".RenamedOperands")
133 .desc("Number of destination operands rename has renamed")
134 .prereq(renameRenamedOperands);
135 renameRenameLookups
136 .name(name() + ".RenameLookups")
137 .desc("Number of register rename lookups that rename has made")
138 .prereq(renameRenameLookups);
139 renameCommittedMaps
140 .name(name() + ".CommittedMaps")
141 .desc("Number of HB maps that are committed")
142 .prereq(renameCommittedMaps);
143 renameUndoneMaps
144 .name(name() + ".UndoneMaps")
145 .desc("Number of HB maps that are undone due to squashing")
146 .prereq(renameUndoneMaps);
147 renamedSerializing
148 .name(name() + ".serializingInsts")
149 .desc("count of serializing insts renamed")
150 .flags(Stats::total)
151 ;
152 renamedTempSerializing
153 .name(name() + ".tempSerializingInsts")
154 .desc("count of temporary serializing insts renamed")
155 .flags(Stats::total)
156 ;
157 renameSkidInsts
158 .name(name() + ".skidInsts")
159 .desc("count of insts added to the skid buffer")
160 .flags(Stats::total)
161 ;
162 intRenameLookups
163 .name(name() + ".int_rename_lookups")
164 .desc("Number of integer rename lookups")
165 .prereq(intRenameLookups);
166 fpRenameLookups
167 .name(name() + ".fp_rename_lookups")
168 .desc("Number of floating rename lookups")
169 .prereq(fpRenameLookups);
170}
171
172template <class Impl>
173void
174DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
175{
176 timeBuffer = tb_ptr;
177
178 // Setup wire to read information from time buffer, from IEW stage.
179 fromIEW = timeBuffer->getWire(-iewToRenameDelay);
180
181 // Setup wire to read infromation from time buffer, from commit stage.
182 fromCommit = timeBuffer->getWire(-commitToRenameDelay);
183
184 // Setup wire to write information to previous stages.
185 toDecode = timeBuffer->getWire(0);
186}
187
188template <class Impl>
189void
190DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
191{
192 renameQueue = rq_ptr;
193
194 // Setup wire to write information to future stages.
195 toIEW = renameQueue->getWire(0);
196}
197
198template <class Impl>
199void
200DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
201{
202 decodeQueue = dq_ptr;
203
204 // Setup wire to get information from decode.
205 fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
206}
207
208template <class Impl>
209void
210DefaultRename<Impl>::startupStage()
211{
212 resetStage();
213}
214
215template <class Impl>
216void
217DefaultRename<Impl>::resetStage()
218{
219 _status = Inactive;
220
221 resumeSerialize = false;
222 resumeUnblocking = false;
223
224 // Grab the number of free entries directly from the stages.
225 for (ThreadID tid = 0; tid < numThreads; tid++) {
226 renameStatus[tid] = Idle;
227
228 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
229 freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
230 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
231 emptyROB[tid] = true;
232
233 stalls[tid].iew = false;
234 stalls[tid].commit = false;
235 serializeInst[tid] = NULL;
236
237 instsInProgress[tid] = 0;
238
239 serializeOnNextInst[tid] = false;
240 }
241}
242
243template<class Impl>
244void
245DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
246{
247 activeThreads = at_ptr;
248}
249
250
251template <class Impl>
252void
253DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
254{
255 for (ThreadID tid = 0; tid < numThreads; tid++)
256 renameMap[tid] = &rm_ptr[tid];
257}
258
259template <class Impl>
260void
261DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
262{
263 freeList = fl_ptr;
264}
265
266template<class Impl>
267void
268DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
269{
270 scoreboard = _scoreboard;
271}
272
273template <class Impl>
274bool
275DefaultRename<Impl>::isDrained() const
276{
277 for (ThreadID tid = 0; tid < numThreads; tid++) {
278 if (instsInProgress[tid] != 0 ||
279 !historyBuffer[tid].empty() ||
280 !skidBuffer[tid].empty() ||
281 !insts[tid].empty())
282 return false;
283 }
284 return true;
285}
286
287template <class Impl>
288void
289DefaultRename<Impl>::takeOverFrom()
290{
291 resetStage();
292}
293
294template <class Impl>
295void
296DefaultRename<Impl>::drainSanityCheck() const
297{
298 for (ThreadID tid = 0; tid < numThreads; tid++) {
299 assert(historyBuffer[tid].empty());
300 assert(insts[tid].empty());
301 assert(skidBuffer[tid].empty());
302 assert(instsInProgress[tid] == 0);
303 }
304}
305
306template <class Impl>
307void
308DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid)
309{
310 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
311
312 // Clear the stall signal if rename was blocked or unblocking before.
313 // If it still needs to block, the blocking should happen the next
314 // cycle and there should be space to hold everything due to the squash.
315 if (renameStatus[tid] == Blocked ||
316 renameStatus[tid] == Unblocking) {
317 toDecode->renameUnblock[tid] = 1;
318
319 resumeSerialize = false;
320 serializeInst[tid] = NULL;
321 } else if (renameStatus[tid] == SerializeStall) {
322 if (serializeInst[tid]->seqNum <= squash_seq_num) {
323 DPRINTF(Rename, "Rename will resume serializing after squash\n");
324 resumeSerialize = true;
325 assert(serializeInst[tid]);
326 } else {
327 resumeSerialize = false;
328 toDecode->renameUnblock[tid] = 1;
329
330 serializeInst[tid] = NULL;
331 }
332 }
333
334 // Set the status to Squashing.
335 renameStatus[tid] = Squashing;
336
337 // Squash any instructions from decode.
338 unsigned squashCount = 0;
339
340 for (int i=0; i<fromDecode->size; i++) {
341 if (fromDecode->insts[i]->threadNumber == tid &&
342 fromDecode->insts[i]->seqNum > squash_seq_num) {
343 fromDecode->insts[i]->setSquashed();
344 wroteToTimeBuffer = true;
345 squashCount++;
346 }
347
348 }
349
350 // Clear the instruction list and skid buffer in case they have any
351 // insts in them.
352 insts[tid].clear();
353
354 // Clear the skid buffer in case it has any data in it.
355 skidBuffer[tid].clear();
356
357 doSquash(squash_seq_num, tid);
358}
359
360template <class Impl>
361void
362DefaultRename<Impl>::tick()
363{
364 wroteToTimeBuffer = false;
365
366 blockThisCycle = false;
367
368 bool status_change = false;
369
370 toIEWIndex = 0;
371
372 sortInsts();
373
374 list<ThreadID>::iterator threads = activeThreads->begin();
375 list<ThreadID>::iterator end = activeThreads->end();
376
377 // Check stall and squash signals.
378 while (threads != end) {
379 ThreadID tid = *threads++;
380
381 DPRINTF(Rename, "Processing [tid:%i]\n", tid);
382
383 status_change = checkSignalsAndUpdate(tid) || status_change;
384
385 rename(status_change, tid);
386 }
387
388 if (status_change) {
389 updateStatus();
390 }
391
392 if (wroteToTimeBuffer) {
393 DPRINTF(Activity, "Activity this cycle.\n");
394 cpu->activityThisCycle();
395 }
396
397 threads = activeThreads->begin();
398
399 while (threads != end) {
400 ThreadID tid = *threads++;
401
402 // If we committed this cycle then doneSeqNum will be > 0
403 if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
404 !fromCommit->commitInfo[tid].squash &&
405 renameStatus[tid] != Squashing) {
406
407 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
408 tid);
409 }
410 }
411
412 // @todo: make into updateProgress function
413 for (ThreadID tid = 0; tid < numThreads; tid++) {
414 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
415
416 assert(instsInProgress[tid] >=0);
417 }
418
419}
420
421template<class Impl>
422void
423DefaultRename<Impl>::rename(bool &status_change, ThreadID tid)
424{
425 // If status is Running or idle,
426 // call renameInsts()
427 // If status is Unblocking,
428 // buffer any instructions coming from decode
429 // continue trying to empty skid buffer
430 // check if stall conditions have passed
431
432 if (renameStatus[tid] == Blocked) {
433 ++renameBlockCycles;
434 } else if (renameStatus[tid] == Squashing) {
435 ++renameSquashCycles;
436 } else if (renameStatus[tid] == SerializeStall) {
437 ++renameSerializeStallCycles;
438 // If we are currently in SerializeStall and resumeSerialize
439 // was set, then that means that we are resuming serializing
440 // this cycle. Tell the previous stages to block.
441 if (resumeSerialize) {
442 resumeSerialize = false;
443 block(tid);
444 toDecode->renameUnblock[tid] = false;
445 }
446 } else if (renameStatus[tid] == Unblocking) {
447 if (resumeUnblocking) {
448 block(tid);
449 resumeUnblocking = false;
450 toDecode->renameUnblock[tid] = false;
451 }
452 }
453
454 if (renameStatus[tid] == Running ||
455 renameStatus[tid] == Idle) {
456 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
457 "stage.\n", tid);
458
459 renameInsts(tid);
460 } else if (renameStatus[tid] == Unblocking) {
461 renameInsts(tid);
462
463 if (validInsts()) {
464 // Add the current inputs to the skid buffer so they can be
465 // reprocessed when this stage unblocks.
466 skidInsert(tid);
467 }
468
469 // If we switched over to blocking, then there's a potential for
470 // an overall status change.
471 status_change = unblock(tid) || status_change || blockThisCycle;
472 }
473}
474
475template <class Impl>
476void
477DefaultRename<Impl>::renameInsts(ThreadID tid)
478{
479 // Instructions can be either in the skid buffer or the queue of
480 // instructions coming from decode, depending on the status.
481 int insts_available = renameStatus[tid] == Unblocking ?
482 skidBuffer[tid].size() : insts[tid].size();
483
484 // Check the decode queue to see if instructions are available.
485 // If there are no available instructions to rename, then do nothing.
486 if (insts_available == 0) {
487 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
488 tid);
489 // Should I change status to idle?
490 ++renameIdleCycles;
491 return;
492 } else if (renameStatus[tid] == Unblocking) {
493 ++renameUnblockCycles;
494 } else if (renameStatus[tid] == Running) {
495 ++renameRunCycles;
496 }
497
498 DynInstPtr inst;
499
500 // Will have to do a different calculation for the number of free
501 // entries.
502 int free_rob_entries = calcFreeROBEntries(tid);
503 int free_iq_entries = calcFreeIQEntries(tid);
504 int free_lsq_entries = calcFreeLSQEntries(tid);
505 int min_free_entries = free_rob_entries;
506
507 FullSource source = ROB;
508
509 if (free_iq_entries < min_free_entries) {
510 min_free_entries = free_iq_entries;
511 source = IQ;
512 }
513
514 if (free_lsq_entries < min_free_entries) {
515 min_free_entries = free_lsq_entries;
516 source = LSQ;
517 }
518
519 // Check if there's any space left.
520 if (min_free_entries <= 0) {
521 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
522 "entries.\n"
523 "ROB has %i free entries.\n"
524 "IQ has %i free entries.\n"
525 "LSQ has %i free entries.\n",
526 tid,
527 free_rob_entries,
528 free_iq_entries,
529 free_lsq_entries);
530
531 blockThisCycle = true;
532
533 block(tid);
534
535 incrFullStat(source);
536
537 return;
538 } else if (min_free_entries < insts_available) {
539 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
540 "%i insts available, but only %i insts can be "
541 "renamed due to ROB/IQ/LSQ limits.\n",
542 tid, insts_available, min_free_entries);
543
544 insts_available = min_free_entries;
545
546 blockThisCycle = true;
547
548 incrFullStat(source);
549 }
550
551 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
552 skidBuffer[tid] : insts[tid];
553
554 DPRINTF(Rename, "[tid:%u]: %i available instructions to "
555 "send iew.\n", tid, insts_available);
556
557 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
558 "dispatched to IQ last cycle.\n",
559 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
560
561 // Handle serializing the next instruction if necessary.
562 if (serializeOnNextInst[tid]) {
563 if (emptyROB[tid] && instsInProgress[tid] == 0) {
564 // ROB already empty; no need to serialize.
565 serializeOnNextInst[tid] = false;
566 } else if (!insts_to_rename.empty()) {
567 insts_to_rename.front()->setSerializeBefore();
568 }
569 }
570
571 int renamed_insts = 0;
572
573 while (insts_available > 0 && toIEWIndex < renameWidth) {
574 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
575
576 assert(!insts_to_rename.empty());
577
578 inst = insts_to_rename.front();
579
580 insts_to_rename.pop_front();
581
582 if (renameStatus[tid] == Unblocking) {
583 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
584 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
585 }
586
587 if (inst->isSquashed()) {
588 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
589 "squashed, skipping.\n", tid, inst->seqNum,
590 inst->pcState());
591
592 ++renameSquashedInsts;
593
594 // Decrement how many instructions are available.
595 --insts_available;
596
597 continue;
598 }
599
600 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
601 "PC %s.\n", tid, inst->seqNum, inst->pcState());
602
603 // Check here to make sure there are enough destination registers
604 // to rename to. Otherwise block.
605 if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
606 DPRINTF(Rename, "Blocking due to lack of free "
607 "physical registers to rename to.\n");
608 blockThisCycle = true;
609 insts_to_rename.push_front(inst);
610 ++renameFullRegistersEvents;
611
612 break;
613 }
614
603 // Handle serializeAfter/serializeBefore instructions.
604 // serializeAfter marks the next instruction as serializeBefore.
605 // serializeBefore makes the instruction wait in rename until the ROB
606 // is empty.
607
608 // In this model, IPR accesses are serialize before
609 // instructions, and store conditionals are serialize after
610 // instructions. This is mainly due to lack of support for
611 // out-of-order operations of either of those classes of
612 // instructions.
613 if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
614 !inst->isSerializeHandled()) {
615 DPRINTF(Rename, "Serialize before instruction encountered.\n");
616
617 if (!inst->isTempSerializeBefore()) {
618 renamedSerializing++;
619 inst->setSerializeHandled();
620 } else {
621 renamedTempSerializing++;
622 }
623
624 // Change status over to SerializeStall so that other stages know
625 // what this is blocked on.
626 renameStatus[tid] = SerializeStall;
627
628 serializeInst[tid] = inst;
629
630 blockThisCycle = true;
631
632 break;
633 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
634 !inst->isSerializeHandled()) {
635 DPRINTF(Rename, "Serialize after instruction encountered.\n");
636
637 renamedSerializing++;
638
639 inst->setSerializeHandled();
640
641 serializeAfter(insts_to_rename, tid);
642 }
643
615 // Handle serializeAfter/serializeBefore instructions.
616 // serializeAfter marks the next instruction as serializeBefore.
617 // serializeBefore makes the instruction wait in rename until the ROB
618 // is empty.
619
620 // In this model, IPR accesses are serialize before
621 // instructions, and store conditionals are serialize after
622 // instructions. This is mainly due to lack of support for
623 // out-of-order operations of either of those classes of
624 // instructions.
625 if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
626 !inst->isSerializeHandled()) {
627 DPRINTF(Rename, "Serialize before instruction encountered.\n");
628
629 if (!inst->isTempSerializeBefore()) {
630 renamedSerializing++;
631 inst->setSerializeHandled();
632 } else {
633 renamedTempSerializing++;
634 }
635
636 // Change status over to SerializeStall so that other stages know
637 // what this is blocked on.
638 renameStatus[tid] = SerializeStall;
639
640 serializeInst[tid] = inst;
641
642 blockThisCycle = true;
643
644 break;
645 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
646 !inst->isSerializeHandled()) {
647 DPRINTF(Rename, "Serialize after instruction encountered.\n");
648
649 renamedSerializing++;
650
651 inst->setSerializeHandled();
652
653 serializeAfter(insts_to_rename, tid);
654 }
655
644 // Check here to make sure there are enough destination registers
645 // to rename to. Otherwise block.
646 if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
647 DPRINTF(Rename, "Blocking due to lack of free "
648 "physical registers to rename to.\n");
649 blockThisCycle = true;
650 insts_to_rename.push_front(inst);
651 ++renameFullRegistersEvents;
652
653 break;
654 }
655
656 renameSrcRegs(inst, inst->threadNumber);
657
658 renameDestRegs(inst, inst->threadNumber);
659
660 ++renamed_insts;
661
662
663 // Put instruction in rename queue.
664 toIEW->insts[toIEWIndex] = inst;
665 ++(toIEW->size);
666
667 // Increment which instruction we're on.
668 ++toIEWIndex;
669
670 // Decrement how many instructions are available.
671 --insts_available;
672 }
673
674 instsInProgress[tid] += renamed_insts;
675 renameRenamedInsts += renamed_insts;
676
677 // If we wrote to the time buffer, record this.
678 if (toIEWIndex) {
679 wroteToTimeBuffer = true;
680 }
681
682 // Check if there's any instructions left that haven't yet been renamed.
683 // If so then block.
684 if (insts_available) {
685 blockThisCycle = true;
686 }
687
688 if (blockThisCycle) {
689 block(tid);
690 toDecode->renameUnblock[tid] = false;
691 }
692}
693
694template<class Impl>
695void
696DefaultRename<Impl>::skidInsert(ThreadID tid)
697{
698 DynInstPtr inst = NULL;
699
700 while (!insts[tid].empty()) {
701 inst = insts[tid].front();
702
703 insts[tid].pop_front();
704
705 assert(tid == inst->threadNumber);
706
707 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
708 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
709
710 ++renameSkidInsts;
711
712 skidBuffer[tid].push_back(inst);
713 }
714
715 if (skidBuffer[tid].size() > skidBufferMax)
716 {
717 typename InstQueue::iterator it;
718 warn("Skidbuffer contents:\n");
719 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
720 {
721 warn("[tid:%u]: %s [sn:%i].\n", tid,
722 (*it)->staticInst->disassemble(inst->instAddr()),
723 (*it)->seqNum);
724 }
725 panic("Skidbuffer Exceeded Max Size");
726 }
727}
728
729template <class Impl>
730void
731DefaultRename<Impl>::sortInsts()
732{
733 int insts_from_decode = fromDecode->size;
734 for (int i = 0; i < insts_from_decode; ++i) {
735 DynInstPtr inst = fromDecode->insts[i];
736 insts[inst->threadNumber].push_back(inst);
737#if TRACING_ON
738 if (DTRACE(O3PipeView)) {
739 inst->renameTick = curTick() - inst->fetchTick;
740 }
741#endif
742 }
743}
744
745template<class Impl>
746bool
747DefaultRename<Impl>::skidsEmpty()
748{
749 list<ThreadID>::iterator threads = activeThreads->begin();
750 list<ThreadID>::iterator end = activeThreads->end();
751
752 while (threads != end) {
753 ThreadID tid = *threads++;
754
755 if (!skidBuffer[tid].empty())
756 return false;
757 }
758
759 return true;
760}
761
762template<class Impl>
763void
764DefaultRename<Impl>::updateStatus()
765{
766 bool any_unblocking = false;
767
768 list<ThreadID>::iterator threads = activeThreads->begin();
769 list<ThreadID>::iterator end = activeThreads->end();
770
771 while (threads != end) {
772 ThreadID tid = *threads++;
773
774 if (renameStatus[tid] == Unblocking) {
775 any_unblocking = true;
776 break;
777 }
778 }
779
780 // Rename will have activity if it's unblocking.
781 if (any_unblocking) {
782 if (_status == Inactive) {
783 _status = Active;
784
785 DPRINTF(Activity, "Activating stage.\n");
786
787 cpu->activateStage(O3CPU::RenameIdx);
788 }
789 } else {
790 // If it's not unblocking, then rename will not have any internal
791 // activity. Switch it to inactive.
792 if (_status == Active) {
793 _status = Inactive;
794 DPRINTF(Activity, "Deactivating stage.\n");
795
796 cpu->deactivateStage(O3CPU::RenameIdx);
797 }
798 }
799}
800
801template <class Impl>
802bool
803DefaultRename<Impl>::block(ThreadID tid)
804{
805 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
806
807 // Add the current inputs onto the skid buffer, so they can be
808 // reprocessed when this stage unblocks.
809 skidInsert(tid);
810
811 // Only signal backwards to block if the previous stages do not think
812 // rename is already blocked.
813 if (renameStatus[tid] != Blocked) {
814 // If resumeUnblocking is set, we unblocked during the squash,
815 // but now we're have unblocking status. We need to tell earlier
816 // stages to block.
817 if (resumeUnblocking || renameStatus[tid] != Unblocking) {
818 toDecode->renameBlock[tid] = true;
819 toDecode->renameUnblock[tid] = false;
820 wroteToTimeBuffer = true;
821 }
822
823 // Rename can not go from SerializeStall to Blocked, otherwise
824 // it would not know to complete the serialize stall.
825 if (renameStatus[tid] != SerializeStall) {
826 // Set status to Blocked.
827 renameStatus[tid] = Blocked;
828 return true;
829 }
830 }
831
832 return false;
833}
834
835template <class Impl>
836bool
837DefaultRename<Impl>::unblock(ThreadID tid)
838{
839 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
840
841 // Rename is done unblocking if the skid buffer is empty.
842 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
843
844 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
845
846 toDecode->renameUnblock[tid] = true;
847 wroteToTimeBuffer = true;
848
849 renameStatus[tid] = Running;
850 return true;
851 }
852
853 return false;
854}
855
856template <class Impl>
857void
858DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid)
859{
860 typename std::list<RenameHistory>::iterator hb_it =
861 historyBuffer[tid].begin();
862
863 // After a syscall squashes everything, the history buffer may be empty
864 // but the ROB may still be squashing instructions.
865 if (historyBuffer[tid].empty()) {
866 return;
867 }
868
869 // Go through the most recent instructions, undoing the mappings
870 // they did and freeing up the registers.
871 while (!historyBuffer[tid].empty() &&
872 (*hb_it).instSeqNum > squashed_seq_num) {
873 assert(hb_it != historyBuffer[tid].end());
874
875 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
876 "number %i.\n", tid, (*hb_it).instSeqNum);
877
878 // Tell the rename map to set the architected register to the
879 // previous physical register that it was renamed to.
880 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
881
882 // Put the renamed physical register back on the free list.
883 freeList->addReg(hb_it->newPhysReg);
884
885 // Be sure to mark its register as ready if it's a misc register.
886 if (hb_it->newPhysReg >= maxPhysicalRegs) {
887 scoreboard->setReg(hb_it->newPhysReg);
888 }
889
890 historyBuffer[tid].erase(hb_it++);
891
892 ++renameUndoneMaps;
893 }
894}
895
896template<class Impl>
897void
898DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
899{
900 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
901 "history buffer %u (size=%i), until [sn:%lli].\n",
902 tid, tid, historyBuffer[tid].size(), inst_seq_num);
903
904 typename std::list<RenameHistory>::iterator hb_it =
905 historyBuffer[tid].end();
906
907 --hb_it;
908
909 if (historyBuffer[tid].empty()) {
910 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
911 return;
912 } else if (hb_it->instSeqNum > inst_seq_num) {
913 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure "
914 "that a syscall happened recently.\n", tid);
915 return;
916 }
917
918 // Commit all the renames up until (and including) the committed sequence
919 // number. Some or even all of the committed instructions may not have
920 // rename histories if they did not have destination registers that were
921 // renamed.
922 while (!historyBuffer[tid].empty() &&
923 hb_it != historyBuffer[tid].end() &&
924 (*hb_it).instSeqNum <= inst_seq_num) {
925
926 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
927 "[sn:%lli].\n",
928 tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
929
930 freeList->addReg((*hb_it).prevPhysReg);
931 ++renameCommittedMaps;
932
933 historyBuffer[tid].erase(hb_it--);
934 }
935}
936
937template <class Impl>
938inline void
939DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
940{
941 assert(renameMap[tid] != 0);
942
943 unsigned num_src_regs = inst->numSrcRegs();
944
945 // Get the architectual register numbers from the source and
946 // destination operands, and redirect them to the right register.
947 // Will need to mark dependencies though.
948 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
949 RegIndex src_reg = inst->srcRegIdx(src_idx);
950 RegIndex flat_src_reg = src_reg;
951 if (src_reg < TheISA::FP_Base_DepTag) {
952 flat_src_reg = inst->tcBase()->flattenIntIndex(src_reg);
953 DPRINTF(Rename, "Flattening index %d to %d.\n",
954 (int)src_reg, (int)flat_src_reg);
955 } else if (src_reg < TheISA::Ctrl_Base_DepTag) {
956 src_reg = src_reg - TheISA::FP_Base_DepTag;
957 flat_src_reg = inst->tcBase()->flattenFloatIndex(src_reg);
958 DPRINTF(Rename, "Flattening index %d to %d.\n",
959 (int)src_reg, (int)flat_src_reg);
960 flat_src_reg += TheISA::NumIntRegs;
961 } else if (src_reg < TheISA::Max_DepTag) {
962 flat_src_reg = src_reg - TheISA::Ctrl_Base_DepTag +
963 TheISA::NumFloatRegs + TheISA::NumIntRegs;
964 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
965 src_reg, flat_src_reg);
966 } else {
967 panic("Reg index is out of bound: %d.", src_reg);
968 }
969
970 // Look up the source registers to get the phys. register they've
971 // been renamed to, and set the sources to those registers.
972 PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg);
973
974 DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
975 "physical reg %i.\n", tid, (int)flat_src_reg,
976 (int)renamed_reg);
977
978 inst->renameSrcReg(src_idx, renamed_reg);
979
980 // See if the register is ready or not.
981 if (scoreboard->getReg(renamed_reg) == true) {
982 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n",
983 tid, renamed_reg);
984
985 inst->markSrcRegReady(src_idx);
986 } else {
987 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n",
988 tid, renamed_reg);
989 }
990
991 ++renameRenameLookups;
992 inst->isFloating() ? fpRenameLookups++ : intRenameLookups++;
993 }
994}
995
996template <class Impl>
997inline void
998DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
999{
1000 typename RenameMap::RenameInfo rename_result;
1001
1002 unsigned num_dest_regs = inst->numDestRegs();
1003
1004 // Rename the destination registers.
1005 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
1006 RegIndex dest_reg = inst->destRegIdx(dest_idx);
1007 RegIndex flat_dest_reg = dest_reg;
1008 if (dest_reg < TheISA::FP_Base_DepTag) {
1009 // Integer registers are flattened.
1010 flat_dest_reg = inst->tcBase()->flattenIntIndex(dest_reg);
1011 DPRINTF(Rename, "Flattening index %d to %d.\n",
1012 (int)dest_reg, (int)flat_dest_reg);
1013 } else if (dest_reg < TheISA::Ctrl_Base_DepTag) {
1014 dest_reg = dest_reg - TheISA::FP_Base_DepTag;
1015 flat_dest_reg = inst->tcBase()->flattenFloatIndex(dest_reg);
1016 DPRINTF(Rename, "Flattening index %d to %d.\n",
1017 (int)dest_reg, (int)flat_dest_reg);
1018 flat_dest_reg += TheISA::NumIntRegs;
1019 } else if (dest_reg < TheISA::Max_DepTag) {
1020 // Floating point and Miscellaneous registers need their indexes
1021 // adjusted to account for the expanded number of flattened int regs.
1022 flat_dest_reg = dest_reg - TheISA::Ctrl_Base_DepTag +
1023 TheISA::NumIntRegs + TheISA::NumFloatRegs;
1024 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
1025 dest_reg, flat_dest_reg);
1026 } else {
1027 panic("Reg index is out of bound: %d.", dest_reg);
1028 }
1029
1030 inst->flattenDestReg(dest_idx, flat_dest_reg);
1031
1032 // Get the physical register that the destination will be
1033 // renamed to.
1034 rename_result = renameMap[tid]->rename(flat_dest_reg);
1035
1036 //Mark Scoreboard entry as not ready
1037 if (dest_reg < TheISA::Ctrl_Base_DepTag)
1038 scoreboard->unsetReg(rename_result.first);
1039
1040 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
1041 "reg %i.\n", tid, (int)flat_dest_reg,
1042 (int)rename_result.first);
1043
1044 // Record the rename information so that a history can be kept.
1045 RenameHistory hb_entry(inst->seqNum, flat_dest_reg,
1046 rename_result.first,
1047 rename_result.second);
1048
1049 historyBuffer[tid].push_front(hb_entry);
1050
1051 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer "
1052 "(size=%i), [sn:%lli].\n",tid,
1053 historyBuffer[tid].size(),
1054 (*historyBuffer[tid].begin()).instSeqNum);
1055
1056 // Tell the instruction to rename the appropriate destination
1057 // register (dest_idx) to the new physical register
1058 // (rename_result.first), and record the previous physical
1059 // register that the same logical register was renamed to
1060 // (rename_result.second).
1061 inst->renameDestReg(dest_idx,
1062 rename_result.first,
1063 rename_result.second);
1064
1065 ++renameRenamedOperands;
1066 }
1067}
1068
1069template <class Impl>
1070inline int
1071DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid)
1072{
1073 int num_free = freeEntries[tid].robEntries -
1074 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1075
1076 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
1077
1078 return num_free;
1079}
1080
1081template <class Impl>
1082inline int
1083DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid)
1084{
1085 int num_free = freeEntries[tid].iqEntries -
1086 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1087
1088 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
1089
1090 return num_free;
1091}
1092
1093template <class Impl>
1094inline int
1095DefaultRename<Impl>::calcFreeLSQEntries(ThreadID tid)
1096{
1097 int num_free = freeEntries[tid].lsqEntries -
1098 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
1099
1100 //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
1101
1102 return num_free;
1103}
1104
1105template <class Impl>
1106unsigned
1107DefaultRename<Impl>::validInsts()
1108{
1109 unsigned inst_count = 0;
1110
1111 for (int i=0; i<fromDecode->size; i++) {
1112 if (!fromDecode->insts[i]->isSquashed())
1113 inst_count++;
1114 }
1115
1116 return inst_count;
1117}
1118
1119template <class Impl>
1120void
1121DefaultRename<Impl>::readStallSignals(ThreadID tid)
1122{
1123 if (fromIEW->iewBlock[tid]) {
1124 stalls[tid].iew = true;
1125 }
1126
1127 if (fromIEW->iewUnblock[tid]) {
1128 assert(stalls[tid].iew);
1129 stalls[tid].iew = false;
1130 }
1131
1132 if (fromCommit->commitBlock[tid]) {
1133 stalls[tid].commit = true;
1134 }
1135
1136 if (fromCommit->commitUnblock[tid]) {
1137 assert(stalls[tid].commit);
1138 stalls[tid].commit = false;
1139 }
1140}
1141
1142template <class Impl>
1143bool
1144DefaultRename<Impl>::checkStall(ThreadID tid)
1145{
1146 bool ret_val = false;
1147
1148 if (stalls[tid].iew) {
1149 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
1150 ret_val = true;
1151 } else if (stalls[tid].commit) {
1152 DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
1153 ret_val = true;
1154 } else if (calcFreeROBEntries(tid) <= 0) {
1155 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
1156 ret_val = true;
1157 } else if (calcFreeIQEntries(tid) <= 0) {
1158 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
1159 ret_val = true;
1160 } else if (calcFreeLSQEntries(tid) <= 0) {
1161 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
1162 ret_val = true;
1163 } else if (renameMap[tid]->numFreeEntries() <= 0) {
1164 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
1165 ret_val = true;
1166 } else if (renameStatus[tid] == SerializeStall &&
1167 (!emptyROB[tid] || instsInProgress[tid])) {
1168 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
1169 "empty.\n",
1170 tid);
1171 ret_val = true;
1172 }
1173
1174 return ret_val;
1175}
1176
1177template <class Impl>
1178void
1179DefaultRename<Impl>::readFreeEntries(ThreadID tid)
1180{
1181 if (fromIEW->iewInfo[tid].usedIQ)
1182 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries;
1183
1184 if (fromIEW->iewInfo[tid].usedLSQ)
1185 freeEntries[tid].lsqEntries = fromIEW->iewInfo[tid].freeLSQEntries;
1186
1187 if (fromCommit->commitInfo[tid].usedROB) {
1188 freeEntries[tid].robEntries =
1189 fromCommit->commitInfo[tid].freeROBEntries;
1190 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
1191 }
1192
1193 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
1194 tid,
1195 freeEntries[tid].iqEntries,
1196 freeEntries[tid].robEntries,
1197 freeEntries[tid].lsqEntries);
1198
1199 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
1200 tid, instsInProgress[tid]);
1201}
1202
1203template <class Impl>
1204bool
1205DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
1206{
1207 // Check if there's a squash signal, squash if there is
1208 // Check stall signals, block if necessary.
1209 // If status was blocked
1210 // check if stall conditions have passed
1211 // if so then go to unblocking
1212 // If status was Squashing
1213 // check if squashing is not high. Switch to running this cycle.
1214 // If status was serialize stall
1215 // check if ROB is empty and no insts are in flight to the ROB
1216
1217 readFreeEntries(tid);
1218 readStallSignals(tid);
1219
1220 if (fromCommit->commitInfo[tid].squash) {
1221 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
1222 "commit.\n", tid);
1223
1224 squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
1225
1226 return true;
1227 }
1228
1229 if (fromCommit->commitInfo[tid].robSquashing) {
1230 DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
1231
1232 renameStatus[tid] = Squashing;
1233
1234 return true;
1235 }
1236
1237 if (checkStall(tid)) {
1238 return block(tid);
1239 }
1240
1241 if (renameStatus[tid] == Blocked) {
1242 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
1243 tid);
1244
1245 renameStatus[tid] = Unblocking;
1246
1247 unblock(tid);
1248
1249 return true;
1250 }
1251
1252 if (renameStatus[tid] == Squashing) {
1253 // Switch status to running if rename isn't being told to block or
1254 // squash this cycle.
1255 if (resumeSerialize) {
1256 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n",
1257 tid);
1258
1259 renameStatus[tid] = SerializeStall;
1260 return true;
1261 } else if (resumeUnblocking) {
1262 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n",
1263 tid);
1264 renameStatus[tid] = Unblocking;
1265 return true;
1266 } else {
1267 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
1268 tid);
1269
1270 renameStatus[tid] = Running;
1271 return false;
1272 }
1273 }
1274
1275 if (renameStatus[tid] == SerializeStall) {
1276 // Stall ends once the ROB is free.
1277 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
1278 "unblocking.\n", tid);
1279
1280 DynInstPtr serial_inst = serializeInst[tid];
1281
1282 renameStatus[tid] = Unblocking;
1283
1284 unblock(tid);
1285
1286 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
1287 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
1288
1289 // Put instruction into queue here.
1290 serial_inst->clearSerializeBefore();
1291
1292 if (!skidBuffer[tid].empty()) {
1293 skidBuffer[tid].push_front(serial_inst);
1294 } else {
1295 insts[tid].push_front(serial_inst);
1296 }
1297
1298 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
1299 " Adding to front of list.\n", tid);
1300
1301 serializeInst[tid] = NULL;
1302
1303 return true;
1304 }
1305
1306 // If we've reached this point, we have not gotten any signals that
1307 // cause rename to change its status. Rename remains the same as before.
1308 return false;
1309}
1310
1311template<class Impl>
1312void
1313DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid)
1314{
1315 if (inst_list.empty()) {
1316 // Mark a bit to say that I must serialize on the next instruction.
1317 serializeOnNextInst[tid] = true;
1318 return;
1319 }
1320
1321 // Set the next instruction as serializing.
1322 inst_list.front()->setSerializeBefore();
1323}
1324
1325template <class Impl>
1326inline void
1327DefaultRename<Impl>::incrFullStat(const FullSource &source)
1328{
1329 switch (source) {
1330 case ROB:
1331 ++renameROBFullEvents;
1332 break;
1333 case IQ:
1334 ++renameIQFullEvents;
1335 break;
1336 case LSQ:
1337 ++renameLSQFullEvents;
1338 break;
1339 default:
1340 panic("Rename full stall stat should be incremented for a reason!");
1341 break;
1342 }
1343}
1344
1345template <class Impl>
1346void
1347DefaultRename<Impl>::dumpHistory()
1348{
1349 typename std::list<RenameHistory>::iterator buf_it;
1350
1351 for (ThreadID tid = 0; tid < numThreads; tid++) {
1352
1353 buf_it = historyBuffer[tid].begin();
1354
1355 while (buf_it != historyBuffer[tid].end()) {
1356 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1357 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1358 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1359
1360 buf_it++;
1361 }
1362 }
1363}
656 renameSrcRegs(inst, inst->threadNumber);
657
658 renameDestRegs(inst, inst->threadNumber);
659
660 ++renamed_insts;
661
662
663 // Put instruction in rename queue.
664 toIEW->insts[toIEWIndex] = inst;
665 ++(toIEW->size);
666
667 // Increment which instruction we're on.
668 ++toIEWIndex;
669
670 // Decrement how many instructions are available.
671 --insts_available;
672 }
673
674 instsInProgress[tid] += renamed_insts;
675 renameRenamedInsts += renamed_insts;
676
677 // If we wrote to the time buffer, record this.
678 if (toIEWIndex) {
679 wroteToTimeBuffer = true;
680 }
681
682 // Check if there's any instructions left that haven't yet been renamed.
683 // If so then block.
684 if (insts_available) {
685 blockThisCycle = true;
686 }
687
688 if (blockThisCycle) {
689 block(tid);
690 toDecode->renameUnblock[tid] = false;
691 }
692}
693
694template<class Impl>
695void
696DefaultRename<Impl>::skidInsert(ThreadID tid)
697{
698 DynInstPtr inst = NULL;
699
700 while (!insts[tid].empty()) {
701 inst = insts[tid].front();
702
703 insts[tid].pop_front();
704
705 assert(tid == inst->threadNumber);
706
707 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
708 "skidBuffer\n", tid, inst->seqNum, inst->pcState());
709
710 ++renameSkidInsts;
711
712 skidBuffer[tid].push_back(inst);
713 }
714
715 if (skidBuffer[tid].size() > skidBufferMax)
716 {
717 typename InstQueue::iterator it;
718 warn("Skidbuffer contents:\n");
719 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
720 {
721 warn("[tid:%u]: %s [sn:%i].\n", tid,
722 (*it)->staticInst->disassemble(inst->instAddr()),
723 (*it)->seqNum);
724 }
725 panic("Skidbuffer Exceeded Max Size");
726 }
727}
728
729template <class Impl>
730void
731DefaultRename<Impl>::sortInsts()
732{
733 int insts_from_decode = fromDecode->size;
734 for (int i = 0; i < insts_from_decode; ++i) {
735 DynInstPtr inst = fromDecode->insts[i];
736 insts[inst->threadNumber].push_back(inst);
737#if TRACING_ON
738 if (DTRACE(O3PipeView)) {
739 inst->renameTick = curTick() - inst->fetchTick;
740 }
741#endif
742 }
743}
744
745template<class Impl>
746bool
747DefaultRename<Impl>::skidsEmpty()
748{
749 list<ThreadID>::iterator threads = activeThreads->begin();
750 list<ThreadID>::iterator end = activeThreads->end();
751
752 while (threads != end) {
753 ThreadID tid = *threads++;
754
755 if (!skidBuffer[tid].empty())
756 return false;
757 }
758
759 return true;
760}
761
762template<class Impl>
763void
764DefaultRename<Impl>::updateStatus()
765{
766 bool any_unblocking = false;
767
768 list<ThreadID>::iterator threads = activeThreads->begin();
769 list<ThreadID>::iterator end = activeThreads->end();
770
771 while (threads != end) {
772 ThreadID tid = *threads++;
773
774 if (renameStatus[tid] == Unblocking) {
775 any_unblocking = true;
776 break;
777 }
778 }
779
780 // Rename will have activity if it's unblocking.
781 if (any_unblocking) {
782 if (_status == Inactive) {
783 _status = Active;
784
785 DPRINTF(Activity, "Activating stage.\n");
786
787 cpu->activateStage(O3CPU::RenameIdx);
788 }
789 } else {
790 // If it's not unblocking, then rename will not have any internal
791 // activity. Switch it to inactive.
792 if (_status == Active) {
793 _status = Inactive;
794 DPRINTF(Activity, "Deactivating stage.\n");
795
796 cpu->deactivateStage(O3CPU::RenameIdx);
797 }
798 }
799}
800
801template <class Impl>
802bool
803DefaultRename<Impl>::block(ThreadID tid)
804{
805 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
806
807 // Add the current inputs onto the skid buffer, so they can be
808 // reprocessed when this stage unblocks.
809 skidInsert(tid);
810
811 // Only signal backwards to block if the previous stages do not think
812 // rename is already blocked.
813 if (renameStatus[tid] != Blocked) {
814 // If resumeUnblocking is set, we unblocked during the squash,
815 // but now we're have unblocking status. We need to tell earlier
816 // stages to block.
817 if (resumeUnblocking || renameStatus[tid] != Unblocking) {
818 toDecode->renameBlock[tid] = true;
819 toDecode->renameUnblock[tid] = false;
820 wroteToTimeBuffer = true;
821 }
822
823 // Rename can not go from SerializeStall to Blocked, otherwise
824 // it would not know to complete the serialize stall.
825 if (renameStatus[tid] != SerializeStall) {
826 // Set status to Blocked.
827 renameStatus[tid] = Blocked;
828 return true;
829 }
830 }
831
832 return false;
833}
834
835template <class Impl>
836bool
837DefaultRename<Impl>::unblock(ThreadID tid)
838{
839 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
840
841 // Rename is done unblocking if the skid buffer is empty.
842 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
843
844 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
845
846 toDecode->renameUnblock[tid] = true;
847 wroteToTimeBuffer = true;
848
849 renameStatus[tid] = Running;
850 return true;
851 }
852
853 return false;
854}
855
856template <class Impl>
857void
858DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid)
859{
860 typename std::list<RenameHistory>::iterator hb_it =
861 historyBuffer[tid].begin();
862
863 // After a syscall squashes everything, the history buffer may be empty
864 // but the ROB may still be squashing instructions.
865 if (historyBuffer[tid].empty()) {
866 return;
867 }
868
869 // Go through the most recent instructions, undoing the mappings
870 // they did and freeing up the registers.
871 while (!historyBuffer[tid].empty() &&
872 (*hb_it).instSeqNum > squashed_seq_num) {
873 assert(hb_it != historyBuffer[tid].end());
874
875 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
876 "number %i.\n", tid, (*hb_it).instSeqNum);
877
878 // Tell the rename map to set the architected register to the
879 // previous physical register that it was renamed to.
880 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
881
882 // Put the renamed physical register back on the free list.
883 freeList->addReg(hb_it->newPhysReg);
884
885 // Be sure to mark its register as ready if it's a misc register.
886 if (hb_it->newPhysReg >= maxPhysicalRegs) {
887 scoreboard->setReg(hb_it->newPhysReg);
888 }
889
890 historyBuffer[tid].erase(hb_it++);
891
892 ++renameUndoneMaps;
893 }
894}
895
896template<class Impl>
897void
898DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
899{
900 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
901 "history buffer %u (size=%i), until [sn:%lli].\n",
902 tid, tid, historyBuffer[tid].size(), inst_seq_num);
903
904 typename std::list<RenameHistory>::iterator hb_it =
905 historyBuffer[tid].end();
906
907 --hb_it;
908
909 if (historyBuffer[tid].empty()) {
910 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
911 return;
912 } else if (hb_it->instSeqNum > inst_seq_num) {
913 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure "
914 "that a syscall happened recently.\n", tid);
915 return;
916 }
917
918 // Commit all the renames up until (and including) the committed sequence
919 // number. Some or even all of the committed instructions may not have
920 // rename histories if they did not have destination registers that were
921 // renamed.
922 while (!historyBuffer[tid].empty() &&
923 hb_it != historyBuffer[tid].end() &&
924 (*hb_it).instSeqNum <= inst_seq_num) {
925
926 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
927 "[sn:%lli].\n",
928 tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
929
930 freeList->addReg((*hb_it).prevPhysReg);
931 ++renameCommittedMaps;
932
933 historyBuffer[tid].erase(hb_it--);
934 }
935}
936
937template <class Impl>
938inline void
939DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
940{
941 assert(renameMap[tid] != 0);
942
943 unsigned num_src_regs = inst->numSrcRegs();
944
945 // Get the architectual register numbers from the source and
946 // destination operands, and redirect them to the right register.
947 // Will need to mark dependencies though.
948 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
949 RegIndex src_reg = inst->srcRegIdx(src_idx);
950 RegIndex flat_src_reg = src_reg;
951 if (src_reg < TheISA::FP_Base_DepTag) {
952 flat_src_reg = inst->tcBase()->flattenIntIndex(src_reg);
953 DPRINTF(Rename, "Flattening index %d to %d.\n",
954 (int)src_reg, (int)flat_src_reg);
955 } else if (src_reg < TheISA::Ctrl_Base_DepTag) {
956 src_reg = src_reg - TheISA::FP_Base_DepTag;
957 flat_src_reg = inst->tcBase()->flattenFloatIndex(src_reg);
958 DPRINTF(Rename, "Flattening index %d to %d.\n",
959 (int)src_reg, (int)flat_src_reg);
960 flat_src_reg += TheISA::NumIntRegs;
961 } else if (src_reg < TheISA::Max_DepTag) {
962 flat_src_reg = src_reg - TheISA::Ctrl_Base_DepTag +
963 TheISA::NumFloatRegs + TheISA::NumIntRegs;
964 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
965 src_reg, flat_src_reg);
966 } else {
967 panic("Reg index is out of bound: %d.", src_reg);
968 }
969
970 // Look up the source registers to get the phys. register they've
971 // been renamed to, and set the sources to those registers.
972 PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg);
973
974 DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
975 "physical reg %i.\n", tid, (int)flat_src_reg,
976 (int)renamed_reg);
977
978 inst->renameSrcReg(src_idx, renamed_reg);
979
980 // See if the register is ready or not.
981 if (scoreboard->getReg(renamed_reg) == true) {
982 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n",
983 tid, renamed_reg);
984
985 inst->markSrcRegReady(src_idx);
986 } else {
987 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n",
988 tid, renamed_reg);
989 }
990
991 ++renameRenameLookups;
992 inst->isFloating() ? fpRenameLookups++ : intRenameLookups++;
993 }
994}
995
996template <class Impl>
997inline void
998DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
999{
1000 typename RenameMap::RenameInfo rename_result;
1001
1002 unsigned num_dest_regs = inst->numDestRegs();
1003
1004 // Rename the destination registers.
1005 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
1006 RegIndex dest_reg = inst->destRegIdx(dest_idx);
1007 RegIndex flat_dest_reg = dest_reg;
1008 if (dest_reg < TheISA::FP_Base_DepTag) {
1009 // Integer registers are flattened.
1010 flat_dest_reg = inst->tcBase()->flattenIntIndex(dest_reg);
1011 DPRINTF(Rename, "Flattening index %d to %d.\n",
1012 (int)dest_reg, (int)flat_dest_reg);
1013 } else if (dest_reg < TheISA::Ctrl_Base_DepTag) {
1014 dest_reg = dest_reg - TheISA::FP_Base_DepTag;
1015 flat_dest_reg = inst->tcBase()->flattenFloatIndex(dest_reg);
1016 DPRINTF(Rename, "Flattening index %d to %d.\n",
1017 (int)dest_reg, (int)flat_dest_reg);
1018 flat_dest_reg += TheISA::NumIntRegs;
1019 } else if (dest_reg < TheISA::Max_DepTag) {
1020 // Floating point and Miscellaneous registers need their indexes
1021 // adjusted to account for the expanded number of flattened int regs.
1022 flat_dest_reg = dest_reg - TheISA::Ctrl_Base_DepTag +
1023 TheISA::NumIntRegs + TheISA::NumFloatRegs;
1024 DPRINTF(Rename, "Adjusting reg index from %d to %d.\n",
1025 dest_reg, flat_dest_reg);
1026 } else {
1027 panic("Reg index is out of bound: %d.", dest_reg);
1028 }
1029
1030 inst->flattenDestReg(dest_idx, flat_dest_reg);
1031
1032 // Get the physical register that the destination will be
1033 // renamed to.
1034 rename_result = renameMap[tid]->rename(flat_dest_reg);
1035
1036 //Mark Scoreboard entry as not ready
1037 if (dest_reg < TheISA::Ctrl_Base_DepTag)
1038 scoreboard->unsetReg(rename_result.first);
1039
1040 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
1041 "reg %i.\n", tid, (int)flat_dest_reg,
1042 (int)rename_result.first);
1043
1044 // Record the rename information so that a history can be kept.
1045 RenameHistory hb_entry(inst->seqNum, flat_dest_reg,
1046 rename_result.first,
1047 rename_result.second);
1048
1049 historyBuffer[tid].push_front(hb_entry);
1050
1051 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer "
1052 "(size=%i), [sn:%lli].\n",tid,
1053 historyBuffer[tid].size(),
1054 (*historyBuffer[tid].begin()).instSeqNum);
1055
1056 // Tell the instruction to rename the appropriate destination
1057 // register (dest_idx) to the new physical register
1058 // (rename_result.first), and record the previous physical
1059 // register that the same logical register was renamed to
1060 // (rename_result.second).
1061 inst->renameDestReg(dest_idx,
1062 rename_result.first,
1063 rename_result.second);
1064
1065 ++renameRenamedOperands;
1066 }
1067}
1068
1069template <class Impl>
1070inline int
1071DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid)
1072{
1073 int num_free = freeEntries[tid].robEntries -
1074 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1075
1076 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
1077
1078 return num_free;
1079}
1080
1081template <class Impl>
1082inline int
1083DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid)
1084{
1085 int num_free = freeEntries[tid].iqEntries -
1086 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
1087
1088 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
1089
1090 return num_free;
1091}
1092
1093template <class Impl>
1094inline int
1095DefaultRename<Impl>::calcFreeLSQEntries(ThreadID tid)
1096{
1097 int num_free = freeEntries[tid].lsqEntries -
1098 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
1099
1100 //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
1101
1102 return num_free;
1103}
1104
1105template <class Impl>
1106unsigned
1107DefaultRename<Impl>::validInsts()
1108{
1109 unsigned inst_count = 0;
1110
1111 for (int i=0; i<fromDecode->size; i++) {
1112 if (!fromDecode->insts[i]->isSquashed())
1113 inst_count++;
1114 }
1115
1116 return inst_count;
1117}
1118
1119template <class Impl>
1120void
1121DefaultRename<Impl>::readStallSignals(ThreadID tid)
1122{
1123 if (fromIEW->iewBlock[tid]) {
1124 stalls[tid].iew = true;
1125 }
1126
1127 if (fromIEW->iewUnblock[tid]) {
1128 assert(stalls[tid].iew);
1129 stalls[tid].iew = false;
1130 }
1131
1132 if (fromCommit->commitBlock[tid]) {
1133 stalls[tid].commit = true;
1134 }
1135
1136 if (fromCommit->commitUnblock[tid]) {
1137 assert(stalls[tid].commit);
1138 stalls[tid].commit = false;
1139 }
1140}
1141
1142template <class Impl>
1143bool
1144DefaultRename<Impl>::checkStall(ThreadID tid)
1145{
1146 bool ret_val = false;
1147
1148 if (stalls[tid].iew) {
1149 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
1150 ret_val = true;
1151 } else if (stalls[tid].commit) {
1152 DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
1153 ret_val = true;
1154 } else if (calcFreeROBEntries(tid) <= 0) {
1155 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
1156 ret_val = true;
1157 } else if (calcFreeIQEntries(tid) <= 0) {
1158 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
1159 ret_val = true;
1160 } else if (calcFreeLSQEntries(tid) <= 0) {
1161 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
1162 ret_val = true;
1163 } else if (renameMap[tid]->numFreeEntries() <= 0) {
1164 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
1165 ret_val = true;
1166 } else if (renameStatus[tid] == SerializeStall &&
1167 (!emptyROB[tid] || instsInProgress[tid])) {
1168 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
1169 "empty.\n",
1170 tid);
1171 ret_val = true;
1172 }
1173
1174 return ret_val;
1175}
1176
1177template <class Impl>
1178void
1179DefaultRename<Impl>::readFreeEntries(ThreadID tid)
1180{
1181 if (fromIEW->iewInfo[tid].usedIQ)
1182 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries;
1183
1184 if (fromIEW->iewInfo[tid].usedLSQ)
1185 freeEntries[tid].lsqEntries = fromIEW->iewInfo[tid].freeLSQEntries;
1186
1187 if (fromCommit->commitInfo[tid].usedROB) {
1188 freeEntries[tid].robEntries =
1189 fromCommit->commitInfo[tid].freeROBEntries;
1190 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
1191 }
1192
1193 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
1194 tid,
1195 freeEntries[tid].iqEntries,
1196 freeEntries[tid].robEntries,
1197 freeEntries[tid].lsqEntries);
1198
1199 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
1200 tid, instsInProgress[tid]);
1201}
1202
1203template <class Impl>
1204bool
1205DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
1206{
1207 // Check if there's a squash signal, squash if there is
1208 // Check stall signals, block if necessary.
1209 // If status was blocked
1210 // check if stall conditions have passed
1211 // if so then go to unblocking
1212 // If status was Squashing
1213 // check if squashing is not high. Switch to running this cycle.
1214 // If status was serialize stall
1215 // check if ROB is empty and no insts are in flight to the ROB
1216
1217 readFreeEntries(tid);
1218 readStallSignals(tid);
1219
1220 if (fromCommit->commitInfo[tid].squash) {
1221 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
1222 "commit.\n", tid);
1223
1224 squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
1225
1226 return true;
1227 }
1228
1229 if (fromCommit->commitInfo[tid].robSquashing) {
1230 DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
1231
1232 renameStatus[tid] = Squashing;
1233
1234 return true;
1235 }
1236
1237 if (checkStall(tid)) {
1238 return block(tid);
1239 }
1240
1241 if (renameStatus[tid] == Blocked) {
1242 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
1243 tid);
1244
1245 renameStatus[tid] = Unblocking;
1246
1247 unblock(tid);
1248
1249 return true;
1250 }
1251
1252 if (renameStatus[tid] == Squashing) {
1253 // Switch status to running if rename isn't being told to block or
1254 // squash this cycle.
1255 if (resumeSerialize) {
1256 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n",
1257 tid);
1258
1259 renameStatus[tid] = SerializeStall;
1260 return true;
1261 } else if (resumeUnblocking) {
1262 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n",
1263 tid);
1264 renameStatus[tid] = Unblocking;
1265 return true;
1266 } else {
1267 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
1268 tid);
1269
1270 renameStatus[tid] = Running;
1271 return false;
1272 }
1273 }
1274
1275 if (renameStatus[tid] == SerializeStall) {
1276 // Stall ends once the ROB is free.
1277 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
1278 "unblocking.\n", tid);
1279
1280 DynInstPtr serial_inst = serializeInst[tid];
1281
1282 renameStatus[tid] = Unblocking;
1283
1284 unblock(tid);
1285
1286 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
1287 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
1288
1289 // Put instruction into queue here.
1290 serial_inst->clearSerializeBefore();
1291
1292 if (!skidBuffer[tid].empty()) {
1293 skidBuffer[tid].push_front(serial_inst);
1294 } else {
1295 insts[tid].push_front(serial_inst);
1296 }
1297
1298 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
1299 " Adding to front of list.\n", tid);
1300
1301 serializeInst[tid] = NULL;
1302
1303 return true;
1304 }
1305
1306 // If we've reached this point, we have not gotten any signals that
1307 // cause rename to change its status. Rename remains the same as before.
1308 return false;
1309}
1310
1311template<class Impl>
1312void
1313DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid)
1314{
1315 if (inst_list.empty()) {
1316 // Mark a bit to say that I must serialize on the next instruction.
1317 serializeOnNextInst[tid] = true;
1318 return;
1319 }
1320
1321 // Set the next instruction as serializing.
1322 inst_list.front()->setSerializeBefore();
1323}
1324
1325template <class Impl>
1326inline void
1327DefaultRename<Impl>::incrFullStat(const FullSource &source)
1328{
1329 switch (source) {
1330 case ROB:
1331 ++renameROBFullEvents;
1332 break;
1333 case IQ:
1334 ++renameIQFullEvents;
1335 break;
1336 case LSQ:
1337 ++renameLSQFullEvents;
1338 break;
1339 default:
1340 panic("Rename full stall stat should be incremented for a reason!");
1341 break;
1342 }
1343}
1344
1345template <class Impl>
1346void
1347DefaultRename<Impl>::dumpHistory()
1348{
1349 typename std::list<RenameHistory>::iterator buf_it;
1350
1351 for (ThreadID tid = 0; tid < numThreads; tid++) {
1352
1353 buf_it = historyBuffer[tid].begin();
1354
1355 while (buf_it != historyBuffer[tid].end()) {
1356 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1357 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1358 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1359
1360 buf_it++;
1361 }
1362 }
1363}