rename_impl.hh revision 1684
1#include <list>
2
3#include "cpu/beta_cpu/rename.hh"
4
5template <class Impl>
6SimpleRename<Impl>::SimpleRename(Params &params)
7    : iewToRenameDelay(params.iewToRenameDelay),
8      decodeToRenameDelay(params.decodeToRenameDelay),
9      commitToRenameDelay(params.commitToRenameDelay),
10      renameWidth(params.renameWidth),
11      commitWidth(params.commitWidth),
12      numInst(0)
13{
14    _status = Idle;
15}
16
17template <class Impl>
18void
19SimpleRename<Impl>::regStats()
20{
21    renameSquashCycles
22        .name(name() + ".renameSquashCycles")
23        .desc("Number of cycles rename is squashing")
24        .prereq(renameSquashCycles);
25    renameIdleCycles
26        .name(name() + ".renameIdleCycles")
27        .desc("Number of cycles rename is idle")
28        .prereq(renameIdleCycles);
29    renameBlockCycles
30        .name(name() + ".renameBlockCycles")
31        .desc("Number of cycles rename is blocking")
32        .prereq(renameBlockCycles);
33    renameUnblockCycles
34        .name(name() + ".renameUnblockCycles")
35        .desc("Number of cycles rename is unblocking")
36        .prereq(renameUnblockCycles);
37    renameRenamedInsts
38        .name(name() + ".renameRenamedInsts")
39        .desc("Number of instructions processed by rename")
40        .prereq(renameRenamedInsts);
41    renameSquashedInsts
42        .name(name() + ".renameSquashedInsts")
43        .desc("Number of squashed instructions processed by rename")
44        .prereq(renameSquashedInsts);
45    renameROBFullEvents
46        .name(name() + ".renameROBFullEvents")
47        .desc("Number of times rename has considered the ROB 'full'")
48        .prereq(renameROBFullEvents);
49    renameIQFullEvents
50        .name(name() + ".renameIQFullEvents")
51        .desc("Number of times rename has considered the IQ 'full'")
52        .prereq(renameIQFullEvents);
53    renameFullRegistersEvents
54        .name(name() + ".renameFullRegisterEvents")
55        .desc("Number of times there has been no free registers")
56        .prereq(renameFullRegistersEvents);
57    renameRenamedOperands
58        .name(name() + ".renameRenamedOperands")
59        .desc("Number of destination operands rename has renamed")
60        .prereq(renameRenamedOperands);
61    renameRenameLookups
62        .name(name() + ".renameRenameLookups")
63        .desc("Number of register rename lookups that rename has made")
64        .prereq(renameRenameLookups);
65    renameHBPlaceHolders
66        .name(name() + ".renameHBPlaceHolders")
67        .desc("Number of place holders added to the history buffer")
68        .prereq(renameHBPlaceHolders);
69    renameCommittedMaps
70        .name(name() + ".renameCommittedMaps")
71        .desc("Number of HB maps that are committed")
72        .prereq(renameCommittedMaps);
73    renameUndoneMaps
74        .name(name() + ".renameUndoneMaps")
75        .desc("Number of HB maps that are undone due to squashing")
76        .prereq(renameUndoneMaps);
77    renameValidUndoneMaps
78        .name(name() + ".renameValidUndoneMaps")
79        .desc("Number of HB maps that are undone, and are not place holders")
80        .prereq(renameValidUndoneMaps);
81}
82
83template <class Impl>
84void
85SimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
86{
87    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
88    cpu = cpu_ptr;
89}
90
91template <class Impl>
92void
93SimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
94{
95    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
96    timeBuffer = tb_ptr;
97
98    // Setup wire to read information from time buffer, from IEW stage.
99    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
100
101    // Setup wire to read infromation from time buffer, from commit stage.
102    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
103
104    // Setup wire to write information to previous stages.
105    toDecode = timeBuffer->getWire(0);
106}
107
108template <class Impl>
109void
110SimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
111{
112    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
113    renameQueue = rq_ptr;
114
115    // Setup wire to write information to future stages.
116    toIEW = renameQueue->getWire(0);
117}
118
119template <class Impl>
120void
121SimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
122{
123    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
124    decodeQueue = dq_ptr;
125
126    // Setup wire to get information from decode.
127    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
128}
129
130template <class Impl>
131void
132SimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
133{
134    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
135    renameMap = rm_ptr;
136}
137
138template <class Impl>
139void
140SimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
141{
142    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
143    freeList = fl_ptr;
144}
145
146template <class Impl>
147void
148SimpleRename<Impl>::dumpHistory()
149{
150    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
151
152    while (buf_it != historyBuffer.end())
153    {
154        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
155                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
156                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
157
158        buf_it++;
159    }
160}
161
162template <class Impl>
163void
164SimpleRename<Impl>::block()
165{
166    DPRINTF(Rename, "Rename: Blocking.\n");
167    // Set status to Blocked.
168    _status = Blocked;
169
170    // Add the current inputs onto the skid buffer, so they can be
171    // reprocessed when this stage unblocks.
172    skidBuffer.push(*fromDecode);
173
174    // Note that this stage only signals previous stages to stall when
175    // it is the cause of the stall originates at this stage.  Otherwise
176    // the previous stages are expected to check all possible stall signals.
177}
178
179template <class Impl>
180inline void
181SimpleRename<Impl>::unblock()
182{
183    DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
184            "cycle.\n");
185    // Remove the now processed instructions from the skid buffer.
186    skidBuffer.pop();
187
188    // If there's still information in the skid buffer, then
189    // continue to tell previous stages to stall.  They will be
190    // able to restart once the skid buffer is empty.
191    if (!skidBuffer.empty()) {
192        toDecode->renameInfo.stall = true;
193    } else {
194        DPRINTF(Rename, "Rename: Done unblocking.\n");
195        _status = Running;
196    }
197}
198
199template <class Impl>
200void
201SimpleRename<Impl>::doSquash()
202{
203    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
204
205    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
206
207#ifdef FULL_SYSTEM
208    assert(!historyBuffer.empty());
209#else
210    // After a syscall squashes everything, the history buffer may be empty
211    // but the ROB may still be squashing instructions.
212    if (historyBuffer.empty()) {
213        return;
214    }
215#endif // FULL_SYSTEM
216
217    // Go through the most recent instructions, undoing the mappings
218    // they did and freeing up the registers.
219    while ((*hb_it).instSeqNum > squashed_seq_num)
220    {
221        assert(hb_it != historyBuffer.end());
222
223        DPRINTF(Rename, "Rename: Removing history entry with sequence "
224                "number %i.\n", (*hb_it).instSeqNum);
225
226        // If it's not simply a place holder, then add the registers.
227        if (!(*hb_it).placeHolder) {
228            // Tell the rename map to set the architected register to the
229            // previous physical register that it was renamed to.
230            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
231
232            // Put the renamed physical register back on the free list.
233            freeList->addReg(hb_it->newPhysReg);
234
235            ++renameValidUndoneMaps;
236        }
237
238        historyBuffer.erase(hb_it++);
239
240        ++renameUndoneMaps;
241    }
242}
243
244template <class Impl>
245void
246SimpleRename<Impl>::squash()
247{
248    DPRINTF(Rename, "Rename: Squashing instructions.\n");
249    // Set the status to Squashing.
250    _status = Squashing;
251
252    numInst = 0;
253
254    // Clear the skid buffer in case it has any data in it.
255    while (!skidBuffer.empty())
256    {
257        skidBuffer.pop();
258    }
259
260    doSquash();
261}
262
263template<class Impl>
264void
265SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
266{
267    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
268            "history buffer, until sequence number %lli.\n", inst_seq_num);
269    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
270
271    --hb_it;
272
273    if (hb_it->instSeqNum > inst_seq_num) {
274        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
275                "that a syscall happened recently.\n");
276        return;
277    }
278
279    while ((*hb_it).instSeqNum != inst_seq_num)
280    {
281        // Make sure we haven't gone off the end of the list.
282        assert(hb_it != historyBuffer.end());
283
284        // In theory instructions at the end of the history buffer
285        // should be older than the instruction being removed, which
286        // means they will have a lower sequence number.  Also the
287        // instruction being removed from the history really should
288        // be the last instruction in the list, as it is the instruction
289        // that was just committed that is being removed.
290        assert(hb_it->instSeqNum < inst_seq_num);
291        DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
292                " number %i.\n",
293                (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
294
295        if (!(*hb_it).placeHolder) {
296            freeList->addReg((*hb_it).prevPhysReg);
297            ++renameCommittedMaps;
298        }
299
300        historyBuffer.erase(hb_it--);
301    }
302
303    // Finally free up the previous register of the finished instruction
304    // itself.
305    if (!(*hb_it).placeHolder) {
306        freeList->addReg(hb_it->prevPhysReg);
307        ++renameCommittedMaps;
308    }
309
310    historyBuffer.erase(hb_it);
311}
312
313template <class Impl>
314inline void
315SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
316{
317    unsigned num_src_regs = inst->numSrcRegs();
318
319    // Get the architectual register numbers from the source and
320    // destination operands, and redirect them to the right register.
321    // Will need to mark dependencies though.
322    for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
323    {
324        RegIndex src_reg = inst->srcRegIdx(src_idx);
325
326        // Look up the source registers to get the phys. register they've
327        // been renamed to, and set the sources to those registers.
328        PhysRegIndex renamed_reg = renameMap->lookup(src_reg);
329
330        DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
331                "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
332
333        inst->renameSrcReg(src_idx, renamed_reg);
334
335        // Either incorporate it into the info passed back,
336        // or make another function call to see if that register is
337        // ready or not.
338        if (renameMap->isReady(renamed_reg)) {
339            DPRINTF(Rename, "Rename: Register is ready.\n");
340
341            inst->markSrcRegReady(src_idx);
342        }
343
344        ++renameRenameLookups;
345    }
346}
347
348template <class Impl>
349inline void
350SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
351{
352    typename SimpleRenameMap::RenameInfo rename_result;
353
354    unsigned num_dest_regs = inst->numDestRegs();
355
356    // If it's an instruction with no destination registers, then put
357    // a placeholder within the history buffer.  It might be better
358    // to not put it in the history buffer at all (other than branches,
359    // which always need at least a place holder), and differentiate
360    // between instructions with and without destination registers
361    // when getting from commit the instructions that committed.
362    if (num_dest_regs == 0) {
363        RenameHistory hb_entry(inst->seqNum);
364
365        historyBuffer.push_front(hb_entry);
366
367        DPRINTF(Rename, "Rename: Adding placeholder instruction to "
368                "history buffer, sequence number %lli.\n",
369                inst->seqNum);
370
371        ++renameHBPlaceHolders;
372    } else {
373
374        // Rename the destination registers.
375        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
376        {
377            RegIndex dest_reg = inst->destRegIdx(dest_idx);
378
379            // Get the physical register that the destination will be
380            // renamed to.
381            rename_result = renameMap->rename(dest_reg);
382
383            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
384                    "reg %i.\n", (int)dest_reg,
385                    (int)rename_result.first);
386
387            // Record the rename information so that a history can be kept.
388            RenameHistory hb_entry(inst->seqNum, dest_reg,
389                                   rename_result.first,
390                                   rename_result.second);
391
392            historyBuffer.push_front(hb_entry);
393
394            DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
395                    "sequence number %lli.\n",
396                    (*historyBuffer.begin()).instSeqNum);
397
398            // Tell the instruction to rename the appropriate destination
399            // register (dest_idx) to the new physical register
400            // (rename_result.first), and record the previous physical
401            // register that the same logical register was renamed to
402            // (rename_result.second).
403            inst->renameDestReg(dest_idx,
404                                rename_result.first,
405                                rename_result.second);
406
407            ++renameRenamedOperands;
408        }
409    }
410}
411
412template <class Impl>
413inline int
414SimpleRename<Impl>::calcFreeROBEntries()
415{
416    return fromCommit->commitInfo.freeROBEntries -
417        renameWidth * iewToRenameDelay;
418}
419
420template <class Impl>
421inline int
422SimpleRename<Impl>::calcFreeIQEntries()
423{
424    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
425}
426
427template<class Impl>
428void
429SimpleRename<Impl>::tick()
430{
431    // Rename will need to try to rename as many instructions as it
432    // has bandwidth, unless it is blocked.
433
434    // Check if _status is BarrierStall.  If so, then check if the number
435    // of free ROB entries is equal to the number of total ROB entries.
436    // Once equal then wake this stage up.  Set status to unblocking maybe.
437
438    if (_status != Blocked && _status != Squashing) {
439        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
440                        "run stage.\n");
441        // Make sure that the skid buffer has something in it if the
442        // status is unblocking.
443        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
444
445        rename();
446
447        // If the status was unblocking, then instructions from the skid
448        // buffer were used.  Remove those instructions and handle
449        // the rest of unblocking.
450        if (_status == Unblocking) {
451            ++renameUnblockCycles;
452
453            if (fromDecode->size > 0) {
454                // Add the current inputs onto the skid buffer, so they can be
455                // reprocessed when this stage unblocks.
456                skidBuffer.push(*fromDecode);
457            }
458
459            unblock();
460        }
461    } else if (_status == Blocked) {
462        ++renameBlockCycles;
463
464        // If stage is blocked and still receiving valid instructions,
465        // make sure to store them in the skid buffer.
466        if (fromDecode->size > 0) {
467
468            block();
469
470            // Continue to tell previous stage to stall.
471            toDecode->renameInfo.stall = true;
472        }
473
474        if (!fromIEW->iewInfo.stall &&
475            !fromCommit->commitInfo.stall &&
476            calcFreeROBEntries() > 0 &&
477            calcFreeIQEntries() > 0 &&
478            renameMap->numFreeEntries() > 0) {
479
480            // Need to be sure to check all blocking conditions above.
481            // If they have cleared, then start unblocking.
482            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
483                    "unblock.\n");
484            _status = Unblocking;
485
486            // Continue to tell previous stage to block until this stage
487            // is done unblocking.
488            toDecode->renameInfo.stall = true;
489        } else {
490            // Otherwise no conditions have changed.  Tell previous
491            // stage to continue blocking.
492            toDecode->renameInfo.stall = true;
493        }
494
495        if (fromCommit->commitInfo.squash ||
496            fromCommit->commitInfo.robSquashing) {
497            squash();
498            return;
499        }
500    } else if (_status == Squashing) {
501        ++renameSquashCycles;
502
503        if (fromCommit->commitInfo.squash) {
504            squash();
505        } else if (!fromCommit->commitInfo.squash &&
506                   !fromCommit->commitInfo.robSquashing) {
507
508            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
509            _status = Running;
510            rename();
511        } else {
512            doSquash();
513        }
514    }
515
516    // Ugly code, revamp all of the tick() functions eventually.
517    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
518#ifndef FULL_SYSTEM
519        if (!fromCommit->commitInfo.squash) {
520            removeFromHistory(fromCommit->commitInfo.doneSeqNum);
521        }
522#else
523        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
524#endif
525    }
526
527}
528
529template<class Impl>
530void
531SimpleRename<Impl>::rename()
532{
533    // Check if any of the stages ahead of rename are telling rename
534    // to squash.  The squash() function will also take care of fixing up
535    // the rename map and the free list.
536    if (fromCommit->commitInfo.squash ||
537        fromCommit->commitInfo.robSquashing) {
538        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
539        squash();
540        return;
541    }
542
543    // Check if time buffer is telling this stage to stall.
544    if (fromIEW->iewInfo.stall ||
545        fromCommit->commitInfo.stall) {
546        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
547                        "stall.\n");
548        block();
549        return;
550    }
551
552    // Check if the current status is squashing.  If so, set its status
553    // to running and resume execution the next cycle.
554    if (_status == Squashing) {
555        DPRINTF(Rename, "Rename: Done squashing.\n");
556        _status = Running;
557        return;
558    }
559
560    // Check the decode queue to see if instructions are available.
561    // If there are no available instructions to rename, then do nothing.
562    // Or, if the stage is currently unblocking, then go ahead and run it.
563    if (fromDecode->size == 0 && _status != Unblocking) {
564        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
565        // Should I change status to idle?
566        return;
567    }
568
569    ////////////////////////////////////
570    // Actual rename part.
571    ////////////////////////////////////
572
573    DynInstPtr inst;
574
575    // If we're unblocking, then we may be in the middle of an instruction
576    // group.  Subtract off numInst to get the proper number of instructions
577    // left.
578    int insts_available = _status == Unblocking ?
579        skidBuffer.front().size - numInst :
580        fromDecode->size;
581
582    bool block_this_cycle = false;
583
584    // Will have to do a different calculation for the number of free
585    // entries.  Number of free entries recorded on this cycle -
586    // renameWidth * renameToDecodeDelay
587    int free_rob_entries = calcFreeROBEntries();
588    int free_iq_entries = calcFreeIQEntries();
589    int min_iq_rob = min(free_rob_entries, free_iq_entries);
590
591    unsigned to_iew_index = 0;
592
593    // Check if there's any space left.
594    if (min_iq_rob <= 0) {
595        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
596                "entries.\n"
597                "Rename: ROB has %d free entries.\n"
598                "Rename: IQ has %d free entries.\n",
599                free_rob_entries,
600                free_iq_entries);
601        block();
602        // Tell previous stage to stall.
603        toDecode->renameInfo.stall = true;
604
605        if (free_rob_entries <= 0) {
606            ++renameROBFullEvents;
607        } else {
608            ++renameIQFullEvents;
609        }
610
611        return;
612    } else if (min_iq_rob < insts_available) {
613        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "
614                "%i insts can be renamed due to IQ/ROB limits.\n",
615                min_iq_rob);
616
617        insts_available = min_iq_rob;
618
619        block_this_cycle = true;
620
621        if (free_rob_entries < free_iq_entries) {
622            ++renameROBFullEvents;
623        } else {
624            ++renameIQFullEvents;
625        }
626    }
627
628    while (insts_available > 0) {
629        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
630
631        // Get the next instruction either from the skid buffer or the
632        // decode queue.
633        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
634               fromDecode->insts[numInst];
635
636        if (inst->isSquashed()) {
637            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
638                    "squashed, skipping.\n",
639                    inst->seqNum, inst->readPC());
640
641            // Go to the next instruction.
642            ++numInst;
643
644            ++renameSquashedInsts;
645
646            // Decrement how many instructions are available.
647            --insts_available;
648
649            continue;
650        }
651
652        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
653                inst->seqNum, inst->readPC());
654
655        // If it's a trap instruction, then it needs to wait here within
656        // rename until the ROB is empty.  Needs a way to detect that the
657        // ROB is empty.  Maybe an event?
658        // Would be nice if it could be avoided putting this into a
659        // specific stage and instead just put it into the AlphaFullCPU.
660        // Might not really be feasible though...
661        // (EXCB, TRAPB)
662        if (inst->isSerializing()) {
663            panic("Rename: Serializing instruction encountered.\n");
664            DPRINTF(Rename, "Rename: Serializing instruction "
665                            "encountered.\n");
666
667            // Change status over to BarrierStall so that other stages know
668            // what this is blocked on.
669            _status = BarrierStall;
670
671            block_this_cycle = true;
672
673            break;
674        }
675
676        // Check here to make sure there are enough destination registers
677        // to rename to.  Otherwise block.
678        if (renameMap->numFreeEntries() < inst->numDestRegs())
679        {
680            DPRINTF(Rename, "Rename: Blocking due to lack of free "
681                            "physical registers to rename to.\n");
682            // Need some sort of event based on a register being freed.
683
684            block_this_cycle = true;
685
686            ++renameFullRegistersEvents;
687
688            break;
689        }
690
691        renameSrcRegs(inst);
692
693        renameDestRegs(inst);
694
695        // Put instruction in rename queue.
696        toIEW->insts[to_iew_index] = inst;
697        ++(toIEW->size);
698
699        // Decrease the number of free ROB and IQ entries.
700        --free_rob_entries;
701        --free_iq_entries;
702
703        // Increment which instruction we're on.
704        ++to_iew_index;
705        ++numInst;
706
707        ++renameRenamedInsts;
708
709        // Decrement how many instructions are available.
710        --insts_available;
711    }
712
713    // Check if there's any instructions left that haven't yet been renamed.
714    // If so then block.
715    if (block_this_cycle) {
716        block();
717
718        toDecode->renameInfo.stall = true;
719    } else {
720        // If we had a successful rename and didn't have to exit early, then
721        // reset numInst so it will refer to the correct instruction on next
722        // run.
723        numInst = 0;
724    }
725}
726