ChampSim
basic_btb.h
Go to the documentation of this file.
1 /*
2  * This file implements a basic Branch Target Buffer (BTB) structure.
3  * It uses a set-associative BTB to predict the targets.
4  */
5 
6 #include "ooo_cpu.h"
7 #include "branch_info.h"
8 
9 template <uint32_t SETS, uint32_t WAYS>
10 class BasicBTB {
11 
12 private:
13 
14  struct ENTRY {
15  uint64_t ip_tag;
16  uint64_t target;
17  uint8_t branch_info;
18  uint64_t lru;
19  };
20 
21  ENTRY basic_btb[SETS][WAYS];
22  uint64_t lru_counter;
23 
24  uint64_t set_index(uint64_t ip) { return ((ip >> 2) & (SETS - 1)); }
25 
26  ENTRY* find_entry(uint64_t ip) {
27  uint64_t set = set_index(ip);
28  for (uint32_t i = 0; i < WAYS; i++) {
29  if (basic_btb[set][i].ip_tag == ip) {
30  return &(basic_btb[set][i]);
31  }
32  }
33  return NULL;
34  }
35 
36  ENTRY* get_lru_entry(uint64_t set) {
37  uint32_t lru_way = 0;
38  uint64_t lru_value = basic_btb[set][lru_way].lru;
39  for (uint32_t i = 0; i < WAYS; i++) {
40  if (basic_btb[set][i].lru < lru_value) {
41  lru_way = i;
42  lru_value = basic_btb[set][lru_way].lru;
43  }
44  }
45  return &(basic_btb[set][lru_way]);
46  }
47 
48  void update_lru(ENTRY* btb_entry) {
49  btb_entry->lru = lru_counter;
50  lru_counter++;
51  }
52 
53 public:
54 
55  void initialize() {
56  std::cout << "Basic BTB sets: " << SETS << " ways: " << WAYS << std::endl;
57  for (uint32_t i = 0; i < SETS; i++) {
58  for (uint32_t j = 0; j < WAYS; j++) {
59  basic_btb[i][j].ip_tag = 0;
60  basic_btb[i][j].target = 0;
62  basic_btb[i][j].lru = 0;
63  }
64  }
65  lru_counter = 0;
66  }
67 
68  std::pair<uint64_t, uint8_t> predict(uint64_t ip) {
69  auto btb_entry = find_entry(ip);
70  if (btb_entry == NULL) {
71  // no prediction for this IP
72  return std::make_pair(0, BRANCH_INFO_ALWAYS_TAKEN);
73  }
74  update_lru(btb_entry);
75  return std::make_pair(btb_entry->target, btb_entry->branch_info);
76  }
77 
78  void update(uint64_t ip, uint64_t branch_target, uint8_t taken, uint8_t branch_type) {
79  auto btb_entry = find_entry(ip);
80  if (btb_entry == NULL) {
81  if ((branch_target == 0) || !taken) {
82  return;
83  }
84  // no prediction for this entry so far, so allocate one
85  uint64_t set = set_index(ip);
86  btb_entry = get_lru_entry(set);
87  btb_entry->ip_tag = ip;
88  btb_entry->branch_info = BRANCH_INFO_ALWAYS_TAKEN;
89  update_lru(btb_entry);
90  }
91  // update btb entry
92  if (branch_target != 0) btb_entry->target = branch_target;
94  btb_entry->branch_info = BRANCH_INFO_INDIRECT;
95  } else if (branch_type == BRANCH_RETURN) {
96  btb_entry->branch_info = BRANCH_INFO_RETURN;
97  } else if (branch_type == BRANCH_CONDITIONAL) {
98  btb_entry->branch_info = BRANCH_INFO_CONDITIONAL;
99  }
100  }
101 };
#define BRANCH_INFO_ALWAYS_TAKEN
Definition: branch_info.h:6
#define BRANCH_INFO_INDIRECT
Definition: branch_info.h:4
#define BRANCH_INFO_CONDITIONAL
Definition: branch_info.h:7
#define BRANCH_INFO_RETURN
Definition: branch_info.h:5
Definition: basic_btb.h:10
void initialize()
Definition: basic_btb.h:55
uint64_t set_index(uint64_t ip)
Definition: basic_btb.h:24
void update(uint64_t ip, uint64_t branch_target, uint8_t taken, uint8_t branch_type)
Definition: basic_btb.h:78
uint64_t lru_counter
Definition: basic_btb.h:22
ENTRY * get_lru_entry(uint64_t set)
Definition: basic_btb.h:36
ENTRY basic_btb[SETS][WAYS]
Definition: basic_btb.h:21
void update_lru(ENTRY *btb_entry)
Definition: basic_btb.h:48
std::pair< uint64_t, uint8_t > predict(uint64_t ip)
Definition: basic_btb.h:68
ENTRY * find_entry(uint64_t ip)
Definition: basic_btb.h:26
branch_type
Definition: instruction.h:30
@ BRANCH_INDIRECT_CALL
Definition: instruction.h:36
@ BRANCH_RETURN
Definition: instruction.h:37
@ BRANCH_CONDITIONAL
Definition: instruction.h:34
@ BRANCH_INDIRECT
Definition: instruction.h:33
Definition: basic_btb.h:14
uint64_t target
Definition: basic_btb.h:16
uint8_t branch_info
Definition: basic_btb.h:17
uint64_t lru
Definition: basic_btb.h:18
uint64_t ip_tag
Definition: basic_btb.h:15