/*
 * Copyright 2019 Texas A&M University
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  Author: Daniel A. Jiménez
 *  Adapted to gem5 by: Javier Bueno Hedo
 *
 */

 /*
  * Multiperspective Perceptron Predictor (by Daniel A. Jiménez)
  */

#include "cpu/pred/multiperspective_perceptron.hh"

#include "base/random.hh"
#include "debug/Branch.hh"

namespace gem5
{

namespace branch_prediction
{

int
MultiperspectivePerceptron::xlat[] =
    {1,3,4,5,7,8,9,11,12,14,15,17,19,21,23,25,27,29,32,34,37,41,45,49,53,58,63,
     69,76,85,94,106,};
int
MultiperspectivePerceptron::xlat4[] =
    {0,4,5,7,9,11,12,14,16,17,19,22,28,33,39,45,};

MultiperspectivePerceptron::ThreadData::ThreadData(int num_filters,
        int n_local_histories, int local_history_length, int assoc,
        const std::vector<std::vector<int>> &blurrypath_bits, int path_length,
        int ghist_length, int block_size,
        const std::vector<std::vector<std::vector<bool>>> &acyclic_bits,
        const std::vector<int> &modhist_indices,
        const std::vector<int> &modhist_lengths,
        const std::vector<int> &modpath_indices,
        const std::vector<int> &modpath_lengths,
        const std::vector<int> &table_sizes, int n_sign_bits)
      : filterTable(num_filters), acyclic_histories(acyclic_bits.size()),
        acyclic2_histories(acyclic_bits.size()),
        blurrypath_histories(blurrypath_bits.size()),
        ghist_words(ghist_length/block_size+1, 0),
        path_history(path_length, 0), imli_counter(4,0),
        localHistories(n_local_histories, local_history_length),
        recency_stack(assoc), last_ghist_bit(false), occupancy(0)
{
    for (int i = 0; i < blurrypath_bits.size(); i+= 1) {
        blurrypath_histories[i].resize(blurrypath_bits[i].size());
    }

    for (int i = 0; i < acyclic_bits.size(); i += 1) {
        acyclic_histories[i].resize(acyclic_bits[i].size());
        acyclic2_histories[i].resize(acyclic_bits[i].size());
    }

    int max_modhist_idx = -1;
    for (auto &elem : modhist_indices) {
        max_modhist_idx = (max_modhist_idx < elem) ? elem : max_modhist_idx;
    }
    if (max_modhist_idx >= 0) {
        mod_histories.resize(max_modhist_idx + 1);
    }
    for (int i = 0; i < modhist_lengths.size(); i+= 1) {
        mod_histories[modhist_indices[i]].resize(modhist_lengths[i]);
    }

    int max_modpath_idx = -1;
    for (auto &elem : modpath_indices) {
        max_modpath_idx = (max_modpath_idx < elem) ? elem : max_modpath_idx;
    }
    if (max_modpath_idx >= 0) {
        modpath_histories.resize(max_modpath_idx + 1);
    }
    for (int i = 0; i < modpath_lengths.size(); i+= 1) {
        modpath_histories[modpath_indices[i]].resize(modpath_lengths[i]);
    }

    for (int i = 0; i < table_sizes.size(); i += 1) {
        mpreds.push_back(0);
        tables.push_back(std::vector<short int>(table_sizes[i]));
        sign_bits.push_back(std::vector<std::array<bool, 2>>(table_sizes[i]));
        for (int j = 0; j < table_sizes[i]; j += 1) {
            for (int k = 0; k < n_sign_bits; k += 1) {
                sign_bits[i][j][k] = (i & 1) | (k & 1);
            }
        }
    }
}

MultiperspectivePerceptron::MultiperspectivePerceptron(
    const MultiperspectivePerceptronParams &p) : BPredUnit(p),
    blockSize(p.block_size), pcshift(p.pcshift), threshold(p.threshold),
    bias0(p.bias0), bias1(p.bias1), biasmostly0(p.biasmostly0),
    biasmostly1(p.biasmostly1), nbest(p.nbest), tunebits(p.tunebits),
    hshift(p.hshift), imli_mask1(p.imli_mask1), imli_mask4(p.imli_mask4),
    recencypos_mask(p.recencypos_mask), fudge(p.fudge),
    n_sign_bits(p.n_sign_bits), pcbit(p.pcbit), decay(p.decay),
    record_mask(p.record_mask), hash_taken(p.hash_taken),
    tuneonly(p.tuneonly), extra_rounds(p.extra_rounds), speed(p.speed),
    budgetbits(p.budgetbits), speculative_update(p.speculative_update),
    threadData(p.numThreads, nullptr), doing_local(false),
    doing_recency(false), assoc(0), ghist_length(p.initial_ghist_length),
    modghist_length(1), path_length(1), thresholdCounter(0),
    theta(p.initial_theta), extrabits(0), imli_counter_bits(4),
    modhist_indices(), modhist_lengths(), modpath_indices(), modpath_lengths()
{
    fatal_if(speculative_update, "Speculative update not implemented");
}

void
MultiperspectivePerceptron::setExtraBits(int bits)
{
    extrabits = bits;
}

void
MultiperspectivePerceptron::init()
{
    createSpecs();

    for (auto &spec : specs) {
        // initial assignation of values
        table_sizes.push_back(spec->size);
    }

    // Update bit requirements and runtime values
    for (auto &spec : specs) {
        spec->setBitRequirements();
    }
    const MultiperspectivePerceptronParams &p =
        static_cast<const MultiperspectivePerceptronParams &>(params());

    computeBits(p.num_filter_entries, p.num_local_histories,
                p.local_history_length, p.ignore_path_size);

    for (int i = 0; i < threadData.size(); i += 1) {
        threadData[i] = new ThreadData(p.num_filter_entries,
                                       p.num_local_histories,
                                       p.local_history_length, assoc,
                                       blurrypath_bits, path_length,
                                       ghist_length, blockSize, acyclic_bits,
                                       modhist_indices, modhist_lengths,
                                       modpath_indices, modpath_lengths,
                                       table_sizes, n_sign_bits);
    }
}

void
MultiperspectivePerceptron::computeBits(int num_filter_entries,
        int nlocal_histories, int local_history_length, bool ignore_path_size)
{
    int totalbits = extrabits;
    for (auto &imli_bits : imli_counter_bits) {
        totalbits += imli_bits;
    }
    totalbits += ghist_length;
    if (!ignore_path_size) {
        totalbits += path_length * 16;
    }
    totalbits += (threshold >= 0) ? (tunebits * specs.size()) : 0;
    for (auto &len : modhist_lengths) {
        totalbits += len;
    }
    if (!ignore_path_size) {
        for (auto &len : modpath_lengths) {
            totalbits += 16 * len;
        }
    }
    totalbits += doing_local ? (nlocal_histories * local_history_length) : 0;
    totalbits += doing_recency ? (assoc * 16) : 0;

    for (auto &bv : blurrypath_bits) {
        for (auto &bve : bv) {
            totalbits += bve;
        }
    }
    totalbits += num_filter_entries * 2;

    for (auto &abi : acyclic_bits) {
        for (auto &abj : abi) {
            for (auto abk : abj) {
                totalbits += abk;
            }
        }
    }

    int remaining = budgetbits - totalbits;

    // count the tables that have already been assigned sizes
    int num_sized = 0;
    for (int i = 0; i < specs.size(); i +=1) {
        if (table_sizes[i] != 0) {
            int sz = table_sizes[i] * (specs[i]->width + (n_sign_bits - 1));
            totalbits += sz;
            remaining -= sz;
            num_sized += 1;
        }
    }

    // whatever is left, we divide among the rest of the tables
    int table_size_bits = (remaining / (specs.size()-num_sized));
    for (int i = 0; i < specs.size(); i += 1) {
        // if a table doesn't have a size yet, give it one and count those bits
        if (!table_sizes[i]) {
            int my_table_size = table_size_bits /
                (specs[i]->width + (n_sign_bits - 1)); // extra sign bits
            table_sizes[i] = my_table_size;
            totalbits += my_table_size * (specs[i]->width + (n_sign_bits - 1));
        }
    }

    DPRINTF(Branch, "%d bits of metadata so far, %d left out of "
            "%d total budget\n", totalbits, remaining, budgetbits);
    DPRINTF(Branch, "table size is %d bits, %d entries for 5 bit, %d entries "
            "for 6 bit\n", table_size_bits,
            table_size_bits / (5 + (n_sign_bits - 1)),
            table_size_bits / (6 + (n_sign_bits - 1)));
    DPRINTF(Branch, "%d total bits (%0.2fKB)\n", totalbits,
            totalbits / 8192.0);
}

void
MultiperspectivePerceptron::findBest(ThreadID tid,
                                     std::vector<int> &best_preds) const
{
    if (threshold < 0) {
        return;
    }
    struct BestPair
    {
        int index;
        int mpreds;
        bool operator<(BestPair const &bp) const
        {
            return mpreds < bp.mpreds;
        }
    };
    std::vector<BestPair> pairs(best_preds.size());
    for (int i = 0; i < best_preds.size(); i += 1) {
        pairs[i].index = i;
        pairs[i].mpreds = threadData[tid]->mpreds[i];
    }
    std::sort(pairs.begin(), pairs.end());
    for (int i = 0; i < (std::min(nbest, (int) best_preds.size())); i += 1) {
        best_preds[i] = pairs[i].index;
    }
}

unsigned int
MultiperspectivePerceptron::getIndex(ThreadID tid, const MPPBranchInfo &bi,
                                     const HistorySpec &spec, int index) const
{
    unsigned int g = spec.getHash(tid, bi.getPC(), bi.getPC2(), index);
    unsigned long long int h = g;
     // shift the hash from the feature to xor with the hashed PC
    if (hshift < 0) {
        h <<= -hshift;
        h ^= bi.getPC2();
    } else {
        h <<= hshift;
        h ^= bi.getHPC();
    }
    // xor in the imli counter(s) and/or recency position based on the masks
    if ((1ull<<index) & imli_mask1) {
        h ^= threadData[tid]->imli_counter[0];
    }
    if ((1ull<<index) & imli_mask4) {
        h ^= threadData[tid]->imli_counter[3];
    }
    if (doing_recency) {
        if ((1ull<<index) & recencypos_mask) {
            h ^= RECENCYPOS::hash(threadData[tid]->recency_stack, table_sizes,
                    bi.getPC2(), 31, index);
        }
    }
    h %= table_sizes[index];
    return h;
}

int
MultiperspectivePerceptron::computeOutput(ThreadID tid, MPPBranchInfo &bi)
{
    // list of best predictors
    std::vector<int> best_preds(specs.size(), -1);

    // initialize sum
    bi.yout = 0;

    // bias the prediction by whether the local history is
    // one of four distinctive patterns
    int lhist = threadData[tid]->localHistories[bi.getPC()];
    int history_len = threadData[tid]->localHistories.getLocalHistoryLength();
    if (lhist == 0) {
        bi.yout = bias0;
    } else if (lhist == ((1<<history_len)-1)) {
        bi.yout = bias1;
    } else if (lhist == (1<<(history_len-1))) {
        bi.yout = biasmostly0;
    } else if (lhist == ((1<<(history_len-1))-1)) {
        bi.yout = biasmostly1;
    }
    // find the best subset of features to use in case of a low-confidence
    // branch
    findBest(tid, best_preds);

    // begin computation of the sum for low-confidence branch
    int bestval = 0;

    for (int i = 0; i < specs.size(); i += 1) {
        HistorySpec const &spec = *specs[i];
        // get the hash to index the table
        unsigned int hashed_idx = getIndex(tid, bi, spec, i);
        // add the weight; first get the weight's magnitude
        int counter = threadData[tid]->tables[i][hashed_idx];
        // get the sign
        bool sign =
          threadData[tid]->sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
        // apply the transfer function and multiply by a coefficient
        int weight = spec.coeff * ((spec.width == 5) ?
                                   xlat4[counter] : xlat[counter]);
        // apply the sign
        int val = sign ? -weight : weight;
        // add the value
        bi.yout += val;
        // if this is one of those good features, add the value to bestval
        if (threshold >= 0) {
            for (int j = 0;
                 j < std::min(nbest, (int) best_preds.size());
                 j += 1)
            {
                if (best_preds[j] == i) {
                    bestval += val;
                    break;
                }
            }
        }
    }
    // apply a fudge factor to affect when training is triggered
    bi.yout *= fudge;
    return bestval;
}

void
MultiperspectivePerceptron::satIncDec(bool taken, bool &sign, int &counter,
                                      int max_weight) const
{
    if (taken) {
        // increment sign/magnitude
        if (sign) {
            // go toward 0 away from negative max weight
            if (counter == 0) {
                sign = false; // moved to positive 0
            } else {
                counter -= 1;
            }
        } else {
            // go toward max weight away from 0
            if (counter < max_weight) {
                counter += 1;
            }
        }
    } else {
        // decrement sign/magnitude
        if (sign) {
            // go toward negative max weight down from 0
            if (counter < max_weight) {
                counter += 1;
            }
        } else {
            // go toward 0 away from max weight
            if (counter == 0) {
                sign = true; // negative 0
            } else {
                counter -= 1;
            }
        }
    }
}

void
MultiperspectivePerceptron::train(ThreadID tid, MPPBranchInfo &bi, bool taken)
{
    std::vector<std::vector<short int>> &tables = threadData[tid]->tables;
    std::vector<std::vector<std::array<bool, 2>>> &sign_bits =
            threadData[tid]->sign_bits;
    std::vector<int> &mpreds = threadData[tid]->mpreds;
    // was the prediction correct?
    bool correct = (bi.yout >= 1) == taken;
    // what is the magnitude of yout?
    int abs_yout = abs(bi.yout);
    // keep track of mispredictions per table
    if (threshold >= 0) if (!tuneonly || (abs_yout <= threshold)) {
        bool halve = false;

        // for each table, figure out if there was a misprediction
        for (int i = 0; i < specs.size(); i += 1) {
            HistorySpec const &spec = *specs[i];
            // get the hash to index the table
            unsigned int hashed_idx = getIndex(tid, bi, spec, i);
            bool sign = sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
            int counter = tables[i][hashed_idx];
            int weight = spec.coeff * ((spec.width == 5) ?
                                       xlat4[counter] : xlat[counter]);
            if (sign) weight = -weight;
            bool pred = weight >= 1;
            if (pred != taken) {
                mpreds[i] += 1;
                if (mpreds[i] == (1 << tunebits) - 1) {
                    halve = true;
                }
            }
        }
        // if we reach the maximum counter value, halve all the counters
        if (halve) {
            for (int i = 0; i < specs.size(); i += 1) {
                mpreds[i] /= 2;
            }
        }
    }
    // if the branch was predicted incorrectly or the correct
    // prediction was weak, update the weights
    bool do_train = !correct || (abs_yout <= theta);
    if (!do_train) return;

    // adaptive theta training, adapted from O-GEHL
    if (!correct) {
        thresholdCounter += 1;
        if (thresholdCounter >= speed) {
            theta += 1;
            thresholdCounter = 0;
        }
    }
    if (correct && abs_yout < theta) {
        thresholdCounter -= 1;
        if (thresholdCounter <= -speed) {
            theta -= 1;
            thresholdCounter = 0;
        }
    }

    // train the weights, computing what the value of yout
    // would have been if these updates had been applied before
    int newyout = 0;
    for (int i = 0; i < specs.size(); i += 1) {
        HistorySpec const &spec = *specs[i];
        // get the magnitude
        unsigned int hashed_idx = getIndex(tid, bi, spec, i);
        int counter = tables[i][hashed_idx];
        // get the sign
        bool sign = sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
        // increment/decrement if taken/not taken
        satIncDec(taken, sign, counter, (1 << (spec.width - 1)) - 1);
        // update the magnitude and sign
        tables[i][hashed_idx] = counter;
        sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits] = sign;
        int weight = ((spec.width == 5) ? xlat4[counter] : xlat[counter]);
        // update the new version of yout
        if (sign) {
            newyout -= weight;
        } else {
            newyout += weight;
        }
    }

    // if the prediction still would have been incorrect even
    // with the updated weights, update some more weights to
    // try to fix the problem
    if ((newyout >= 1) != taken) {
        if (extra_rounds != -1) {
            int round_counter = 0;
            bool found;
            do {
                // udpate a random weight
                int besti = -1;
                int nrand = random_mt.random<int>() % specs.size();
                int pout;
                found = false;
                for (int j = 0; j < specs.size(); j += 1) {
                    int i = (nrand + j) % specs.size();
                    HistorySpec const &spec = *specs[i];
                    unsigned int hashed_idx = getIndex(tid, bi, spec, i);
                    int counter = tables[i][hashed_idx];
                    bool sign =
                        sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
                    int weight = ((spec.width == 5) ?
                            xlat4[counter] : xlat[counter]);
                    int signed_weight = sign ? -weight : weight;
                    pout = newyout - signed_weight;
                    if ((pout >= 1) == taken) {
                        // we have found a weight that if we blow
                        // it away will help!
                        besti = i;
                        break;
                    }
                }
                if (besti != -1) {
                    int i = besti;
                    HistorySpec const &spec = *specs[i];
                    unsigned int hashed_idx = getIndex(tid, bi, spec, i);
                    int counter = tables[i][hashed_idx];
                    bool sign =
                        sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
                    if (counter > 1) {
                        counter--;
                        tables[i][hashed_idx] = counter;
                    }
                    int weight = ((spec.width == 5) ?
                            xlat4[counter] : xlat[counter]);
                    int signed_weight = sign ? -weight : weight;
                    int out = pout + signed_weight;
                    round_counter += 1;
                    if ((out >= 1) != taken) {
                        found = true;
                    }
                }
            } while (found && round_counter < extra_rounds);
        }
    }
}

void
MultiperspectivePerceptron::uncondBranch(ThreadID tid, Addr pc,
                                         void * &bp_history)
{
    MPPBranchInfo *bi = new MPPBranchInfo(pc, pcshift, false);
    std::vector<unsigned int> &ghist_words = threadData[tid]->ghist_words;

    bp_history = (void *)bi;
    unsigned short int pc2 = pc >> 2;
    bool ab = !(pc & (1<<pcbit));
    for (int i = 0; i < ghist_length / blockSize + 1; i += 1) {
        bool ab_new = (ghist_words[i] >> (blockSize - 1)) & 1;
        ghist_words[i] <<= 1;
        ghist_words[i] |= ab;
        ghist_words[i] &= (1 << blockSize) - 1;
        ab = ab_new;
    }
    memmove(&threadData[tid]->path_history[1],
            &threadData[tid]->path_history[0],
            sizeof(unsigned short int) * (path_length - 1));
    threadData[tid]->path_history[0] = pc2;
}

bool
MultiperspectivePerceptron::lookup(ThreadID tid, Addr instPC,
                                   void * &bp_history)
{
    MPPBranchInfo *bi = new MPPBranchInfo(instPC, pcshift, true);
    bp_history = (void *)bi;

    bool use_static = false;

    if (!threadData[tid]->filterTable.empty()) {
        unsigned int findex =
            bi->getHashFilter(threadData[tid]->last_ghist_bit) %
            threadData[tid]->filterTable.size();
        FilterEntry &f = threadData[tid]->filterTable[findex];
        if (f.alwaysNotTakenSoFar()) {
            bi->filtered = true;
            bi->prediction = false;
            return false;
        } else if (f.alwaysTakenSoFar()) {
            bi->filtered = true;
            bi->prediction = true;
            return true;
        }
        if (f.neverSeen()) {
            use_static = true;
        }
    }

    int bestval = computeOutput(tid, *bi);
    if (use_static) {
        bi->prediction = false;
    } else {
        if (abs(bi->yout) <= threshold) {
            bi->prediction = (bestval >= 1);
        } else {
            bi->prediction = (bi->yout >= 1);
        }
    }

    return bi->prediction;
}

void
MultiperspectivePerceptron::update(ThreadID tid, Addr instPC, bool taken,
                                   void *bp_history, bool squashed,
                                   const StaticInstPtr & inst,
                                   Addr corrTarget)
{
    assert(bp_history);
    MPPBranchInfo *bi = static_cast<MPPBranchInfo*>(bp_history);
    if (squashed) {
        //delete bi;
        return;
    }

    if (bi->isUnconditional()) {
        delete bi;
        return;
    }

    bool do_train = true;

    if (!threadData[tid]->filterTable.empty()) {
        int findex = bi->getHashFilter(threadData[tid]->last_ghist_bit) %
                                       threadData[tid]->filterTable.size();
        FilterEntry &f = threadData[tid]->filterTable[findex];

        // compute this first, so we don't not train on the
        // first time a branch is seen.
        bool transition = false;
        if (f.alwaysNotTakenSoFar() || f.alwaysTakenSoFar()) {
            do_train = false;
        }
        if (taken) {
            if (f.alwaysNotTakenSoFar()) {
                transition = true;
            }
            f.seenTaken = true;
        } else {
            if (f.alwaysTakenSoFar()) {
                transition = true;
            }
            f.seenUntaken = true;
        }
        // is this the first time time the branch has gone both ways?
        if (transition) {
            threadData[tid]->occupancy += 1;
        }
        // for every new dynamic branch, when there ar
        // more than 'decay' number of branches in the
        // filter, blow a random filter entry away
        if (decay && transition &&
            ((threadData[tid]->occupancy > decay) || (decay == 1))) {
            int rnd = random_mt.random<int>() %
                      threadData[tid]->filterTable.size();
            FilterEntry &frand = threadData[tid]->filterTable[rnd];
            if (frand.seenTaken && frand.seenUntaken) {
                threadData[tid]->occupancy -= 1;
            }
            frand.seenTaken = false;
            frand.seenUntaken = false;
        }
    }

    if (do_train) {
        train(tid, *bi, taken);
    }

    enum RecordFiltered
    {
        Imli = 1,
        GHist = 2,
        Path = 4,
        Acyclic = 8,
        Mod = 16,
        Blurry = 32,
        // Should never record a filtered local branch - duh!
        Local = 64,
        Recency = 128
    };

    // four different styles of IMLI
    if (!bi->filtered || (record_mask & Imli)) {
        unsigned int target = corrTarget;
        if (target < bi->getPC()) {
            if (taken) {
                threadData[tid]->imli_counter[0] += 1;
            } else {
                threadData[tid]->imli_counter[0] = 0;
            }
            if (!taken) {
                threadData[tid]->imli_counter[1] += 1;
            } else {
                threadData[tid]->imli_counter[1] = 0;
            }
        } else {
            if (taken) {
                threadData[tid]->imli_counter[2] += 1;
            } else {
                threadData[tid]->imli_counter[2] = 0;
            }
            if (!taken) {
                threadData[tid]->imli_counter[3] += 1;
            } else {
                threadData[tid]->imli_counter[3] = 0;
            }
        }
    }

    bool hashed_taken = hash_taken ? (taken ^ !!(bi->getPC() & (1<<pcbit)))
                                   : taken;
    // record into ghist
    if (!bi->filtered || (record_mask & GHist)) {
        bool ab = hashed_taken;
        assert(threadData[tid]->ghist_words.size() > 0);
        for (int i = 0; i < ghist_length / blockSize + 1; i += 1) {
            unsigned int a = threadData[tid]->ghist_words[i];
            bool ab_new = (a >> (blockSize - 1)) & 1;
            a <<= 1;
            a |= ab;
            ab = ab_new;
            a &= (1 << blockSize) - 1;
            threadData[tid]->ghist_words[i] = a;
        }
    }

    // record into path history
    if (!bi->filtered || (record_mask & Path)) {
        assert(threadData[tid]->path_history.size() > 0);
        memmove(&threadData[tid]->path_history[1],
                &threadData[tid]->path_history[0],
                sizeof(unsigned short int) * (path_length - 1));
        threadData[tid]->path_history[0] = bi->getPC2();
    }

    // record into acyclic history
    if (!bi->filtered || (record_mask & Acyclic)) {
        threadData[tid]->updateAcyclic(hashed_taken, bi->getHPC());
    }

    // record into modulo path history
    if (!bi->filtered || (record_mask & Mod)) {
        for (int ii = 0; ii < modpath_indices.size(); ii += 1) {
            int i = modpath_indices[ii];
            if (bi->getHPC() % (i + 2) == 0) {
                memmove(&threadData[tid]->modpath_histories[i][1],
                        &threadData[tid]->modpath_histories[i][0],
                        sizeof(unsigned short int) * (modpath_lengths[ii]-1));
                threadData[tid]->modpath_histories[i][0] = bi->getPC2();
            }
        }
    }

    // update blurry history
    if (!bi->filtered || (record_mask & Blurry)) {
        std::vector<std::vector<unsigned int>> &blurrypath_histories =
             threadData[tid]->blurrypath_histories;

        for (int i = 0; i < blurrypath_histories.size(); i += 1)
        {
            if (blurrypath_histories[i].size() > 0) {
                unsigned int z = bi->getPC() >> i;
                if (blurrypath_histories[i][0] != z) {
                    memmove(&blurrypath_histories[i][1],
                            &blurrypath_histories[i][0],
                            sizeof(unsigned int) *
                            (blurrypath_histories[i].size() - 1));
                    blurrypath_histories[i][0] = z;
                }
            }
        }
    }

    // record into modulo pattern history
    if (!bi->filtered || (record_mask & Mod)) {
        for (int ii = 0; ii < modhist_indices.size(); ii += 1) {
            int i = modhist_indices[ii];
            if (bi->getHPC() % (i + 2) == 0) {
                for (int j = modhist_lengths[ii] - 1; j > 0; j -= 1) {
                    threadData[tid]->mod_histories[i][j] =
                        threadData[tid]->mod_histories[i][j-1];
                }
                threadData[tid]->mod_histories[i][0] = hashed_taken;
            }
        }
    }

    // insert this PC into the recency stack
    if (doing_recency) {
        if (!bi->filtered || (record_mask & Recency)) {
            threadData[tid]->insertRecency(bi->getPC2(), assoc);
        }
    }

    // record into a local history
    if (!bi->filtered || (record_mask & Local)) {
        threadData[tid]->localHistories.update(bi->getPC(), hashed_taken);
    }

    // update last ghist bit, used to index filter
    threadData[tid]->last_ghist_bit = taken;

    delete bi;
}

void
MultiperspectivePerceptron::btbUpdate(ThreadID tid, Addr branch_pc,
                                      void* &bp_history)
{
}

void
MultiperspectivePerceptron::squash(ThreadID tid, void *bp_history)
{
    assert(bp_history);
    MPPBranchInfo *bi = static_cast<MPPBranchInfo*>(bp_history);
    delete bi;
}

} // namespace branch_prediction
} // namespace gem5
