simple_indirect.cc revision 13957
12623SN/A/*
22623SN/A * Copyright (c) 2014 ARM Limited
32623SN/A * All rights reserved.
42623SN/A *
52623SN/A * Redistribution and use in source and binary forms, with or without
62623SN/A * modification, are permitted provided that the following conditions are
72623SN/A * met: redistributions of source code must retain the above copyright
82623SN/A * notice, this list of conditions and the following disclaimer;
92623SN/A * redistributions in binary form must reproduce the above copyright
102623SN/A * notice, this list of conditions and the following disclaimer in the
112623SN/A * documentation and/or other materials provided with the distribution;
122623SN/A * neither the name of the copyright holders nor the names of its
132623SN/A * contributors may be used to endorse or promote products derived from
142623SN/A * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Mitch Hayenga
292623SN/A */
302623SN/A
313170Sstever@eecs.umich.edu#include "cpu/pred/simple_indirect.hh"
323806Ssaidi@eecs.umich.edu
332623SN/A#include "base/intmath.hh"
344040Ssaidi@eecs.umich.edu#include "debug/Indirect.hh"
356658Snate@binkert.org
362623SN/ASimpleIndirectPredictor::SimpleIndirectPredictor(
372623SN/A        const SimpleIndirectPredictorParams * params)
383348Sbinkertn@umich.edu    : IndirectPredictor(params),
393348Sbinkertn@umich.edu      hashGHR(params->indirectHashGHR),
404762Snate@binkert.org      hashTargets(params->indirectHashTargets),
412901Ssaidi@eecs.umich.edu      numSets(params->indirectSets),
422623SN/A      numWays(params->indirectWays),
432623SN/A      tagBits(params->indirectTagSize),
442623SN/A      pathLength(params->indirectPathLength),
452623SN/A      instShift(params->instShiftAmt),
462623SN/A      ghrNumBits(params->indirectGHRBits),
475606Snate@binkert.org      ghrMask((1 << params->indirectGHRBits)-1)
482623SN/A{
492623SN/A    if (!isPowerOf2(numSets)) {
502623SN/A      panic("Indirect predictor requires power of 2 number of sets");
512623SN/A    }
522623SN/A
532623SN/A    threadInfo.resize(params->numThreads);
542623SN/A
552623SN/A    targetCache.resize(numSets);
562623SN/A    for (unsigned i = 0; i < numSets; i++) {
572623SN/A        targetCache[i].resize(numWays);
582623SN/A    }
595336Shines@cs.fsu.edu
602623SN/A    fatal_if(ghrNumBits > (sizeof(ThreadInfo::ghr)*8), "ghr_size is too big");
614873Sstever@eecs.umich.edu}
622623SN/A
632623SN/Avoid
642856Srdreslin@umich.eduSimpleIndirectPredictor::genIndirectInfo(ThreadID tid,
656227Snate@binkert.org                                         void* & indirect_history)
662856Srdreslin@umich.edu{
672856Srdreslin@umich.edu    // record the GHR as it was before this prediction
682856Srdreslin@umich.edu    // It will be used to recover the history in case this prediction is
692856Srdreslin@umich.edu    // wrong or belongs to bad path
702856Srdreslin@umich.edu    indirect_history = new unsigned(threadInfo[tid].ghr);
714968Sacolyte@umich.edu}
724968Sacolyte@umich.edu
734968Sacolyte@umich.eduvoid
744968Sacolyte@umich.eduSimpleIndirectPredictor::updateDirectionInfo(
752856Srdreslin@umich.edu    ThreadID tid, bool actually_taken)
762856Srdreslin@umich.edu{
772856Srdreslin@umich.edu    threadInfo[tid].ghr <<= 1;
782623SN/A    threadInfo[tid].ghr |= actually_taken;
792623SN/A    threadInfo[tid].ghr &= ghrMask;
802623SN/A}
812623SN/A
822623SN/Avoid
832623SN/ASimpleIndirectPredictor::changeDirectionPrediction(ThreadID tid,
846221Snate@binkert.org    void * indirect_history, bool actually_taken)
856221Snate@binkert.org{
862680Sktlim@umich.edu    unsigned * previousGhr = static_cast<unsigned *>(indirect_history);
872623SN/A    threadInfo[tid].ghr = ((*previousGhr) << 1) + actually_taken;
882623SN/A    threadInfo[tid].ghr &= ghrMask;
895714Shsul@eecs.umich.edu}
902623SN/A
912623SN/Abool
924968Sacolyte@umich.eduSimpleIndirectPredictor::lookup(Addr br_addr, TheISA::PCState& target,
934968Sacolyte@umich.edu    ThreadID tid)
944968Sacolyte@umich.edu{
954968Sacolyte@umich.edu    Addr set_index = getSetIndex(br_addr, threadInfo[tid].ghr, tid);
964968Sacolyte@umich.edu    Addr tag = getTag(br_addr);
974968Sacolyte@umich.edu
985714Shsul@eecs.umich.edu    assert(set_index < numSets);
995712Shsul@eecs.umich.edu
1005712Shsul@eecs.umich.edu    DPRINTF(Indirect, "Looking up %x (set:%d)\n", br_addr, set_index);
1015712Shsul@eecs.umich.edu    const auto &iset = targetCache[set_index];
1022623SN/A    for (auto way = iset.begin(); way != iset.end(); ++way) {
1032623SN/A        if (way->tag == tag) {
1042623SN/A            DPRINTF(Indirect, "Hit %x (target:%s)\n", br_addr, way->target);
1053349Sbinkertn@umich.edu            target = way->target;
1062623SN/A            return true;
1073184Srdreslin@umich.edu        }
1082623SN/A    }
1092623SN/A    DPRINTF(Indirect, "Miss %x\n", br_addr);
1102623SN/A    return false;
1112623SN/A}
1123349Sbinkertn@umich.edu
1132623SN/Avoid
1143310Srdreslin@umich.eduSimpleIndirectPredictor::recordIndirect(Addr br_addr, Addr tgt_addr,
1153649Srdreslin@umich.edu    InstSeqNum seq_num, ThreadID tid)
1162623SN/A{
1172623SN/A    DPRINTF(Indirect, "Recording %x seq:%d\n", br_addr, seq_num);
1182623SN/A    HistoryEntry entry(br_addr, tgt_addr, seq_num);
1193349Sbinkertn@umich.edu    threadInfo[tid].pathHist.push_back(entry);
1202623SN/A}
1213184Srdreslin@umich.edu
1223184Srdreslin@umich.eduvoid
1232623SN/ASimpleIndirectPredictor::commit(InstSeqNum seq_num, ThreadID tid,
1242623SN/A                          void * indirect_history)
1252623SN/A{
1262623SN/A    DPRINTF(Indirect, "Committing seq:%d\n", seq_num);
1272623SN/A    ThreadInfo &t_info = threadInfo[tid];
1283647Srdreslin@umich.edu
1293647Srdreslin@umich.edu    // we do not need to recover the GHR, so delete the information
1303647Srdreslin@umich.edu    unsigned * previousGhr = static_cast<unsigned *>(indirect_history);
1313647Srdreslin@umich.edu    delete previousGhr;
1323647Srdreslin@umich.edu
1332626SN/A    if (t_info.pathHist.empty()) return;
1343647Srdreslin@umich.edu
1352626SN/A    if (t_info.headHistEntry < t_info.pathHist.size() &&
1362623SN/A        t_info.pathHist[t_info.headHistEntry].seqNum <= seq_num) {
1372623SN/A        if (t_info.headHistEntry >= pathLength) {
1382623SN/A            t_info.pathHist.pop_front();
1392657Ssaidi@eecs.umich.edu        } else {
1402623SN/A             ++t_info.headHistEntry;
1412623SN/A        }
1422623SN/A    }
1432623SN/A}
1442623SN/A
1454192Sktlim@umich.eduvoid
1464192Sktlim@umich.eduSimpleIndirectPredictor::squash(InstSeqNum seq_num, ThreadID tid)
1474192Sktlim@umich.edu{
1484192Sktlim@umich.edu    DPRINTF(Indirect, "Squashing seq:%d\n", seq_num);
1494192Sktlim@umich.edu    ThreadInfo &t_info = threadInfo[tid];
1504192Sktlim@umich.edu    auto squash_itr = t_info.pathHist.begin();
1514192Sktlim@umich.edu    while (squash_itr != t_info.pathHist.end()) {
1524192Sktlim@umich.edu        if (squash_itr->seqNum > seq_num) {
1535497Ssaidi@eecs.umich.edu           break;
1544192Sktlim@umich.edu        }
1554192Sktlim@umich.edu        ++squash_itr;
1562623SN/A    }
1575529Snate@binkert.org    if (squash_itr != t_info.pathHist.end()) {
1586078Sgblack@eecs.umich.edu        DPRINTF(Indirect, "Squashing series starting with sn:%d\n",
1595487Snate@binkert.org                squash_itr->seqNum);
1605487Snate@binkert.org    }
1614968Sacolyte@umich.edu    t_info.pathHist.erase(squash_itr, t_info.pathHist.end());
1624968Sacolyte@umich.edu}
1632623SN/A
1642623SN/Avoid
1652623SN/ASimpleIndirectPredictor::deleteIndirectInfo(ThreadID tid,
1663647Srdreslin@umich.edu                                            void * indirect_history)
1673647Srdreslin@umich.edu{
1683647Srdreslin@umich.edu    unsigned * previousGhr = static_cast<unsigned *>(indirect_history);
1692623SN/A    threadInfo[tid].ghr = *previousGhr;
1702623SN/A
1712623SN/A    delete previousGhr;
1722623SN/A}
1732623SN/A
1746775SBrad.Beckmann@amd.comvoid
1756775SBrad.Beckmann@amd.comSimpleIndirectPredictor::recordTarget(
1766775SBrad.Beckmann@amd.com    InstSeqNum seq_num, void * indirect_history, const TheISA::PCState& target,
1772623SN/A    ThreadID tid)
1782623SN/A{
1792623SN/A    ThreadInfo &t_info = threadInfo[tid];
1802623SN/A
1812623SN/A    unsigned * ghr = static_cast<unsigned *>(indirect_history);
1822915Sktlim@umich.edu
1832915Sktlim@umich.edu    // Should have just squashed so this branch should be the oldest
1846078Sgblack@eecs.umich.edu    auto hist_entry = *(t_info.pathHist.rbegin());
1853145Shsul@eecs.umich.edu    // Temporarily pop it off the history so we can calculate the set
1862623SN/A    t_info.pathHist.pop_back();
1872623SN/A    Addr set_index = getSetIndex(hist_entry.pcAddr, *ghr, tid);
1882623SN/A    Addr tag = getTag(hist_entry.pcAddr);
1892623SN/A    hist_entry.targetAddr = target.instAddr();
1902623SN/A    t_info.pathHist.push_back(hist_entry);
1912623SN/A
1922623SN/A    assert(set_index < numSets);
1932915Sktlim@umich.edu
1942915Sktlim@umich.edu    auto &iset = targetCache[set_index];
1956078Sgblack@eecs.umich.edu    for (auto way = iset.begin(); way != iset.end(); ++way) {
1963145Shsul@eecs.umich.edu        if (way->tag == tag) {
1972915Sktlim@umich.edu            DPRINTF(Indirect, "Updating Target (seq: %d br:%x set:%d target:"
1982915Sktlim@umich.edu                    "%s)\n", seq_num, hist_entry.pcAddr, set_index, target);
1992915Sktlim@umich.edu            way->target = target;
2002915Sktlim@umich.edu            return;
2012915Sktlim@umich.edu        }
2022915Sktlim@umich.edu    }
2035220Ssaidi@eecs.umich.edu
2045220Ssaidi@eecs.umich.edu    DPRINTF(Indirect, "Allocating Target (seq: %d br:%x set:%d target:%s)\n",
2055220Ssaidi@eecs.umich.edu            seq_num, hist_entry.pcAddr, set_index, target);
2064940Snate@binkert.org    // Did not find entry, random replacement
2075220Ssaidi@eecs.umich.edu    auto &way = iset[rand() % numWays];
2083324Shsul@eecs.umich.edu    way.tag = tag;
2095220Ssaidi@eecs.umich.edu    way.target = target;
2105220Ssaidi@eecs.umich.edu}
2115606Snate@binkert.org
2125606Snate@binkert.org
2132915Sktlim@umich.eduinline Addr
2142623SN/ASimpleIndirectPredictor::getSetIndex(Addr br_addr, unsigned ghr, ThreadID tid)
2152623SN/A{
2162623SN/A    ThreadInfo &t_info = threadInfo[tid];
2172798Sktlim@umich.edu
2182623SN/A    Addr hash = br_addr >> instShift;
2195496Ssaidi@eecs.umich.edu    if (hashGHR) {
2202798Sktlim@umich.edu        hash ^= ghr;
2212623SN/A    }
2222798Sktlim@umich.edu    if (hashTargets) {
2232623SN/A        unsigned hash_shift = floorLog2(numSets) / pathLength;
2242623SN/A        for (int i = t_info.pathHist.size()-1, p = 0;
2252623SN/A             i >= 0 && p < pathLength; i--, p++) {
2262623SN/A            hash ^= (t_info.pathHist[i].targetAddr >>
2272623SN/A                     (instShift + p*hash_shift));
2282623SN/A        }
2294192Sktlim@umich.edu    }
2302623SN/A    return hash & (numSets-1);
2312623SN/A}
2322623SN/A
2332680Sktlim@umich.eduinline Addr
2342623SN/ASimpleIndirectPredictor::getTag(Addr br_addr)
2356221Snate@binkert.org{
2366221Snate@binkert.org    return (br_addr >> instShift) & ((0x1<<tagBits)-1);
2372680Sktlim@umich.edu}
2382680Sktlim@umich.edu
2392623SN/ASimpleIndirectPredictor *
2405606Snate@binkert.orgSimpleIndirectPredictorParams::create()
2412623SN/A{
2422623SN/A    return new SimpleIndirectPredictor(this);
2432623SN/A}
2443512Sktlim@umich.edu