loop_predictor.cc revision 14081
1/* 2 * Copyright (c) 2014 The University of Wisconsin 3 * 4 * Copyright (c) 2006 INRIA (Institut National de Recherche en 5 * Informatique et en Automatique / French National Research Institute 6 * for Computer Science and Applied Mathematics) 7 * 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are 12 * met: redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer; 14 * redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution; 17 * neither the name of the copyright holders nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 34 * from André Seznec's code. 35 */ 36 37#include "cpu/pred/loop_predictor.hh" 38 39#include "base/random.hh" 40#include "debug/LTage.hh" 41#include "params/LoopPredictor.hh" 42 43LoopPredictor::LoopPredictor(LoopPredictorParams *p) 44 : SimObject(p), logSizeLoopPred(p->logSizeLoopPred), 45 loopTableAgeBits(p->loopTableAgeBits), 46 loopTableConfidenceBits(p->loopTableConfidenceBits), 47 loopTableTagBits(p->loopTableTagBits), 48 loopTableIterBits(p->loopTableIterBits), 49 logLoopTableAssoc(p->logLoopTableAssoc), 50 confidenceThreshold((1 << loopTableConfidenceBits) - 1), 51 loopTagMask((1 << loopTableTagBits) - 1), 52 loopNumIterMask((1 << loopTableIterBits) - 1), 53 loopSetMask((1 << (logSizeLoopPred - logLoopTableAssoc)) - 1), 54 loopUseCounter(-1), 55 withLoopBits(p->withLoopBits), 56 useDirectionBit(p->useDirectionBit), 57 useSpeculation(p->useSpeculation), 58 useHashing(p->useHashing), 59 restrictAllocation(p->restrictAllocation), 60 initialLoopIter(p->initialLoopIter), 61 initialLoopAge(p->initialLoopAge), 62 optionalAgeReset(p->optionalAgeReset) 63{ 64 assert(initialLoopAge <= ((1 << loopTableAgeBits) - 1)); 65} 66 67void 68LoopPredictor::init() 69{ 70 // we use uint16_t type for these vales, so they cannot be more than 71 // 16 bits 72 assert(loopTableTagBits <= 16); 73 assert(loopTableIterBits <= 16); 74 75 assert(logSizeLoopPred >= logLoopTableAssoc); 76 77 ltable = new LoopEntry[ULL(1) << logSizeLoopPred]; 78} 79 80LoopPredictor::BranchInfo* 81LoopPredictor::makeBranchInfo() 82{ 83 return new BranchInfo(); 84} 85 86int 87LoopPredictor::lindex(Addr pc_in, unsigned instShiftAmt) const 88{ 89 // The loop table is implemented as a linear table 90 // If associativity is N (N being 1 << logLoopTableAssoc), 91 // the first N entries are for set 0, the next N entries are for set 1, 92 // and so on. 93 // Thus, this function calculates the set and then it gets left shifted 94 // by logLoopTableAssoc in order to return the index of the first of the 95 // N entries of the set 96 Addr pc = pc_in >> instShiftAmt; 97 if (useHashing) { 98 pc ^= pc_in; 99 } 100 return ((pc & loopSetMask) << logLoopTableAssoc); 101} 102 103int 104LoopPredictor::finallindex(int index, int lowPcBits, int way) const 105{ 106 return (useHashing ? (index ^ ((lowPcBits >> way) << logLoopTableAssoc)) : 107 (index)) 108 + way; 109} 110 111//loop prediction: only used if high confidence 112bool 113LoopPredictor::getLoop(Addr pc, BranchInfo* bi, bool speculative, 114 unsigned instShiftAmt) const 115{ 116 bi->loopHit = -1; 117 bi->loopPredValid = false; 118 bi->loopIndex = lindex(pc, instShiftAmt); 119 120 if (useHashing) { 121 unsigned pcShift = logSizeLoopPred - logLoopTableAssoc; 122 bi->loopIndexB = (pc >> pcShift) & loopSetMask; 123 bi->loopTag = (pc >> pcShift) ^ (pc >> (pcShift + loopTableTagBits)); 124 bi->loopTag &= loopTagMask; 125 } else { 126 unsigned pcShift = instShiftAmt + logSizeLoopPred - logLoopTableAssoc; 127 bi->loopTag = (pc >> pcShift) & loopTagMask; 128 // bi->loopIndexB is not used without hash 129 } 130 131 for (int i = 0; i < (1 << logLoopTableAssoc); i++) { 132 int idx = finallindex(bi->loopIndex, bi->loopIndexB, i); 133 if (ltable[idx].tag == bi->loopTag) { 134 bi->loopHit = i; 135 bi->loopPredValid = calcConf(idx); 136 137 uint16_t iter = speculative ? ltable[idx].currentIterSpec 138 : ltable[idx].currentIter; 139 140 if ((iter + 1) == ltable[idx].numIter) { 141 return useDirectionBit ? !(ltable[idx].dir) : false; 142 } else { 143 return useDirectionBit ? (ltable[idx].dir) : true; 144 } 145 } 146 } 147 return false; 148} 149 150bool 151LoopPredictor::calcConf(int index) const 152{ 153 return ltable[index].confidence == confidenceThreshold; 154} 155 156void 157LoopPredictor::specLoopUpdate(bool taken, BranchInfo* bi) 158{ 159 if (bi->loopHit>=0) { 160 int index = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit); 161 if (taken != ltable[index].dir) { 162 ltable[index].currentIterSpec = 0; 163 } else { 164 ltable[index].currentIterSpec = 165 (ltable[index].currentIterSpec + 1) & loopNumIterMask; 166 } 167 } 168} 169 170bool 171LoopPredictor::optionalAgeInc() const 172{ 173 return false; 174} 175 176void 177LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred) 178{ 179 int idx = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit); 180 if (bi->loopHit >= 0) { 181 //already a hit 182 if (bi->loopPredValid) { 183 if (taken != bi->loopPred) { 184 // free the entry 185 ltable[idx].numIter = 0; 186 ltable[idx].age = 0; 187 ltable[idx].confidence = 0; 188 ltable[idx].currentIter = 0; 189 return; 190 } else if (bi->loopPred != tage_pred || optionalAgeInc()) { 191 DPRINTF(LTage, "Loop Prediction success:%lx\n",pc); 192 unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits); 193 } 194 } 195 196 ltable[idx].currentIter = 197 (ltable[idx].currentIter + 1) & loopNumIterMask; 198 if (ltable[idx].currentIter > ltable[idx].numIter) { 199 ltable[idx].confidence = 0; 200 if (ltable[idx].numIter != 0) { 201 // free the entry 202 ltable[idx].numIter = 0; 203 if (optionalAgeReset) { 204 ltable[idx].age = 0; 205 } 206 } 207 } 208 209 if (taken != (useDirectionBit ? ltable[idx].dir : true)) { 210 if (ltable[idx].currentIter == ltable[idx].numIter) { 211 DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc); 212 unsignedCtrUpdate(ltable[idx].confidence, true, 213 loopTableConfidenceBits); 214 //just do not predict when the loop count is 1 or 2 215 if (ltable[idx].numIter < 3) { 216 // free the entry 217 ltable[idx].dir = taken; // ignored if no useDirectionBit 218 ltable[idx].numIter = 0; 219 ltable[idx].age = 0; 220 ltable[idx].confidence = 0; 221 } 222 } else { 223 DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc); 224 if (ltable[idx].numIter == 0) { 225 // first complete nest; 226 ltable[idx].confidence = 0; 227 ltable[idx].numIter = ltable[idx].currentIter; 228 } else { 229 //not the same number of iterations as last time: free the 230 //entry 231 ltable[idx].numIter = 0; 232 if (optionalAgeReset) { 233 ltable[idx].age = 0; 234 } 235 ltable[idx].confidence = 0; 236 } 237 } 238 ltable[idx].currentIter = 0; 239 } 240 241 } else if (useDirectionBit ? (bi->predTaken != taken) : taken) { 242 if ((random_mt.random<int>() & 3) == 0 || !restrictAllocation) { 243 //try to allocate an entry on taken branch 244 int nrand = random_mt.random<int>(); 245 for (int i = 0; i < (1 << logLoopTableAssoc); i++) { 246 int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1); 247 idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit); 248 if (ltable[idx].age == 0) { 249 DPRINTF(LTage, 250 "Allocating loop pred entry for branch %lx\n", 251 pc); 252 ltable[idx].dir = !taken; // ignored if no useDirectionBit 253 ltable[idx].tag = bi->loopTag; 254 ltable[idx].numIter = 0; 255 ltable[idx].age = initialLoopAge; 256 ltable[idx].confidence = 0; 257 ltable[idx].currentIter = initialLoopIter; 258 break; 259 260 } else { 261 ltable[idx].age--; 262 } 263 if (restrictAllocation) { 264 break; 265 } 266 } 267 } 268 } 269} 270 271bool 272LoopPredictor::loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch, 273 BranchInfo* bi, bool prev_pred_taken, unsigned instShiftAmt) 274{ 275 bool pred_taken = prev_pred_taken; 276 if (cond_branch) { 277 // loop prediction 278 bi->loopPred = getLoop(branch_pc, bi, useSpeculation, instShiftAmt); 279 280 if ((loopUseCounter >= 0) && bi->loopPredValid) { 281 pred_taken = bi->loopPred; 282 bi->loopPredUsed = true; 283 } 284 285 if (useSpeculation) { 286 specLoopUpdate(pred_taken, bi); 287 } 288 } 289 290 return pred_taken; 291} 292 293void 294LoopPredictor::squash(ThreadID tid, BranchInfo *bi) 295{ 296 if (bi->loopHit >= 0) { 297 int idx = finallindex(bi->loopIndex, 298 bi->loopIndexB, 299 bi->loopHit); 300 ltable[idx].currentIterSpec = bi->currentIter; 301 } 302} 303 304void 305LoopPredictor::squashLoop(BranchInfo* bi) 306{ 307 if (bi->loopHit >= 0) { 308 int idx = finallindex(bi->loopIndex, 309 bi->loopIndexB, 310 bi->loopHit); 311 ltable[idx].currentIterSpec = bi->currentIter; 312 } 313} 314 315void 316LoopPredictor::updateStats(bool taken, BranchInfo* bi) 317{ 318 if (taken == bi->loopPred) { 319 loopPredictorCorrect++; 320 } else { 321 loopPredictorWrong++; 322 } 323} 324 325void 326LoopPredictor::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, 327 bool tage_pred, BranchInfo* bi, 328 unsigned instShiftAmt) 329{ 330 if (useSpeculation) { 331 // recalculate loop prediction without speculation 332 // It is ok to overwrite the loop prediction fields in bi 333 // as the stats have already been updated with the previous 334 // values 335 bi->loopPred = getLoop(branch_pc, bi, false, instShiftAmt); 336 } 337 338 if (bi->loopPredValid) { 339 if (bi->predTaken != bi->loopPred) { 340 signedCtrUpdate(loopUseCounter, 341 (bi->loopPred == taken), 342 withLoopBits); 343 } 344 } 345 346 loopUpdate(branch_pc, taken, bi, tage_pred); 347} 348 349void 350LoopPredictor::regStats() 351{ 352 loopPredictorCorrect 353 .name(name() + ".loopPredictorCorrect") 354 .desc("Number of times the loop predictor is the provider and " 355 "the prediction is correct"); 356 357 loopPredictorWrong 358 .name(name() + ".loopPredictorWrong") 359 .desc("Number of times the loop predictor is the provider and " 360 "the prediction is wrong"); 361} 362 363size_t 364LoopPredictor::getSizeInBits() const 365{ 366 return (1ULL << logSizeLoopPred) * 367 ((useSpeculation ? 3 : 2) * loopTableIterBits + 368 loopTableConfidenceBits + loopTableTagBits + 369 loopTableAgeBits + useDirectionBit); 370} 371 372LoopPredictor * 373LoopPredictorParams::create() 374{ 375 return new LoopPredictor(this); 376} 377