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