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