1/* 2 * Copyright (c) 2011, 2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2004-2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Kevin Lim 41 */ 42 43#include "cpu/pred/tournament.hh" 44 45#include "base/bitfield.hh" 46#include "base/intmath.hh" 47 48TournamentBP::TournamentBP(const TournamentBPParams *params) 49 : BPredUnit(params), 50 localPredictorSize(params->localPredictorSize), 51 localCtrBits(params->localCtrBits), 52 localCtrs(localPredictorSize, SatCounter(localCtrBits)), 53 localHistoryTableSize(params->localHistoryTableSize), 54 localHistoryBits(ceilLog2(params->localPredictorSize)), 55 globalPredictorSize(params->globalPredictorSize), 56 globalCtrBits(params->globalCtrBits), 57 globalCtrs(globalPredictorSize, SatCounter(globalCtrBits)), 58 globalHistory(params->numThreads, 0), 59 globalHistoryBits( 60 ceilLog2(params->globalPredictorSize) > 61 ceilLog2(params->choicePredictorSize) ? 62 ceilLog2(params->globalPredictorSize) : 63 ceilLog2(params->choicePredictorSize)), 64 choicePredictorSize(params->choicePredictorSize), 65 choiceCtrBits(params->choiceCtrBits), 66 choiceCtrs(choicePredictorSize, SatCounter(choiceCtrBits)) 67{ 68 if (!isPowerOf2(localPredictorSize)) { 69 fatal("Invalid local predictor size!\n"); 70 } 71 72 if (!isPowerOf2(globalPredictorSize)) { 73 fatal("Invalid global predictor size!\n"); 74 } 75 76 localPredictorMask = mask(localHistoryBits); 77 78 if (!isPowerOf2(localHistoryTableSize)) { 79 fatal("Invalid local history table size!\n"); 80 } 81 82 //Setup the history table for the local table 83 localHistoryTable.resize(localHistoryTableSize); 84 85 for (int i = 0; i < localHistoryTableSize; ++i) 86 localHistoryTable[i] = 0; 87 88 // Set up the global history mask 89 // this is equivalent to mask(log2(globalPredictorSize) 90 globalHistoryMask = globalPredictorSize - 1; 91 92 if (!isPowerOf2(choicePredictorSize)) { 93 fatal("Invalid choice predictor size!\n"); 94 } 95 96 // Set up choiceHistoryMask 97 // this is equivalent to mask(log2(choicePredictorSize) 98 choiceHistoryMask = choicePredictorSize - 1; 99 100 //Set up historyRegisterMask 101 historyRegisterMask = mask(globalHistoryBits); 102 103 //Check that predictors don't use more bits than they have available 104 if (globalHistoryMask > historyRegisterMask) { 105 fatal("Global predictor too large for global history bits!\n"); 106 } 107 if (choiceHistoryMask > historyRegisterMask) { 108 fatal("Choice predictor too large for global history bits!\n"); 109 } 110 111 if (globalHistoryMask < historyRegisterMask && 112 choiceHistoryMask < historyRegisterMask) { 113 inform("More global history bits than required by predictors\n"); 114 } 115 116 // Set thresholds for the three predictors' counters 117 // This is equivalent to (2^(Ctr))/2 - 1 118 localThreshold = (ULL(1) << (localCtrBits - 1)) - 1; 119 globalThreshold = (ULL(1) << (globalCtrBits - 1)) - 1; 120 choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1; 121} 122 123inline 124unsigned 125TournamentBP::calcLocHistIdx(Addr &branch_addr) 126{ 127 // Get low order bits after removing instruction offset. 128 return (branch_addr >> instShiftAmt) & (localHistoryTableSize - 1); 129} 130 131inline 132void 133TournamentBP::updateGlobalHistTaken(ThreadID tid) 134{ 135 globalHistory[tid] = (globalHistory[tid] << 1) | 1; 136 globalHistory[tid] = globalHistory[tid] & historyRegisterMask; 137} 138 139inline 140void 141TournamentBP::updateGlobalHistNotTaken(ThreadID tid) 142{ 143 globalHistory[tid] = (globalHistory[tid] << 1); 144 globalHistory[tid] = globalHistory[tid] & historyRegisterMask; 145} 146 147inline 148void 149TournamentBP::updateLocalHistTaken(unsigned local_history_idx) 150{ 151 localHistoryTable[local_history_idx] = 152 (localHistoryTable[local_history_idx] << 1) | 1; 153} 154 155inline 156void 157TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx) 158{ 159 localHistoryTable[local_history_idx] = 160 (localHistoryTable[local_history_idx] << 1); 161} 162 163 164void 165TournamentBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) 166{ 167 unsigned local_history_idx = calcLocHistIdx(branch_addr); 168 //Update Global History to Not Taken (clear LSB) 169 globalHistory[tid] &= (historyRegisterMask & ~ULL(1)); 170 //Update Local History to Not Taken 171 localHistoryTable[local_history_idx] = 172 localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1)); 173} 174 175bool 176TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) 177{ 178 bool local_prediction; 179 unsigned local_history_idx; 180 unsigned local_predictor_idx; 181 182 bool global_prediction; 183 bool choice_prediction; 184 185 //Lookup in the local predictor to get its branch prediction 186 local_history_idx = calcLocHistIdx(branch_addr); 187 local_predictor_idx = localHistoryTable[local_history_idx] 188 & localPredictorMask; 189 local_prediction = localCtrs[local_predictor_idx] > localThreshold; 190 191 //Lookup in the global predictor to get its branch prediction 192 global_prediction = globalThreshold < 193 globalCtrs[globalHistory[tid] & globalHistoryMask]; 194 195 //Lookup in the choice predictor to see which one to use 196 choice_prediction = choiceThreshold < 197 choiceCtrs[globalHistory[tid] & choiceHistoryMask]; 198 199 // Create BPHistory and pass it back to be recorded. 200 BPHistory *history = new BPHistory; 201 history->globalHistory = globalHistory[tid]; 202 history->localPredTaken = local_prediction; 203 history->globalPredTaken = global_prediction; 204 history->globalUsed = choice_prediction; 205 history->localHistoryIdx = local_history_idx; 206 history->localHistory = local_predictor_idx; 207 bp_history = (void *)history; 208 209 assert(local_history_idx < localHistoryTableSize); 210 211 // Speculative update of the global history and the 212 // selected local history. 213 if (choice_prediction) { 214 if (global_prediction) { 215 updateGlobalHistTaken(tid); 216 updateLocalHistTaken(local_history_idx); 217 return true; 218 } else { 219 updateGlobalHistNotTaken(tid); 220 updateLocalHistNotTaken(local_history_idx); 221 return false; 222 } 223 } else { 224 if (local_prediction) { 225 updateGlobalHistTaken(tid); 226 updateLocalHistTaken(local_history_idx); 227 return true; 228 } else { 229 updateGlobalHistNotTaken(tid); 230 updateLocalHistNotTaken(local_history_idx); 231 return false; 232 } 233 } 234} 235 236void 237TournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history) 238{ 239 // Create BPHistory and pass it back to be recorded. 240 BPHistory *history = new BPHistory; 241 history->globalHistory = globalHistory[tid]; 242 history->localPredTaken = true; 243 history->globalPredTaken = true; 244 history->globalUsed = true; 245 history->localHistoryIdx = invalidPredictorIndex; 246 history->localHistory = invalidPredictorIndex; 247 bp_history = static_cast<void *>(history); 248 249 updateGlobalHistTaken(tid); 250} 251 252void 253TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, 254 void *bp_history, bool squashed, 255 const StaticInstPtr & inst, Addr corrTarget) 256{ 257 assert(bp_history); 258 259 BPHistory *history = static_cast<BPHistory *>(bp_history); 260 261 unsigned local_history_idx = calcLocHistIdx(branch_addr); 262 263 assert(local_history_idx < localHistoryTableSize); 264 265 // Unconditional branches do not use local history. 266 bool old_local_pred_valid = history->localHistory != 267 invalidPredictorIndex; 268 269 // If this is a misprediction, restore the speculatively 270 // updated state (global history register and local history) 271 // and update again. 272 if (squashed) { 273 // Global history restore and update 274 globalHistory[tid] = (history->globalHistory << 1) | taken; 275 globalHistory[tid] &= historyRegisterMask; 276 277 // Local history restore and update. 278 if (old_local_pred_valid) { 279 localHistoryTable[local_history_idx] = 280 (history->localHistory << 1) | taken; 281 } 282 283 return; 284 } 285 286 unsigned old_local_pred_index = history->localHistory & 287 localPredictorMask; 288 289 assert(old_local_pred_index < localPredictorSize); 290 291 // Update the choice predictor to tell it which one was correct if 292 // there was a prediction. 293 if (history->localPredTaken != history->globalPredTaken && 294 old_local_pred_valid) 295 { 296 // If the local prediction matches the actual outcome, 297 // decrement the counter. Otherwise increment the 298 // counter. 299 unsigned choice_predictor_idx = 300 history->globalHistory & choiceHistoryMask; 301 if (history->localPredTaken == taken) { 302 choiceCtrs[choice_predictor_idx]--; 303 } else if (history->globalPredTaken == taken) { 304 choiceCtrs[choice_predictor_idx]++; 305 } 306 } 307 308 // Update the counters with the proper 309 // resolution of the branch. Histories are updated 310 // speculatively, restored upon squash() calls, and 311 // recomputed upon update(squash = true) calls, 312 // so they do not need to be updated. 313 unsigned global_predictor_idx = 314 history->globalHistory & globalHistoryMask; 315 if (taken) { 316 globalCtrs[global_predictor_idx]++; 317 if (old_local_pred_valid) { 318 localCtrs[old_local_pred_index]++; 319 } 320 } else { 321 globalCtrs[global_predictor_idx]--; 322 if (old_local_pred_valid) { 323 localCtrs[old_local_pred_index]--; 324 } 325 } 326 327 // We're done with this history, now delete it. 328 delete history; 329} 330 331void 332TournamentBP::squash(ThreadID tid, void *bp_history) 333{ 334 BPHistory *history = static_cast<BPHistory *>(bp_history); 335 336 // Restore global history to state prior to this branch. 337 globalHistory[tid] = history->globalHistory; 338 339 // Restore local history 340 if (history->localHistoryIdx != invalidPredictorIndex) { 341 localHistoryTable[history->localHistoryIdx] = history->localHistory; 342 } 343 344 // Delete this BPHistory now that we're done with it. 345 delete history; 346} 347 348TournamentBP* 349TournamentBPParams::create() 350{ 351 return new TournamentBP(this); 352} 353 354#ifdef DEBUG 355int 356TournamentBP::BPHistory::newCount = 0; 357#endif 358