# HG changeset patch # User Taylor Lloyd # Date 1373913514 21600 # Mon Jul 15 12:38:34 2013 -0600 # Node ID 3c2dda87aca0fe25493025216f85e1e2bce6ed14 # Parent 13ffc0066b76a257620b767892c11d58f71b8515 Added GaG (global-global) branch predictor. -Fixed issues raised during review diff -r 13ffc0066b76 -r 3c2dda87aca0 src/cpu/pred/BranchPredictor.py --- a/src/cpu/pred/BranchPredictor.py Thu Jul 11 21:57:04 2013 -0500 +++ b/src/cpu/pred/BranchPredictor.py Mon Jul 15 12:38:34 2013 -0600 @@ -36,7 +36,7 @@ numThreads = Param.Unsigned(1, "Number of threads") predType = Param.String("tournament", - "Branch predictor type ('local', 'tournament')") + "Branch predictor type ('local', 'global', 'tournament')") localPredictorSize = Param.Unsigned(2048, "Size of local predictor") localCtrBits = Param.Unsigned(2, "Bits per counter") localHistoryTableSize = Param.Unsigned(2048, "Size of local history table") diff -r 13ffc0066b76 -r 3c2dda87aca0 src/cpu/pred/SConscript --- a/src/cpu/pred/SConscript Thu Jul 11 21:57:04 2013 -0500 +++ b/src/cpu/pred/SConscript Mon Jul 15 12:38:34 2013 -0600 @@ -35,6 +35,7 @@ Source('bpred_unit.cc') Source('2bit_local.cc') + Source('global.cc') Source('btb.cc') Source('ras.cc') Source('tournament.cc') diff -r 13ffc0066b76 -r 3c2dda87aca0 src/cpu/pred/bpred_unit.cc --- a/src/cpu/pred/bpred_unit.cc Thu Jul 11 21:57:04 2013 -0500 +++ b/src/cpu/pred/bpred_unit.cc Mon Jul 15 12:38:34 2013 -0600 @@ -33,6 +33,7 @@ #include "cpu/pred/2bit_local.hh" #include "cpu/pred/bpred_unit_impl.hh" +#include "cpu/pred/global.hh" #include "cpu/pred/tournament.hh" BPredUnit * @@ -43,6 +44,8 @@ return new LocalBP(this); } else if (predType == "tournament") { return new TournamentBP(this); + } else if (predType == "global") { + return new GlobalBP(this); } else { fatal("Invalid BP selected!"); } diff -r 13ffc0066b76 -r 3c2dda87aca0 src/cpu/pred/global.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/pred/global.hh Mon Jul 15 12:38:34 2013 -0600 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * 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; + * neither the name of the copyright holders 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 + * OWNER 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. + * + * Authors: Kevin Lim + * Taylor Lloyd + */ + +#ifndef __CPU_PRED_GLOBAL_PRED_HH__ +#define __CPU_PRED_GLOBAL_PRED_HH__ + +#include + +#include "base/types.hh" +#include "cpu/pred/bpred_unit.hh" +#include "cpu/pred/sat_counter.hh" + +/** + * Implements a set global-global (gAG) predictor. It uses the branch history + * to index into a table of counters. Global history is speculatively updated, + * and corrected during a squash. + */ +class GlobalBP : public BPredUnit +{ + public: + /** + * Default branch predictor constructor. + */ + GlobalBP(const Params *params); + /** + * Looks up the given address in the branch predictor and returns + * a true/false value as to whether it is taken. Also creates a + * BPHistory object to store any state it will need on squash/update. + * @param branch_addr The address of the branch to look up. + * @param bp_history Pointer that will be set to the BPHistory object. + * @return Whether or not the branch is taken. + */ + bool lookup(Addr branch_addr, void * &bp_history); + + /** + * Records that there was an unconditional branch, and modifies + * the bp history to point to an object that has the previous + * global history stored in it. + * @param bp_history Pointer that will be set to the BPHistory object. + */ + void uncondBranch(void * &bp_history); + /** + * Updates the branch predictor to Not Taken if a BTB entry is + * invalid or not found. + * @param branch_addr The address of the branch to look up. + * @param bp_history Pointer to any bp history state. + * @return Whether or not the branch is taken. + */ + void btbUpdate(Addr branch_addr, void * &bp_history); + /** + * Updates the branch predictor with the actual result of a branch. + * @param branch_addr The address of the branch to update. + * @param taken Whether or not the branch was taken. + * @param bp_history Pointer to the BPHistory object that was created + * when the branch was predicted. + * @param squashed is set when this function is called during a squash + * operation. + */ + void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); + + /** + * Restores the global branch history on a squash. + * @param bp_history Pointer to the BPHistory object that has the + * previous global branch history in it. + */ + void squash(void *bp_history); + + private: + /** Updates global history as taken. */ + inline void updateGlobalHistTaken(); + + /** Updates global history as not taken. */ + inline void updateGlobalHistNotTaken(); + + /** + * The branch history information that is created with a prediction. + * It's used for recovery upon a squash, and discarded for correct + * predictions. + */ + struct GlobalHistory { + unsigned globalHistory; + bool predTaken; + }; + + /** Table of the global counters */ + std::vector globalCtrs; + + /** Number of entries in the global predictor */ + unsigned globalPredictorSize; + + /** Number of bits required to index the predictor */ + unsigned globalHistoryBits; + + /** Number of bits in each counter of the global predictor */ + unsigned globalCtrBits; + + /** Global history register. */ + unsigned globalHistory; + + /** The mask to ensure no extra history is stored */ + unsigned globalHistoryMask; + + /** Counter threshold to decide taken/untaken */ + unsigned threshold; +}; +#endif // __CPU_PRED_GLOBAL_PRED_HH__ diff -r 13ffc0066b76 -r 3c2dda87aca0 src/cpu/pred/global.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/pred/global.cc Mon Jul 15 12:38:34 2013 -0600 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * 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; + * neither the name of the copyright holders 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 + * OWNER 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. + * + * Authors: Kevin Lim + * Taylor Lloyd + */ + +#include "base/intmath.hh" +#include "base/misc.hh" +#include "base/trace.hh" +#include "cpu/pred/global.hh" +#include "debug/Fetch.hh" + +GlobalBP::GlobalBP(const Params *params) + : BPredUnit(params), + globalPredictorSize(params->globalPredictorSize), + globalCtrBits(params->globalCtrBits) +{ + if (!isPowerOf2(globalPredictorSize)) { + fatal("Invalid global predictor size! (Must be power of 2)\n"); + } + + //Calculate logarithm to get history bits (cheat for powers of two) + int globalHistoryBits = 0; + for (int size = globalPredictorSize; size != 0; size = size >> 1) + { + globalHistoryBits++; + } + + // Setup the array of counters for the global predictor. + globalCtrs.resize(globalPredictorSize); + + for (unsigned i = 0; i < globalPredictorSize; ++i) + globalCtrs[i].setBits(globalCtrBits); + + DPRINTF(Fetch, "Branch predictor: global predictor size: %i\n", + globalPredictorSize); + DPRINTF(Fetch, "Branch predictor: global history size: %i\n", globalHistoryBits); + DPRINTF(Fetch, "Branch predictor: global counter bits: %i\n", globalCtrBits); + + //set the initial history + globalHistory = 0; + //setup the history mask + globalHistoryMask = (1 << globalHistoryBits) - 1; + //setup the 'predict taken' threshold + threshold = (1 << (globalCtrBits - 1)) - 1; +} + +inline void +GlobalBP::updateGlobalHistTaken() +{ + globalHistory = (globalHistory << 1) | 1; + globalHistory = globalHistory & globalHistoryMask; +} + +inline void +GlobalBP::updateGlobalHistNotTaken() +{ + globalHistory = globalHistory << 1; + globalHistory = globalHistory & globalHistoryMask; +} + +void +GlobalBP::btbUpdate(Addr branch_addr, void * &bp_history) +{ + //Update Global History to Not Taken + globalHistory = globalHistory & (globalHistoryMask - 1); +} + +bool +GlobalBP::lookup(Addr branch_addr, void * &bp_history) +{ + bool taken = globalCtrs[globalHistory].read() > threshold; + + DPRINTF(Fetch, "Branch predictor: prediction is %i.\n", + (int)taken); + GlobalHistory *history = new GlobalHistory; + history->globalHistory = globalHistory; + history->predTaken = taken; + bp_history = (void *)history; + + if (taken) { + updateGlobalHistTaken(); + return true; + } else { + updateGlobalHistNotTaken(); + return false; + } +} + +void +GlobalBP::uncondBranch(void * &bp_history) +{ + //Create the history + GlobalHistory *history = new GlobalHistory; + history->globalHistory = globalHistory; + history->predTaken = true; + bp_history = (void *)history; + updateGlobalHistTaken(); +} + +void +GlobalBP::update(Addr branch_addr, bool taken, void *bp_history, bool squashed) +{ + DPRINTF(Fetch, "Predictor: Updating predictive counters\n"); + if (bp_history) { + GlobalHistory *history = (GlobalHistory *) bp_history; + if(taken) { + globalCtrs[history->globalHistory].increment(); + } else { + globalCtrs[history->globalHistory].decrement(); + } + if(squashed) { + // Recover using our past history + DPRINTF(Fetch, "Predictor: Update - recovering from squash\n"); + globalHistory = (history->globalHistory << 1) | taken; + globalHistory = globalHistory & globalHistoryMask; + } + delete history; + bp_history = 0; + } +} + +void +GlobalBP::squash(void *bp_history) +{ + DPRINTF(Fetch, "Predictor: Recovering from squash\n"); + GlobalHistory *history = (GlobalHistory *)bp_history; + globalHistory = history->globalHistory; + delete history; + bp_history = 0; +}