ChampSim
ras.h
Go to the documentation of this file.
1 /*
2  * This file implements a Return Address Stack (RAS).
3  */
4 
5 #include "ooo_cpu.h"
6 
7 template<uint32_t RAS_SIZE, uint32_t CALL_INSTR_SIZE_TRACKERS>
8 class RAS {
9 
10 private:
11 
12  uint64_t ras[RAS_SIZE];
13  int ras_index;
14  /*
15  * The following two variables are used to automatically identify the
16  * size of call instructions, in bytes, which tells us the appropriate
17  * target for a call's corresponding return.
18  * They exist because ChampSim does not model a specific ISA, and
19  * different ISAs could use different sizes for call instructions,
20  * and even within the same ISA, calls can have different sizes.
21  */
22  uint64_t call_instr_sizes[CALL_INSTR_SIZE_TRACKERS];
23 
24  uint64_t abs_addr_dist(uint64_t addr1, uint64_t addr2) {
25  if (addr1 > addr2) {
26  return addr1 - addr2;
27  }
28  return addr2 - addr1;
29  }
30 
31  void push_ras(uint64_t ip) {
32  ras_index++;
33  if (ras_index == RAS_SIZE) {
34  ras_index = 0;
35  }
36  ras[ras_index] = ip;
37  }
38 
39  uint64_t peek_ras() { return ras[ras_index]; }
40 
41  uint64_t pop_ras() {
42  uint64_t target = ras[ras_index];
43  ras[ras_index] = 0;
44  ras_index--;
45  if (ras_index == -1) {
46  ras_index += RAS_SIZE;
47  }
48  return target;
49  }
50 
51  uint64_t call_size_tracker_hash(uint64_t ip) { return (ip & (CALL_INSTR_SIZE_TRACKERS - 1)); }
52 
53  uint64_t get_call_size(uint64_t ip) { return call_instr_sizes[call_size_tracker_hash(ip)]; }
54 
55 public:
56 
57  void initialize() {
58  std::cout << "RAS size: " << RAS_SIZE << std::endl;
59  for (uint32_t i = 0; i < RAS_SIZE; i++) {
60  ras[i] = 0;
61  }
62  ras_index = 0;
63  for (uint32_t i = 0; i < CALL_INSTR_SIZE_TRACKERS; i++) {
64  call_instr_sizes[i] = 4;
65  }
66  }
67 
68  uint64_t predict() {
69  // peek at the top of the RAS
70  // and adjust for the size of the call instr
71  uint64_t target = peek_ras();
72  if (target) target += get_call_size(target);
73  return target;
74  }
75 
76  void update(uint64_t ip, uint64_t branch_target, uint8_t taken, uint8_t branch_type) {
78  // add something to the RAS
79  push_ras(ip);
80  }
81  if (branch_type == BRANCH_RETURN) {
82  // recalibrate call-return offset
83  // if our return prediction got us into the right ball park, but not the
84  // exactly correct byte target, then adjust our call instr size tracker
85  uint64_t call_ip = pop_ras();
86  uint64_t estimated_call_instr_size = abs_addr_dist(call_ip, branch_target);
87  if (estimated_call_instr_size <= 10) {
88  call_instr_sizes[call_size_tracker_hash(call_ip)] = estimated_call_instr_size;
89  }
90  }
91  }
92 };
Definition: ras.h:8
uint64_t ras[RAS_SIZE]
Definition: ras.h:12
uint64_t call_instr_sizes[CALL_INSTR_SIZE_TRACKERS]
Definition: ras.h:22
void initialize()
Definition: ras.h:57
uint64_t pop_ras()
Definition: ras.h:41
uint64_t predict()
Definition: ras.h:68
uint64_t call_size_tracker_hash(uint64_t ip)
Definition: ras.h:51
uint64_t abs_addr_dist(uint64_t addr1, uint64_t addr2)
Definition: ras.h:24
void push_ras(uint64_t ip)
Definition: ras.h:31
int ras_index
Definition: ras.h:13
void update(uint64_t ip, uint64_t branch_target, uint8_t taken, uint8_t branch_type)
Definition: ras.h:76
uint64_t peek_ras()
Definition: ras.h:39
uint64_t get_call_size(uint64_t ip)
Definition: ras.h:53
branch_type
Definition: instruction.h:30
@ BRANCH_INDIRECT_CALL
Definition: instruction.h:36
@ BRANCH_DIRECT_CALL
Definition: instruction.h:35
@ BRANCH_RETURN
Definition: instruction.h:37