rename_impl.hh revision 1858
18839Sandreas.hansson@arm.com/*
28839Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
38839Sandreas.hansson@arm.com * All rights reserved.
48839Sandreas.hansson@arm.com *
58839Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68839Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78839Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98839Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118839Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128839Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
135335Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from
147897Shestness@cs.utexas.edu * this software without specific prior written permission.
154486Sbinkertn@umich.edu *
164486Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174486Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184486Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194486Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204486Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214486Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224486Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234486Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244486Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254486Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264486Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274486Sbinkertn@umich.edu */
284486Sbinkertn@umich.edu
294486Sbinkertn@umich.edu#include <list>
304486Sbinkertn@umich.edu
314486Sbinkertn@umich.edu#include "config/full_system.hh"
324486Sbinkertn@umich.edu#include "cpu/o3/rename.hh"
334486Sbinkertn@umich.edu
344486Sbinkertn@umich.edutemplate <class Impl>
354486Sbinkertn@umich.eduSimpleRename<Impl>::SimpleRename(Params &params)
364486Sbinkertn@umich.edu    : iewToRenameDelay(params.iewToRenameDelay),
374486Sbinkertn@umich.edu      decodeToRenameDelay(params.decodeToRenameDelay),
384486Sbinkertn@umich.edu      commitToRenameDelay(params.commitToRenameDelay),
394486Sbinkertn@umich.edu      renameWidth(params.renameWidth),
404486Sbinkertn@umich.edu      commitWidth(params.commitWidth),
417897Shestness@cs.utexas.edu      numInst(0)
428839Sandreas.hansson@arm.com{
434486Sbinkertn@umich.edu    _status = Idle;
446654Snate@binkert.org}
456654Snate@binkert.org
466654Snate@binkert.orgtemplate <class Impl>
473102SN/Avoid
483102SN/ASimpleRename<Impl>::regStats()
496654Snate@binkert.org{
509036Sandreas.hansson@arm.com    renameSquashCycles
514776Sgblack@eecs.umich.edu        .name(name() + ".renameSquashCycles")
524776Sgblack@eecs.umich.edu        .desc("Number of cycles rename is squashing")
536654Snate@binkert.org        .prereq(renameSquashCycles);
542667SN/A    renameIdleCycles
554776Sgblack@eecs.umich.edu        .name(name() + ".renameIdleCycles")
564776Sgblack@eecs.umich.edu        .desc("Number of cycles rename is idle")
576654Snate@binkert.org        .prereq(renameIdleCycles);
586023Snate@binkert.org    renameBlockCycles
598745Sgblack@eecs.umich.edu        .name(name() + ".renameBlockCycles")
606654Snate@binkert.org        .desc("Number of cycles rename is blocking")
616022Sgblack@eecs.umich.edu        .prereq(renameBlockCycles);
628745Sgblack@eecs.umich.edu    renameUnblockCycles
636654Snate@binkert.org        .name(name() + ".renameUnblockCycles")
646022Sgblack@eecs.umich.edu        .desc("Number of cycles rename is unblocking")
658745Sgblack@eecs.umich.edu        .prereq(renameUnblockCycles);
666654Snate@binkert.org    renameRenamedInsts
676022Sgblack@eecs.umich.edu        .name(name() + ".renameRenamedInsts")
688745Sgblack@eecs.umich.edu        .desc("Number of instructions processed by rename")
696654Snate@binkert.org        .prereq(renameRenamedInsts);
706116Snate@binkert.org    renameSquashedInsts
718745Sgblack@eecs.umich.edu        .name(name() + ".renameSquashedInsts")
726691Stjones1@inf.ed.ac.uk        .desc("Number of squashed instructions processed by rename")
736691Stjones1@inf.ed.ac.uk        .prereq(renameSquashedInsts);
748745Sgblack@eecs.umich.edu    renameROBFullEvents
754486Sbinkertn@umich.edu        .name(name() + ".renameROBFullEvents")
765529Snate@binkert.org        .desc("Number of times rename has considered the ROB 'full'")
771366SN/A        .prereq(renameROBFullEvents);
781310SN/A    renameIQFullEvents
799338SAndreas.Sandberg@arm.com        .name(name() + ".renameIQFullEvents")
809254SAndreas.Sandberg@arm.com        .desc("Number of times rename has considered the IQ 'full'")
819254SAndreas.Sandberg@arm.com        .prereq(renameIQFullEvents);
829254SAndreas.Sandberg@arm.com    renameFullRegistersEvents
839254SAndreas.Sandberg@arm.com        .name(name() + ".renameFullRegisterEvents")
849254SAndreas.Sandberg@arm.com        .desc("Number of times there has been no free registers")
859254SAndreas.Sandberg@arm.com        .prereq(renameFullRegistersEvents);
869254SAndreas.Sandberg@arm.com    renameRenamedOperands
879254SAndreas.Sandberg@arm.com        .name(name() + ".renameRenamedOperands")
889254SAndreas.Sandberg@arm.com        .desc("Number of destination operands rename has renamed")
899254SAndreas.Sandberg@arm.com        .prereq(renameRenamedOperands);
909254SAndreas.Sandberg@arm.com    renameRenameLookups
919254SAndreas.Sandberg@arm.com        .name(name() + ".renameRenameLookups")
922901SN/A        .desc("Number of register rename lookups that rename has made")
935712Shsul@eecs.umich.edu        .prereq(renameRenameLookups);
945529Snate@binkert.org    renameHBPlaceHolders
955529Snate@binkert.org        .name(name() + ".renameHBPlaceHolders")
965529Snate@binkert.org        .desc("Number of place holders added to the history buffer")
979161Sandreas.hansson@arm.com        .prereq(renameHBPlaceHolders);
985529Snate@binkert.org    renameCommittedMaps
995821Ssaidi@eecs.umich.edu        .name(name() + ".renameCommittedMaps")
1003170SN/A        .desc("Number of HB maps that are committed")
1015780Ssteve.reinhardt@amd.com        .prereq(renameCommittedMaps);
1025780Ssteve.reinhardt@amd.com    renameUndoneMaps
1035780Ssteve.reinhardt@amd.com        .name(name() + ".renameUndoneMaps")
1045780Ssteve.reinhardt@amd.com        .desc("Number of HB maps that are undone due to squashing")
1055780Ssteve.reinhardt@amd.com        .prereq(renameUndoneMaps);
1068784Sgblack@eecs.umich.edu    renameValidUndoneMaps
1078784Sgblack@eecs.umich.edu        .name(name() + ".renameValidUndoneMaps")
1088784Sgblack@eecs.umich.edu        .desc("Number of HB maps that are undone, and are not place holders")
1098793Sgblack@eecs.umich.edu        .prereq(renameValidUndoneMaps);
1101310SN/A}
1116654Snate@binkert.org
1126022Sgblack@eecs.umich.edutemplate <class Impl>
1136022Sgblack@eecs.umich.eduvoid
1148745Sgblack@eecs.umich.eduSimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
1158863Snilay@cs.wisc.edu{
1166654Snate@binkert.org    DPRINTF(Rename, "Rename: Setting CPU pointer.\n");
1176023Snate@binkert.org    cpu = cpu_ptr;
1186023Snate@binkert.org}
1198745Sgblack@eecs.umich.edu
1208863Snilay@cs.wisc.edutemplate <class Impl>
1216654Snate@binkert.orgvoid
1226022Sgblack@eecs.umich.eduSimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1236022Sgblack@eecs.umich.edu{
1248863Snilay@cs.wisc.edu    DPRINTF(Rename, "Rename: Setting time buffer pointer.\n");
1256654Snate@binkert.org    timeBuffer = tb_ptr;
1266022Sgblack@eecs.umich.edu
1276022Sgblack@eecs.umich.edu    // Setup wire to read information from time buffer, from IEW stage.
1288745Sgblack@eecs.umich.edu    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
1298863Snilay@cs.wisc.edu
1306654Snate@binkert.org    // Setup wire to read infromation from time buffer, from commit stage.
1316116Snate@binkert.org    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
1326116Snate@binkert.org
1338745Sgblack@eecs.umich.edu    // Setup wire to write information to previous stages.
1348863Snilay@cs.wisc.edu    toDecode = timeBuffer->getWire(0);
1356691Stjones1@inf.ed.ac.uk}
1366691Stjones1@inf.ed.ac.uk
1376691Stjones1@inf.ed.ac.uktemplate <class Impl>
1386691Stjones1@inf.ed.ac.ukvoid
1398745Sgblack@eecs.umich.eduSimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
1408863Snilay@cs.wisc.edu{
1414997Sgblack@eecs.umich.edu    DPRINTF(Rename, "Rename: Setting rename queue pointer.\n");
1424997Sgblack@eecs.umich.edu    renameQueue = rq_ptr;
1436654Snate@binkert.org
1444997Sgblack@eecs.umich.edu    // Setup wire to write information to future stages.
1454997Sgblack@eecs.umich.edu    toIEW = renameQueue->getWire(0);
1461310SN/A}
1471310SN/A
1481310SN/Atemplate <class Impl>
1491310SN/Avoid
1501310SN/ASimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
1511310SN/A{
1521310SN/A    DPRINTF(Rename, "Rename: Setting decode queue pointer.\n");
1531310SN/A    decodeQueue = dq_ptr;
1549180Sandreas.hansson@arm.com
1559180Sandreas.hansson@arm.com    // Setup wire to get information from decode.
1561310SN/A    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
1571369SN/A}
1581310SN/A
1591634SN/Atemplate <class Impl>
1604776Sgblack@eecs.umich.eduvoid
1614776Sgblack@eecs.umich.eduSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
1628839Sandreas.hansson@arm.com{
1638839Sandreas.hansson@arm.com    DPRINTF(Rename, "Rename: Setting rename map pointer.\n");
1648707Sandreas.hansson@arm.com    renameMap = rm_ptr;
1658707Sandreas.hansson@arm.com}
1668756Sgblack@eecs.umich.edu
1678707Sandreas.hansson@arm.comtemplate <class Impl>
1687876Sgblack@eecs.umich.eduvoid
1698839Sandreas.hansson@arm.comSimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
1708839Sandreas.hansson@arm.com{
1718745Sgblack@eecs.umich.edu    DPRINTF(Rename, "Rename: Setting free list pointer.\n");
1728839Sandreas.hansson@arm.com    freeList = fl_ptr;
1738839Sandreas.hansson@arm.com}
1742998SN/A
1758863Snilay@cs.wisc.edutemplate <class Impl>
1768863Snilay@cs.wisc.eduvoid
1778863Snilay@cs.wisc.eduSimpleRename<Impl>::dumpHistory()
1788863Snilay@cs.wisc.edu{
1798863Snilay@cs.wisc.edu    typename list<RenameHistory>::iterator buf_it = historyBuffer.begin();
1808863Snilay@cs.wisc.edu
1818863Snilay@cs.wisc.edu    while (buf_it != historyBuffer.end())
1828863Snilay@cs.wisc.edu    {
1838863Snilay@cs.wisc.edu        cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
1848863Snilay@cs.wisc.edu                "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
1858863Snilay@cs.wisc.edu                (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
1868863Snilay@cs.wisc.edu
1878863Snilay@cs.wisc.edu        buf_it++;
1888863Snilay@cs.wisc.edu    }
1898863Snilay@cs.wisc.edu}
1908863Snilay@cs.wisc.edu
1918863Snilay@cs.wisc.edutemplate <class Impl>
1928863Snilay@cs.wisc.eduvoid
1938863Snilay@cs.wisc.eduSimpleRename<Impl>::block()
1947876Sgblack@eecs.umich.edu{
1957876Sgblack@eecs.umich.edu    DPRINTF(Rename, "Rename: Blocking.\n");
1968839Sandreas.hansson@arm.com    // Set status to Blocked.
1977404SAli.Saidi@ARM.com    _status = Blocked;
1987876Sgblack@eecs.umich.edu
1998839Sandreas.hansson@arm.com    // Add the current inputs onto the skid buffer, so they can be
2008839Sandreas.hansson@arm.com    // reprocessed when this stage unblocks.
2018839Sandreas.hansson@arm.com    skidBuffer.push(*fromDecode);
2028839Sandreas.hansson@arm.com
2037876Sgblack@eecs.umich.edu    // Note that this stage only signals previous stages to stall when
2047876Sgblack@eecs.umich.edu    // it is the cause of the stall originates at this stage.  Otherwise
2057876Sgblack@eecs.umich.edu    // the previous stages are expected to check all possible stall signals.
2067876Sgblack@eecs.umich.edu}
2077876Sgblack@eecs.umich.edu
2087876Sgblack@eecs.umich.edutemplate <class Impl>
2092998SN/Ainline void
2107868Sgblack@eecs.umich.eduSimpleRename<Impl>::unblock()
2112998SN/A{
2122998SN/A    DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
2132998SN/A            "cycle.\n");
2142998SN/A    // Remove the now processed instructions from the skid buffer.
2157876Sgblack@eecs.umich.edu    skidBuffer.pop();
2168796Sgblack@eecs.umich.edu
2178796Sgblack@eecs.umich.edu    // If there's still information in the skid buffer, then
2188796Sgblack@eecs.umich.edu    // continue to tell previous stages to stall.  They will be
2198796Sgblack@eecs.umich.edu    // able to restart once the skid buffer is empty.
2208796Sgblack@eecs.umich.edu    if (!skidBuffer.empty()) {
2218796Sgblack@eecs.umich.edu        toDecode->renameInfo.stall = true;
2228796Sgblack@eecs.umich.edu    } else {
2238796Sgblack@eecs.umich.edu        DPRINTF(Rename, "Rename: Done unblocking.\n");
2248796Sgblack@eecs.umich.edu        _status = Running;
2258796Sgblack@eecs.umich.edu    }
2268887Sgeoffrey.blake@arm.com}
2278809Sgblack@eecs.umich.edu
2288809Sgblack@eecs.umich.edutemplate <class Impl>
2298887Sgeoffrey.blake@arm.comvoid
2308809Sgblack@eecs.umich.eduSimpleRename<Impl>::doSquash()
2318809Sgblack@eecs.umich.edu{
2322998SN/A    typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
2337868Sgblack@eecs.umich.edu
2347868Sgblack@eecs.umich.edu    InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
2359284Sandreas.hansson@arm.com
2369284Sandreas.hansson@arm.com#if FULL_SYSTEM
2379284Sandreas.hansson@arm.com    assert(!historyBuffer.empty());
2389284Sandreas.hansson@arm.com#else
2397876Sgblack@eecs.umich.edu    // After a syscall squashes everything, the history buffer may be empty
2402998SN/A    // but the ROB may still be squashing instructions.
2418839Sandreas.hansson@arm.com    if (historyBuffer.empty()) {
2427876Sgblack@eecs.umich.edu        return;
2438887Sgeoffrey.blake@arm.com    }
2448887Sgeoffrey.blake@arm.com#endif // FULL_SYSTEM
2458887Sgeoffrey.blake@arm.com
246    // Go through the most recent instructions, undoing the mappings
247    // they did and freeing up the registers.
248    while ((*hb_it).instSeqNum > squashed_seq_num)
249    {
250        assert(hb_it != historyBuffer.end());
251
252        DPRINTF(Rename, "Rename: Removing history entry with sequence "
253                "number %i.\n", (*hb_it).instSeqNum);
254
255        // If it's not simply a place holder, then add the registers.
256        if (!(*hb_it).placeHolder) {
257            // Tell the rename map to set the architected register to the
258            // previous physical register that it was renamed to.
259            renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg);
260
261            // Put the renamed physical register back on the free list.
262            freeList->addReg(hb_it->newPhysReg);
263
264            ++renameValidUndoneMaps;
265        }
266
267        historyBuffer.erase(hb_it++);
268
269        ++renameUndoneMaps;
270    }
271}
272
273template <class Impl>
274void
275SimpleRename<Impl>::squash()
276{
277    DPRINTF(Rename, "Rename: Squashing instructions.\n");
278    // Set the status to Squashing.
279    _status = Squashing;
280
281    numInst = 0;
282
283    // Clear the skid buffer in case it has any data in it.
284    while (!skidBuffer.empty())
285    {
286        skidBuffer.pop();
287    }
288
289    doSquash();
290}
291
292template<class Impl>
293void
294SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
295{
296    DPRINTF(Rename, "Rename: Removing a committed instruction from the "
297            "history buffer, until sequence number %lli.\n", inst_seq_num);
298    typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
299
300    --hb_it;
301
302    if (hb_it->instSeqNum > inst_seq_num) {
303        DPRINTF(Rename, "Rename: Old sequence number encountered.  Ensure "
304                "that a syscall happened recently.\n");
305        return;
306    }
307
308    while ((*hb_it).instSeqNum != inst_seq_num)
309    {
310        // Make sure we haven't gone off the end of the list.
311        assert(hb_it != historyBuffer.end());
312
313        // In theory instructions at the end of the history buffer
314        // should be older than the instruction being removed, which
315        // means they will have a lower sequence number.  Also the
316        // instruction being removed from the history really should
317        // be the last instruction in the list, as it is the instruction
318        // that was just committed that is being removed.
319        assert(hb_it->instSeqNum < inst_seq_num);
320        DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
321                " number %i.\n",
322                (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
323
324        if (!(*hb_it).placeHolder) {
325            freeList->addReg((*hb_it).prevPhysReg);
326            ++renameCommittedMaps;
327        }
328
329        historyBuffer.erase(hb_it--);
330    }
331
332    // Finally free up the previous register of the finished instruction
333    // itself.
334    if (!(*hb_it).placeHolder) {
335        freeList->addReg(hb_it->prevPhysReg);
336        ++renameCommittedMaps;
337    }
338
339    historyBuffer.erase(hb_it);
340}
341
342template <class Impl>
343inline void
344SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
345{
346    unsigned num_src_regs = inst->numSrcRegs();
347
348    // Get the architectual register numbers from the source and
349    // destination operands, and redirect them to the right register.
350    // Will need to mark dependencies though.
351    for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
352    {
353        RegIndex src_reg = inst->srcRegIdx(src_idx);
354
355        // Look up the source registers to get the phys. register they've
356        // been renamed to, and set the sources to those registers.
357        PhysRegIndex renamed_reg = renameMap->lookup(src_reg);
358
359        DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
360                "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
361
362        inst->renameSrcReg(src_idx, renamed_reg);
363
364        // Either incorporate it into the info passed back,
365        // or make another function call to see if that register is
366        // ready or not.
367        if (renameMap->isReady(renamed_reg)) {
368            DPRINTF(Rename, "Rename: Register is ready.\n");
369
370            inst->markSrcRegReady(src_idx);
371        }
372
373        ++renameRenameLookups;
374    }
375}
376
377template <class Impl>
378inline void
379SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
380{
381    typename SimpleRenameMap::RenameInfo rename_result;
382
383    unsigned num_dest_regs = inst->numDestRegs();
384
385    // If it's an instruction with no destination registers, then put
386    // a placeholder within the history buffer.  It might be better
387    // to not put it in the history buffer at all (other than branches,
388    // which always need at least a place holder), and differentiate
389    // between instructions with and without destination registers
390    // when getting from commit the instructions that committed.
391    if (num_dest_regs == 0) {
392        RenameHistory hb_entry(inst->seqNum);
393
394        historyBuffer.push_front(hb_entry);
395
396        DPRINTF(Rename, "Rename: Adding placeholder instruction to "
397                "history buffer, sequence number %lli.\n",
398                inst->seqNum);
399
400        ++renameHBPlaceHolders;
401    } else {
402
403        // Rename the destination registers.
404        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
405        {
406            RegIndex dest_reg = inst->destRegIdx(dest_idx);
407
408            // Get the physical register that the destination will be
409            // renamed to.
410            rename_result = renameMap->rename(dest_reg);
411
412            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
413                    "reg %i.\n", (int)dest_reg,
414                    (int)rename_result.first);
415
416            // Record the rename information so that a history can be kept.
417            RenameHistory hb_entry(inst->seqNum, dest_reg,
418                                   rename_result.first,
419                                   rename_result.second);
420
421            historyBuffer.push_front(hb_entry);
422
423            DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
424                    "sequence number %lli.\n",
425                    (*historyBuffer.begin()).instSeqNum);
426
427            // Tell the instruction to rename the appropriate destination
428            // register (dest_idx) to the new physical register
429            // (rename_result.first), and record the previous physical
430            // register that the same logical register was renamed to
431            // (rename_result.second).
432            inst->renameDestReg(dest_idx,
433                                rename_result.first,
434                                rename_result.second);
435
436            ++renameRenamedOperands;
437        }
438    }
439}
440
441template <class Impl>
442inline int
443SimpleRename<Impl>::calcFreeROBEntries()
444{
445    return fromCommit->commitInfo.freeROBEntries -
446        renameWidth * iewToRenameDelay;
447}
448
449template <class Impl>
450inline int
451SimpleRename<Impl>::calcFreeIQEntries()
452{
453    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
454}
455
456template<class Impl>
457void
458SimpleRename<Impl>::tick()
459{
460    // Rename will need to try to rename as many instructions as it
461    // has bandwidth, unless it is blocked.
462
463    // Check if _status is BarrierStall.  If so, then check if the number
464    // of free ROB entries is equal to the number of total ROB entries.
465    // Once equal then wake this stage up.  Set status to unblocking maybe.
466
467    if (_status != Blocked && _status != Squashing) {
468        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "
469                        "run stage.\n");
470        // Make sure that the skid buffer has something in it if the
471        // status is unblocking.
472        assert(_status == Unblocking ? !skidBuffer.empty() : 1);
473
474        rename();
475
476        // If the status was unblocking, then instructions from the skid
477        // buffer were used.  Remove those instructions and handle
478        // the rest of unblocking.
479        if (_status == Unblocking) {
480            ++renameUnblockCycles;
481
482            if (fromDecode->size > 0) {
483                // Add the current inputs onto the skid buffer, so they can be
484                // reprocessed when this stage unblocks.
485                skidBuffer.push(*fromDecode);
486            }
487
488            unblock();
489        }
490    } else if (_status == Blocked) {
491        ++renameBlockCycles;
492
493        // If stage is blocked and still receiving valid instructions,
494        // make sure to store them in the skid buffer.
495        if (fromDecode->size > 0) {
496
497            block();
498
499            // Continue to tell previous stage to stall.
500            toDecode->renameInfo.stall = true;
501        }
502
503        if (!fromIEW->iewInfo.stall &&
504            !fromCommit->commitInfo.stall &&
505            calcFreeROBEntries() > 0 &&
506            calcFreeIQEntries() > 0 &&
507            renameMap->numFreeEntries() > 0) {
508
509            // Need to be sure to check all blocking conditions above.
510            // If they have cleared, then start unblocking.
511            DPRINTF(Rename, "Rename: Stall signals cleared, going to "
512                    "unblock.\n");
513            _status = Unblocking;
514
515            // Continue to tell previous stage to block until this stage
516            // is done unblocking.
517            toDecode->renameInfo.stall = true;
518        } else {
519            // Otherwise no conditions have changed.  Tell previous
520            // stage to continue blocking.
521            toDecode->renameInfo.stall = true;
522        }
523
524        if (fromCommit->commitInfo.squash ||
525            fromCommit->commitInfo.robSquashing) {
526            squash();
527            return;
528        }
529    } else if (_status == Squashing) {
530        ++renameSquashCycles;
531
532        if (fromCommit->commitInfo.squash) {
533            squash();
534        } else if (!fromCommit->commitInfo.squash &&
535                   !fromCommit->commitInfo.robSquashing) {
536
537            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");
538            _status = Running;
539            rename();
540        } else {
541            doSquash();
542        }
543    }
544
545    // Ugly code, revamp all of the tick() functions eventually.
546    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {
547#if !FULL_SYSTEM
548        if (!fromCommit->commitInfo.squash) {
549            removeFromHistory(fromCommit->commitInfo.doneSeqNum);
550        }
551#else
552        removeFromHistory(fromCommit->commitInfo.doneSeqNum);
553#endif
554    }
555
556}
557
558template<class Impl>
559void
560SimpleRename<Impl>::rename()
561{
562    // Check if any of the stages ahead of rename are telling rename
563    // to squash.  The squash() function will also take care of fixing up
564    // the rename map and the free list.
565    if (fromCommit->commitInfo.squash ||
566        fromCommit->commitInfo.robSquashing) {
567        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
568        squash();
569        return;
570    }
571
572    // Check if time buffer is telling this stage to stall.
573    if (fromIEW->iewInfo.stall ||
574        fromCommit->commitInfo.stall) {
575        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "
576                        "stall.\n");
577        block();
578        return;
579    }
580
581    // Check if the current status is squashing.  If so, set its status
582    // to running and resume execution the next cycle.
583    if (_status == Squashing) {
584        DPRINTF(Rename, "Rename: Done squashing.\n");
585        _status = Running;
586        return;
587    }
588
589    // Check the decode queue to see if instructions are available.
590    // If there are no available instructions to rename, then do nothing.
591    // Or, if the stage is currently unblocking, then go ahead and run it.
592    if (fromDecode->size == 0 && _status != Unblocking) {
593        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
594        // Should I change status to idle?
595        return;
596    }
597
598    ////////////////////////////////////
599    // Actual rename part.
600    ////////////////////////////////////
601
602    DynInstPtr inst;
603
604    // If we're unblocking, then we may be in the middle of an instruction
605    // group.  Subtract off numInst to get the proper number of instructions
606    // left.
607    int insts_available = _status == Unblocking ?
608        skidBuffer.front().size - numInst :
609        fromDecode->size;
610
611    bool block_this_cycle = false;
612
613    // Will have to do a different calculation for the number of free
614    // entries.  Number of free entries recorded on this cycle -
615    // renameWidth * renameToDecodeDelay
616    int free_rob_entries = calcFreeROBEntries();
617    int free_iq_entries = calcFreeIQEntries();
618    int min_iq_rob = min(free_rob_entries, free_iq_entries);
619
620    unsigned to_iew_index = 0;
621
622    // Check if there's any space left.
623    if (min_iq_rob <= 0) {
624        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
625                "entries.\n"
626                "Rename: ROB has %d free entries.\n"
627                "Rename: IQ has %d free entries.\n",
628                free_rob_entries,
629                free_iq_entries);
630        block();
631        // Tell previous stage to stall.
632        toDecode->renameInfo.stall = true;
633
634        if (free_rob_entries <= 0) {
635            ++renameROBFullEvents;
636        } else {
637            ++renameIQFullEvents;
638        }
639
640        return;
641    } else if (min_iq_rob < insts_available) {
642        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "
643                "%i insts can be renamed due to IQ/ROB limits.\n",
644                min_iq_rob);
645
646        insts_available = min_iq_rob;
647
648        block_this_cycle = true;
649
650        if (free_rob_entries < free_iq_entries) {
651            ++renameROBFullEvents;
652        } else {
653            ++renameIQFullEvents;
654        }
655    }
656
657    while (insts_available > 0) {
658        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
659
660        // Get the next instruction either from the skid buffer or the
661        // decode queue.
662        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
663               fromDecode->insts[numInst];
664
665        if (inst->isSquashed()) {
666            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
667                    "squashed, skipping.\n",
668                    inst->seqNum, inst->readPC());
669
670            // Go to the next instruction.
671            ++numInst;
672
673            ++renameSquashedInsts;
674
675            // Decrement how many instructions are available.
676            --insts_available;
677
678            continue;
679        }
680
681        DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
682                inst->seqNum, inst->readPC());
683
684        // If it's a trap instruction, then it needs to wait here within
685        // rename until the ROB is empty.  Needs a way to detect that the
686        // ROB is empty.  Maybe an event?
687        // Would be nice if it could be avoided putting this into a
688        // specific stage and instead just put it into the AlphaFullCPU.
689        // Might not really be feasible though...
690        // (EXCB, TRAPB)
691        if (inst->isSerializing()) {
692            panic("Rename: Serializing instruction encountered.\n");
693            DPRINTF(Rename, "Rename: Serializing instruction "
694                            "encountered.\n");
695
696            // Change status over to BarrierStall so that other stages know
697            // what this is blocked on.
698            _status = BarrierStall;
699
700            block_this_cycle = true;
701
702            break;
703        }
704
705        // Check here to make sure there are enough destination registers
706        // to rename to.  Otherwise block.
707        if (renameMap->numFreeEntries() < inst->numDestRegs())
708        {
709            DPRINTF(Rename, "Rename: Blocking due to lack of free "
710                            "physical registers to rename to.\n");
711            // Need some sort of event based on a register being freed.
712
713            block_this_cycle = true;
714
715            ++renameFullRegistersEvents;
716
717            break;
718        }
719
720        renameSrcRegs(inst);
721
722        renameDestRegs(inst);
723
724        // Put instruction in rename queue.
725        toIEW->insts[to_iew_index] = inst;
726        ++(toIEW->size);
727
728        // Decrease the number of free ROB and IQ entries.
729        --free_rob_entries;
730        --free_iq_entries;
731
732        // Increment which instruction we're on.
733        ++to_iew_index;
734        ++numInst;
735
736        ++renameRenamedInsts;
737
738        // Decrement how many instructions are available.
739        --insts_available;
740    }
741
742    // Check if there's any instructions left that haven't yet been renamed.
743    // If so then block.
744    if (block_this_cycle) {
745        block();
746
747        toDecode->renameInfo.stall = true;
748    } else {
749        // If we had a successful rename and didn't have to exit early, then
750        // reset numInst so it will refer to the correct instruction on next
751        // run.
752        numInst = 0;
753    }
754}
755