1/* 2 * Copyright 2019 Texas A&M University 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * 3. Neither the name of the copyright holder nor the names of its 15 * contributors may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Author: Daniel A. Jiménez 31 * Adapted to gem5 by: Javier Bueno Hedo 32 * 33 */ 34 35/* 36 * Multiperspective Perceptron Predictor (by Daniel A. Jiménez) 37 */ 38 39#ifndef __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ 40#define __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ 41 42#include <array> 43#include <vector> 44 45#include "cpu/pred/bpred_unit.hh" 46#include "params/MultiperspectivePerceptron.hh" 47 48class MultiperspectivePerceptron : public BPredUnit 49{ 50 protected: 51 /** 52 * Branch information data 53 */ 54 class MPPBranchInfo { 55 /** pc of the branch */ 56 const unsigned int pc; 57 /** pc of the branch, shifted 2 bits to the right */ 58 const unsigned short int pc2; 59 /** pc of the branch, hashed */ 60 const unsigned short int hpc; 61 /** Whether this is a conditional branch */ 62 const bool condBranch; 63 64 /** 65 * PC Hash functions 66 */ 67 static inline unsigned int hash1(unsigned int a) 68 { 69 a = (a ^ 0xdeadbeef) + (a<<4); 70 a = a ^ (a>>10); 71 a = a + (a<<7); 72 a = a ^ (a>>13); 73 return a; 74 } 75 76 static inline unsigned int hash2(unsigned int key) 77 { 78 int c2 = 0x27d4eb2d; // a prime or an odd constant 79 key = (key ^ 61) ^ (key >> 16); 80 key = key + (key << 3); 81 key = key ^ (key >> 4); 82 key = key * c2; 83 key = key ^ (key >> 15); 84 return key; 85 } 86 87 static inline unsigned int hash(unsigned int key, unsigned int i) 88 { 89 return hash2(key) * i + hash1(key); 90 } 91 92 static inline unsigned int hashPC(unsigned int pc, int pcshift) 93 { 94 if (pcshift < 0) { 95 return hash(pc, -pcshift); 96 } else if (pcshift < 11) { 97 unsigned int x = pc; 98 x ^= (pc >> pcshift); 99 return x; 100 } else { 101 return pc >> (pcshift-11); 102 } 103 } 104 105 public: 106 /** Whether this branch has been filtered by the prefetcher */ 107 bool filtered; 108 /** Result of the prediction (true is taken) */ 109 bool prediction; 110 /** Score of the perceptron */ 111 int yout; 112 113 MPPBranchInfo(Addr _pc, int pcshift, bool cb) : pc((unsigned int)_pc), 114 pc2(pc >> 2), hpc(hashPC(pc, pcshift)), condBranch(cb), 115 filtered(false), prediction(false), yout(0) 116 { } 117 118 unsigned int getPC() const 119 { 120 return pc; 121 } 122 unsigned short int getPC2() const 123 { 124 return pc2; 125 } 126 unsigned short int getHPC() const 127 { 128 return hpc; 129 } 130 unsigned int getHashFilter(bool last_ghist_bit) const 131 { 132 return last_ghist_bit ^ hpc; 133 } 134 bool isUnconditional() const 135 { 136 return !condBranch; 137 } 138 }; 139 140 /** 141 * Entry of the branch filter 142 */ 143 struct FilterEntry { 144 /** Has this branch been taken at least once? */ 145 bool seenTaken; 146 /** Has this branch been not taken at least once? */ 147 bool seenUntaken; 148 149 FilterEntry() : seenTaken(false), seenUntaken(false) {} 150 151 /** Whether this branch has always been observed as not taken */ 152 bool alwaysNotTakenSoFar() const { 153 return seenUntaken & !seenTaken; 154 } 155 /** Whether this branch has always been observed as taken */ 156 bool alwaysTakenSoFar() const { 157 return seenTaken & !seenUntaken; 158 } 159 /** Whether this branch has been observed before */ 160 bool neverSeen() const { 161 return !seenTaken && !seenUntaken; 162 } 163 }; 164 165 166 /** 167 * Local history entries, each enty contains the history of directions 168 * taken by a given branch. 169 */ 170 class LocalHistories { 171 /** The array of histories */ 172 std::vector<unsigned int> localHistories; 173 /** Size in bits of each history entry */ 174 const int localHistoryLength; 175 176 /** Index function given the pc of the branch */ 177 unsigned int index(Addr pc) const { 178 return (pc >> 2) % localHistories.size(); 179 } 180 public: 181 LocalHistories(int nlocal_histories, int histo_len) : 182 localHistories(nlocal_histories), localHistoryLength(histo_len) {} 183 184 /** Obtains the local history entry of a given branch */ 185 unsigned int operator[](Addr pc) const 186 { 187 return localHistories[index(pc)]; 188 } 189 190 /** Adds a history bit to the local history entry of a given branch */ 191 void update(Addr pc, bool value) 192 { 193 assert(localHistories.size() > 0); 194 unsigned int &pos = localHistories[index(pc)]; 195 pos <<= 1; 196 pos |= value; 197 pos &= ((1<<localHistoryLength)-1); 198 } 199 200 /** Returns the number of bits of each local history entry */ 201 int getLocalHistoryLength() const 202 { 203 return localHistoryLength; 204 } 205 206 /** Size in bits required by all history entries */ 207 int getSize() const 208 { 209 return localHistoryLength * localHistories.size(); 210 } 211 }; 212 213 /** 214 * Base class to implement the predictor tables. 215 */ 216 struct HistorySpec { 217 /** First parameter */ 218 const int p1; 219 /** Second parameter */ 220 const int p2; 221 /** Third parameter */ 222 const int p3; 223 /** Coefficient of the feature, models the accuracy of the feature */ 224 const double coeff; 225 /** Pre-assigned size in bits assigned to this feature */ 226 const int size; 227 /** Width of the table in bits */ 228 const int width; 229 /** Reference to the branch predictor class */ 230 MultiperspectivePerceptron &mpp; 231 232 HistorySpec(int _p1, int _p2, int _p3, double _coeff, int _size, 233 int _width, MultiperspectivePerceptron &_mpp) : p1(_p1), 234 p2(_p2), p3(_p3), coeff(_coeff), size(_size), width(_width), 235 mpp(_mpp) 236 {} 237 238 /** 239 * Gets the hash to index the table, using the pc of the branch, 240 * and the index of the table. 241 * @param tid Thread ID of the branch 242 * @param pc address of the branch 243 * @param pc2 address of the branch shifted 2 bits to the right 244 * @param t integer index of the table 245 * @result resulting hash value that will be used to index the table 246 */ 247 virtual unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) 248 const = 0; 249 /** 250 * Sets the size requirements of the table, used when initializing 251 * to set the proper size of the tables 252 */ 253 virtual void setBitRequirements() const {} 254 }; 255 256 /** Predictor parameters */ 257 const int blockSize; 258 const int pcshift; 259 const int threshold; 260 const int bias0; 261 const int bias1; 262 const int biasmostly0; 263 const int biasmostly1; 264 const int nbest; 265 const int tunebits; 266 const int hshift; 267 const unsigned long long int imli_mask1; 268 const unsigned long long int imli_mask4; 269 const unsigned long long int recencypos_mask; 270 const double fudge; 271 const int n_sign_bits; 272 const int pcbit; 273 const int decay; 274 const unsigned int record_mask; 275 const bool hash_taken; 276 const bool tuneonly; 277 const int extra_rounds; 278 const int speed; 279 const int budgetbits; 280 const bool speculative_update; 281 282 /** Transfer function for 6-width tables */ 283 static int xlat[]; 284 /** Transfer function for 5-width tables */ 285 static int xlat4[]; 286 287 /** History data is kept for each thread */ 288 struct ThreadData { 289 ThreadData(int num_filter, int n_local_histories, 290 int local_history_length, int assoc, 291 const std::vector<std::vector<int>> &blurrypath_bits, 292 int path_length, int ghist_length, int block_size, 293 const std::vector<std::vector<std::vector<bool>>> &acyclic_bits, 294 const std::vector<int> &modhist_indices, 295 const std::vector<int> &modhist_lengths, 296 const std::vector<int> &modpath_indices, 297 const std::vector<int> &modpath_lengths, 298 const std::vector<int> &table_sizes, int n_sign_bits); 299 300 std::vector<FilterEntry> filterTable; 301 std::vector<std::vector<bool>> acyclic_histories; 302 std::vector<std::vector<unsigned int>> acyclic2_histories; 303 304 void updateAcyclic(bool hashed_taken, unsigned int hpc) { 305 for (int i = 0; i < acyclic_histories.size(); i += 1) { 306 if (acyclic_histories[i].size() > 0) { 307 acyclic_histories[i][hpc%(i+2)] = hashed_taken; 308 acyclic2_histories[i][hpc%(i+2)] = hpc; 309 } 310 } 311 } 312 313 std::vector<std::vector<unsigned int>> blurrypath_histories; 314 std::vector<unsigned int> ghist_words; 315 std::vector<std::vector<unsigned short int>> modpath_histories; 316 std::vector<std::vector<bool>> mod_histories; 317 std::vector<unsigned short int> path_history; 318 std::vector<unsigned int> imli_counter; 319 LocalHistories localHistories; 320 std::vector<unsigned int short> recency_stack; 321 322 void insertRecency(unsigned int pc, int assoc) { 323 int i = 0; 324 for (i = 0; i < assoc; i += 1) { 325 if (recency_stack[i] == pc) { 326 break; 327 } 328 } 329 if (i == assoc) { 330 i = assoc-1; 331 recency_stack[i] = pc; 332 } 333 int j; 334 unsigned int b = recency_stack[i]; 335 for (j = i; j >= 1; j -= 1) { 336 recency_stack[j] = recency_stack[j-1]; 337 } 338 recency_stack[0] = b; 339 } 340 341 bool last_ghist_bit; 342 int occupancy; 343 344 std::vector<int> mpreds; 345 std::vector<std::vector<short int>> tables; 346 std::vector<std::vector<std::array<bool, 2>>> sign_bits; 347 }; 348 std::vector<ThreadData *> threadData; 349 350 /** Predictor tables */ 351 std::vector<HistorySpec *> specs; 352 std::vector<int> table_sizes; 353 354 /** runtime values and data used to count the size in bits */ 355 bool doing_local; 356 bool doing_recency; 357 int assoc; 358 int ghist_length; 359 int modghist_length; 360 int path_length; 361 int thresholdCounter; 362 int theta; 363 int extrabits; 364 std::vector<int> imli_counter_bits; 365 std::vector<int> modhist_indices; 366 std::vector<int> modhist_lengths; 367 std::vector<int> modpath_indices; 368 std::vector<int> modpath_lengths; 369 std::vector<std::vector<int>> blurrypath_bits; 370 std::vector<std::vector<std::vector<bool>>> acyclic_bits; 371 372 /** Auxiliary function for MODHIST and GHISTMODPATH features */ 373 void insertModhistSpec(int p1, int p2) { 374 int j = insert(modhist_indices, p1); 375 if (modhist_lengths.size() < (j + 1)) { 376 modhist_lengths.resize(j + 1); 377 } 378 if (modhist_lengths[j] < p2 + 1) { 379 modhist_lengths[j] = p2 + 1; 380 } 381 if (p2 >= modghist_length) { 382 modghist_length = p2 + 1; 383 } 384 } 385 386 /** Auxiliary function for MODPATH and GHISTMODPATH features */ 387 void insertModpathSpec(int p1, int p2) { 388 int j = insert(modpath_indices, p1); 389 if (modpath_lengths.size() < (j + 1)) { 390 modpath_lengths.resize(j + 1); 391 } 392 if (modpath_lengths[j] < p2 + 1) { 393 modpath_lengths[j] = p2 + 1; 394 } 395 if (p2 >= path_length) { 396 path_length = p2 + 1; 397 } 398 } 399 400 /** Auxiliary function used by insertModhistSpec and insertModpathSpec*/ 401 int insert(std::vector<int> &v, int x) 402 { 403 for (int i = 0; i < v.size(); i += 1) { 404 if (v[i] == x) { 405 return i; 406 } 407 } 408 v.push_back(x); 409 return v.size()-1; 410 } 411 412 /** 413 * Computes the size in bits of the structures needed to keep track 414 * of the history and the predictor tables and assigns the sizes of 415 * those tables that did not had their size specified. 416 * @param num_filter_entries number of entries of the filter 417 * @param nlocal_histories number of local history entries 418 * @param local_history_length size of each local history entry 419 * @param ignore_path_size ignore the path length storage 420 */ 421 void computeBits(int num_filter_entries, int nlocal_histories, 422 int local_history_length, bool ignore_path_size); 423 424 /** 425 * Creates the tables of the predictor 426 */ 427 virtual void createSpecs() = 0; 428 429 /** 430 * Get the position index of a predictor table 431 * @param tid Thread ID of the branch 432 * @param bi branch informaiton data 433 * @param spec predictor table 434 * @param index integer index of the predictor table 435 * @result index to access the predictor table 436 */ 437 unsigned int getIndex(ThreadID tid, const MPPBranchInfo &bi, 438 const HistorySpec &spec, int index) const; 439 /** 440 * Finds the best subset of features to use in case of a low-confidence 441 * branch, returns the result as an ordered vector of the indices to the 442 * predictor tables 443 * @param tid Thread ID of the branch 444 * @param vector to write the ordered list of indices of the best tables 445 */ 446 void findBest(ThreadID tid, std::vector<int> &best_preds) const; 447 448 /** 449 * Computes the output of the predictor for a given branch and the 450 * resulting best value in case the prediction has low confidence 451 * @param tid Thread ID of the branch 452 * @param bi branch informaiton data 453 * @return resulting sum for low-confidence branch 454 */ 455 int computeOutput(ThreadID tid, MPPBranchInfo &bi); 456 457 /** 458 * Trains the branch predictor with the given branch and direction 459 * @param tid Thread ID of the branch 460 * @param bi branch informaiton data 461 * @param taken whether the branch was taken 462 */ 463 void train(ThreadID tid, MPPBranchInfo &bi, bool taken); 464 465 /** 466 * Auxiliary function to increase a table counter depending on the 467 * direction of the branch 468 * @param taken whether the branch was taken 469 * @param sign current sign of the table 470 * @param c current value of the table 471 * @param max_weight maximum value of the counter 472 */ 473 void satIncDec(bool taken, bool &sign, int &c, int max_weight) const; 474 475 /** Add a table spec to the prefetcher */ 476 void addSpec(HistorySpec *spec) 477 { 478 specs.push_back(spec); 479 } 480 481 /** Available features */ 482 483 class GHIST : public HistorySpec { 484 public: 485 GHIST(int p1, int p2, double coeff, int size, int width, 486 MultiperspectivePerceptron &mpp) 487 : HistorySpec(p1, p2, 0, coeff, size, width, mpp) 488 {} 489 490 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 491 override 492 { 493 return hash(mpp.threadData[tid]->ghist_words, mpp.blockSize, p1, 494 p2); 495 } 496 497 static unsigned int hash(const std::vector<unsigned int> &ghist_words, 498 int block_size, int start_pos, int end_pos) 499 { 500 int a = start_pos; 501 int b = end_pos; 502 503 unsigned int x = 0; 504 // am is the next multiple of block_size after a 505 int am = (((a/block_size)*block_size)+block_size); 506 // bm is the previous multiple of block_size before b 507 int bm = (b/block_size)*block_size; 508 509 // the 0th bit of ghist_words[a/block_size] is the most recent bit. 510 // so the number of bits between a and am is the number to shift 511 // right? 512 513 // start out x as remainder bits from the beginning: 514 // x = [ . . . . . b b b b b ] 515 x += ghist_words[a / block_size] >> (a-am); 516 // add in bits from the middle 517 for (int i=am; i<bm; i+=block_size) { 518 x += ghist_words[i / block_size]; 519 } 520 // add in remainder bits from end: 521 // x += [ b b b b b . . . . . ] 522 unsigned int y = ghist_words[bm / block_size] & ((1<<(b - bm))-1); 523 x += y << (block_size - (b - bm)); 524 return x; 525 } 526 void setBitRequirements() const override 527 { 528 if (mpp.ghist_length <= p2) { 529 mpp.ghist_length = p2 + 1; 530 } 531 } 532 }; 533 534 class ACYCLIC : public HistorySpec { 535 public: 536 ACYCLIC(int p1, int p2, int p3, double coeff, int size, int width, 537 MultiperspectivePerceptron &mpp) 538 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 539 {} 540 541 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 542 override 543 { 544 int a = p1; 545 int shift = p2; 546 int style = p3; 547 std::vector<std::vector<bool>> &acyclic_histories = 548 mpp.threadData[tid]->acyclic_histories; 549 std::vector<std::vector<unsigned int>> &acyclic2_histories = 550 mpp.threadData[tid]->acyclic2_histories; 551 552 unsigned int x = 0; 553 if (style == -1) { 554 unsigned int k = 0; 555 for (int i = 0; i < a + 2; i += 1) { 556 x ^= acyclic_histories[a][i] << k; 557 k += 1; 558 k %= mpp.blockSize; 559 } 560 } else { 561 for (int i = 0; i < a + 2; i += 1) { 562 x <<= shift; 563 x += acyclic2_histories[a][i]; 564 } 565 } 566 return x; 567 } 568 void setBitRequirements() const override 569 { 570 if (mpp.acyclic_bits.size() < (p1 + 1)) { 571 mpp.acyclic_bits.resize(p1 + 1); 572 } 573 if (mpp.acyclic_bits[p1].size() < (p1 + 2)) { 574 mpp.acyclic_bits[p1].resize(p1 + 2, std::vector<bool>(2)); 575 } 576 for (int j = 0; j < p1 + 2; j += 1) { 577 mpp.acyclic_bits[p1][j][!p3] = true; 578 } 579 } 580 }; 581 582 class MODHIST : public HistorySpec { 583 public: 584 MODHIST(int p1, int p2, double coeff, int size, int width, 585 MultiperspectivePerceptron &mpp) 586 : HistorySpec(p1, p2, 0, coeff, size, width, mpp) 587 {} 588 589 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 590 override 591 { 592 int a = p1; 593 int b = p2; 594 std::vector<std::vector<bool>> &mod_histories = 595 mpp.threadData[tid]->mod_histories; 596 597 unsigned int x = 0, k = 0; 598 for (int i = 0; i < b; i += 1) { 599 x ^= mod_histories[a][i] << k; 600 k += 1; 601 k %= mpp.blockSize; 602 } 603 return x; 604 } 605 void setBitRequirements() const override 606 { 607 mpp.insertModhistSpec(p1, p2); 608 } 609 }; 610 611 class BIAS : public HistorySpec { 612 public: 613 BIAS(double coeff, int size, int width, 614 MultiperspectivePerceptron &mpp) 615 : HistorySpec(0, 0, 0, coeff, size, width, mpp) 616 {} 617 618 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 619 override 620 { 621 return 0; 622 } 623 }; 624 625 626 class RECENCY : public HistorySpec { 627 public: 628 RECENCY(int p1, int p2, int p3, double coeff, int size, int width, 629 MultiperspectivePerceptron &mpp) 630 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 631 {} 632 633 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 634 override 635 { 636 int depth = p1; 637 int shift = p2; 638 int style = p3; 639 std::vector<unsigned int short> &recency_stack = 640 mpp.threadData[tid]->recency_stack; 641 642 if (style == -1) { 643 unsigned int x = 0; 644 for (int i = 0; i < depth; i += 1) { 645 x <<= shift; 646 x += recency_stack[i]; 647 } 648 return x; 649 } else { 650 unsigned int x = 0, k = 0; 651 for (int i = 0; i < depth; i += 1) { 652 x ^= (!!(recency_stack[i] & (1 << shift))) << k; 653 k += 1; 654 k %= mpp.blockSize; 655 } 656 return x; 657 } 658 } 659 void setBitRequirements() const override 660 { 661 if (mpp.assoc < p1) { 662 mpp.assoc = p1; 663 } 664 mpp.doing_recency = true; 665 } 666 }; 667 668 class IMLI : public HistorySpec { 669 public: 670 IMLI(int p1, double coeff, int size, int width, 671 MultiperspectivePerceptron &mpp) 672 : HistorySpec(p1, 0, 0, coeff, size, width, mpp) 673 {} 674 675 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 676 override 677 { 678 assert(p1 >= 1); 679 assert(p1 <= 4); 680 return mpp.threadData[tid]->imli_counter[p1-1]; 681 } 682 683 void setBitRequirements() const override 684 { 685 mpp.imli_counter_bits[p1 - 1] = 32; 686 } 687 }; 688 689 class PATH : public HistorySpec { 690 public: 691 PATH(int p1, int p2, int p3, double coeff, int size, int width, 692 MultiperspectivePerceptron &mpp) 693 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 694 {} 695 696 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 697 override 698 { 699 int depth = p1; 700 int shift = p2; 701 int style = p3; 702 std::vector<unsigned short int> &path_history = 703 mpp.threadData[tid]->path_history; 704 705 if (style == -1) { 706 unsigned int x = 0; 707 for (int i = 0; i < depth; i += 1) { 708 x <<= shift; 709 x += path_history[i]; 710 } 711 return x; 712 } else { 713 unsigned int x = 0; 714 int bm = (depth / mpp.blockSize) * mpp.blockSize; 715 for (int i = 0; i < bm; i += mpp.blockSize) { 716 for (int j = 0; j < mpp.blockSize; j += 1) { 717 x ^= (!!(path_history[i + j] & (1 << shift))) << j; 718 } 719 } 720 int k = 0; 721 for (int i = bm; i < depth; i += 1) { 722 x ^= (!!(path_history[i] & (1 << shift))) << k++; 723 } 724 return x; 725 } 726 } 727 void setBitRequirements() const override 728 { 729 if (mpp.path_length <= p1) { 730 mpp.path_length = p1 + 1; 731 } 732 } 733 }; 734 735 class LOCAL : public HistorySpec { 736 public: 737 LOCAL(int p1, double coeff, int size, int width, 738 MultiperspectivePerceptron &mpp) 739 : HistorySpec(p1, 0, 0, coeff, size, width, mpp) 740 {} 741 742 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 743 override 744 { 745 unsigned int x = mpp.threadData[tid]->localHistories[pc]; 746 if (p1 != -1) { 747 x &= ((1 << p1) - 1); 748 } 749 return x; 750 } 751 void setBitRequirements() const override 752 { 753 mpp.doing_local = true; 754 } 755 }; 756 757 class MODPATH : public HistorySpec { 758 public: 759 MODPATH(int p1, int p2, int p3, double coeff, int size, int width, 760 MultiperspectivePerceptron &mpp) 761 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 762 {} 763 764 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 765 override 766 { 767 int a = p1; 768 int depth = p2; 769 int shift = p3; 770 771 unsigned int x = 0; 772 for (int i=0; i<depth; i += 1) { 773 x <<= shift; 774 x += mpp.threadData[tid]->modpath_histories[a][i]; 775 } 776 return x; 777 } 778 void setBitRequirements() const override 779 { 780 mpp.insertModpathSpec(p1, p2); 781 } 782 }; 783 784 class GHISTPATH : public HistorySpec { 785 public: 786 GHISTPATH(int p1, int p2, int p3, double coeff, int size, int width, 787 MultiperspectivePerceptron &mpp) 788 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 789 {} 790 791 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 792 override 793 { 794 int depth = p1; 795 int shift = p2; 796 int style = p3; 797 std::vector<unsigned int> &ghist_words = 798 mpp.threadData[tid]->ghist_words; 799 std::vector<unsigned short int> &path_history = 800 mpp.threadData[tid]->path_history; 801 802 if (style == -1) { 803 unsigned int x = 0; 804 int bm = (depth / mpp.blockSize) * mpp.blockSize; 805 unsigned int w; 806 for (int i = 0; i < bm; i += mpp.blockSize) { 807 w = ghist_words[i / mpp.blockSize]; 808 for (int j = 0; j < mpp.blockSize; j += 1) { 809 x <<= shift; 810 x += (path_history[i + j] << 1) | (w & 1); 811 w >>= 1; 812 } 813 } 814 w = ghist_words[bm / mpp.blockSize]; 815 for (int i = bm; i < depth; i += 1) { 816 x <<= shift; 817 x += (path_history[i] << 1) | (w & 1); 818 w >>= 1; 819 } 820 return x; 821 } else { 822 unsigned int x = 0; 823 int bm = (depth / mpp.blockSize) * mpp.blockSize; 824 unsigned int w = 0; 825 for (int i = 0; i < bm; i += mpp.blockSize) { 826 w = ghist_words[i / mpp.blockSize]; 827 for (int j = 0; j < mpp.blockSize; j += 1) { 828 x ^= (!!(path_history[i + j] & (1 << shift))) << j; 829 x ^= (w & 1) << j; 830 w >>= 1; 831 } 832 } 833 w = ghist_words[bm/mpp.blockSize]; 834 int k = 0; 835 for (int i = bm; i < depth; i += 1) { 836 x ^= (!!(path_history[i] & (1 << shift))) << k; 837 x ^= (w & 1) << k; 838 w >>= 1; 839 k += 1; 840 } 841 return x; 842 } 843 } 844 845 void setBitRequirements() const override 846 { 847 if (mpp.ghist_length <= p1) { 848 mpp.ghist_length = p1 + 1; 849 } 850 if (mpp.path_length <= p1) { 851 mpp.path_length = p1 + 1; 852 } 853 } 854 }; 855 856 class GHISTMODPATH : public HistorySpec { 857 public: 858 GHISTMODPATH(int p1, int p2, int p3, double coeff, int size, int width, 859 MultiperspectivePerceptron &mpp) 860 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 861 {} 862 863 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 864 override 865 { 866 int a = p1; 867 int depth = p2; 868 int shift = p3; 869 std::vector<std::vector<unsigned short int>> &modpath_histories = 870 mpp.threadData[tid]->modpath_histories; 871 std::vector<std::vector<bool>> &mod_histories = 872 mpp.threadData[tid]->mod_histories; 873 874 unsigned int x = 0; 875 for (int i = 0; i < depth; i += 1) { 876 x <<= shift; 877 x += (modpath_histories[a][i] << 1) | mod_histories[a][i]; 878 } 879 return x; 880 } 881 void setBitRequirements() const override 882 { 883 mpp.insertModhistSpec(p1, p2); 884 mpp.insertModpathSpec(p1, p2); 885 } 886 }; 887 888 class BLURRYPATH : public HistorySpec { 889 public: 890 BLURRYPATH(int p1, int p2, int p3, double coeff, int size, int width, 891 MultiperspectivePerceptron &mpp) 892 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 893 {} 894 895 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 896 override 897 { 898 int scale = p1; 899 int depth = p2; 900 int shiftdelta = p3; 901 902 if (shiftdelta == -1) shiftdelta = 0; 903 int sdint = shiftdelta >> 2; 904 int sdfrac = shiftdelta & 3; 905 unsigned int x = 0; 906 int shift = 0; 907 int count = 0; 908 for (int i = 0; i < depth; i += 1) { 909 x += mpp.threadData[tid]->blurrypath_histories[scale][i] >> 910 shift; 911 count += 1; 912 if (count == sdfrac) { 913 shift += sdint; 914 count = 0; 915 } 916 } 917 return x; 918 919 } 920 void setBitRequirements() const override 921 { 922 if (mpp.blurrypath_bits.size() < (p1 + 1)) { 923 mpp.blurrypath_bits.resize(p1 + 1); 924 } 925 if (mpp.blurrypath_bits[p1].size() < p2) { 926 mpp.blurrypath_bits[p1].resize(p2); 927 } 928 for (int j = 0; j < p2; j += 1) { 929 mpp.blurrypath_bits[p1][j] = 32 - p1; 930 } 931 } 932 }; 933 934 class RECENCYPOS : public HistorySpec { 935 public: 936 RECENCYPOS(int p1, double coeff, int size, int width, 937 MultiperspectivePerceptron &mpp) 938 : HistorySpec(p1, 0, 0, coeff, size, width, mpp) 939 {} 940 941 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 942 override 943 { 944 return hash(mpp.threadData[tid]->recency_stack, mpp.table_sizes, 945 pc2, p1, t); 946 } 947 948 static unsigned int hash( 949 const std::vector<unsigned int short> &recency_stack, 950 const std::vector<int> &table_sizes, unsigned short int pc, int l, 951 int t) 952 { 953 // search for the PC 954 955 for (int i = 0; i < l; i += 1) { 956 if (recency_stack[i] == pc) { 957 return i * table_sizes[t] / l; 958 } 959 } 960 961 // return last index in table on a miss 962 963 return table_sizes[t] - 1; 964 } 965 966 void setBitRequirements() const override 967 { 968 if (mpp.assoc < p1) { 969 mpp.assoc = p1; 970 } 971 mpp.doing_recency = true; 972 } 973 }; 974 975 class SGHISTPATH : public HistorySpec { 976 public: 977 SGHISTPATH(int p1, int p2, int p3, double coeff, int size, int width, 978 MultiperspectivePerceptron &mpp) 979 : HistorySpec(p1, p2, p3, coeff, size, width, mpp) 980 {} 981 982 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const 983 override 984 { 985 int a = p1; 986 int b = p2; 987 int shift = p3; 988 std::vector<unsigned int> &ghist_words = 989 mpp.threadData[tid]->ghist_words; 990 std::vector<unsigned short int> &path_history = 991 mpp.threadData[tid]->path_history; 992 993 unsigned int x = 0; 994 int bm = (b / mpp.blockSize) * mpp.blockSize; 995 unsigned int w; 996 for (int i = a; i < bm; i += mpp.blockSize) { 997 w = ghist_words[i / mpp.blockSize]; 998 for (int j = 0; j < mpp.blockSize; j += 1) { 999 x <<= shift; 1000 x += (path_history[i+j] << 1) | (w & 1); 1001 w >>= 1; 1002 } 1003 } 1004 w = ghist_words[bm / mpp.blockSize]; 1005 for (int i = bm; i < b; i += 1) { 1006 x <<= shift; 1007 x += (path_history[i] << 1) | (w & 1); 1008 w >>= 1; 1009 } 1010 return x; 1011 } 1012 }; 1013 1014 public: 1015 MultiperspectivePerceptron(const MultiperspectivePerceptronParams *params); 1016 1017 /** 1018 * Sets the starting number of storage bits to compute the number of 1019 * table entries 1020 * @param bits number of bits used 1021 */ 1022 void setExtraBits(int bits); 1023 1024 void init() override; 1025 1026 void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) override; 1027 void squash(ThreadID tid, void *bp_history) override; 1028 bool lookup(ThreadID tid, Addr instPC, void * &bp_history) override; 1029 void update(ThreadID tid, Addr instPC, bool taken, 1030 void *bp_history, bool squashed, 1031 const StaticInstPtr & inst, 1032 Addr corrTarget = MaxAddr) override; 1033 void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override; 1034}; 1035#endif//__CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ 1036