gem5 v24.0.0.0
Loading...
Searching...
No Matches
ras.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022-2023 The University of Edinburgh
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-2005 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
41#include "cpu/pred/ras.hh"
42
43#include <iomanip>
44
45#include "debug/RAS.hh"
46
47namespace gem5
48{
49
50namespace branch_prediction
51{
52
53
54void
56{
57 numEntries = _numEntries;
58 addrStack.resize(numEntries);
59 for (unsigned i = 0; i < numEntries; ++i) {
60 addrStack[i] = nullptr;
61 }
62 reset();
63}
64
65void
67{
68 usedEntries = 0;
69 tos = 0;
70}
71
72const PCStateBase *
74{
75 return addrStack[tos].get();
76}
77
78
79void
81{
82
83 incrTos();
84
85 set(addrStack[tos], return_addr);
86
87 if (usedEntries != numEntries) {
88 ++usedEntries;
89 }
90}
91
92void
94{
95 if (usedEntries > 0) {
96 --usedEntries;
97 }
98
99 decrTos();
100}
101
102void
104 const PCStateBase *restored)
105{
106 tos = _tos;
107
108 set(addrStack[tos], restored);
109
110 if (usedEntries != numEntries) {
111 ++usedEntries;
112 }
113}
114
115std::string
117{
118 std::stringstream ss;
119 for (int i = 0; i < n; i++) {
120 int idx = int(tos)-i;
121 if (idx < 0 || addrStack[idx] == nullptr) {
122 break;
123 }
124 ss << std::dec << idx << ":0x" << std::setfill('0') << std::setw(16)
125 << std::hex << addrStack[idx]->instAddr() << ";";
126 }
127 return ss.str();
128}
129
130
131// Return address stack class.
132//
133
135 : SimObject(p),
138 stats(this)
139{
140 DPRINTF(RAS, "Create RAS stacks.\n");
141
142 for (unsigned i = 0; i < numThreads; ++i) {
143 addrStacks.emplace_back(*this);
144 addrStacks[i].init(numEntries);
145 }
146}
147
148void
150{
151 DPRINTF(RAS, "RAS Reset.\n");
152 for (auto& r : addrStacks)
153 r.reset();
154}
155
156void
158{
159 RASHistory* history = new RASHistory;
160 history->pushed = false;
161 history->poped = false;
162 ras_history = static_cast<void*>(history);
163}
164
165void
167 void * &ras_history)
168{
169 // Note: The RAS may be both popped and pushed to
170 // support coroutines.
171 if (ras_history == nullptr) {
172 makeRASHistory(ras_history);
173 }
174 RASHistory *history = static_cast<RASHistory*>(ras_history);
175 stats.pushes++;
176 history->pushed = true;
177
178 addrStacks[tid].push(pc);
179
180 DPRINTF(RAS, "%s: RAS[%i] <= %#x. Entries used: %i, tid:%i\n", __func__,
181 addrStacks[tid].tos, pc.instAddr(),
182 addrStacks[tid].usedEntries,tid);
183 // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10));
184}
185
186
187const PCStateBase*
188ReturnAddrStack::pop(ThreadID tid, void * &ras_history)
189{
190 // Note: The RAS may be both popped and pushed to
191 // support coroutines.
192 if (ras_history == nullptr) {
193 makeRASHistory(ras_history);
194 }
195 RASHistory *history = static_cast<RASHistory*>(ras_history);
196 stats.pops++;
197
198 history->poped = true;
199 history->tos = addrStacks[tid].tos;
200
201
202 set(history->ras_entry, addrStacks[tid].top());
203 // Pop the top of stack
204 addrStacks[tid].pop();
205
206 DPRINTF(RAS, "%s: RAS[%i] => %#x. Entries used: %i, tid:%i\n", __func__,
207 addrStacks[tid].tos, (history->ras_entry.get() != nullptr)
208 ? history->ras_entry->instAddr() : 0,
209 addrStacks[tid].usedEntries, tid);
210 // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10));
211
212 return history->ras_entry.get();
213}
214
215void
216ReturnAddrStack::squash(ThreadID tid, void * &ras_history)
217{
218 if (ras_history == nullptr) {
219 // If ras_history is null no stack operation was performed for
220 // this branch. Nothing to be done.
221 return;
222 }
223 stats.squashes++;
224
225 RASHistory *history = static_cast<RASHistory*>(ras_history);
226
227 if (history->pushed) {
228 stats.pops++;
229 addrStacks[tid].pop();
230
231 DPRINTF(RAS, "RAS::%s Incorrect push. Pop RAS[%i]. "
232 "Entries used: %i, tid:%i\n", __func__,
233 addrStacks[tid].tos, addrStacks[tid].usedEntries, tid);
234 }
235
236 if (history->poped) {
237 stats.pushes++;
238 addrStacks[tid].restore(history->tos, history->ras_entry.get());
239 DPRINTF(RAS, "RAS::%s Incorrect pop. Restore to: RAS[%i]:%#x. "
240 "Entries used: %i, tid:%i\n", __func__,
241 history->tos, (history->ras_entry.get() != nullptr)
242 ? history->ras_entry->instAddr() : 0,
243 addrStacks[tid].usedEntries, tid);
244 }
245 // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10));
246 delete history;
247 ras_history = nullptr;
248}
249
250void
252 const BranchType brType, void * &ras_history)
253{
254 // Skip branches that are not call or returns
255 if (!(brType == BranchType::Return ||
256 brType == BranchType::CallDirect ||
257 brType == BranchType::CallIndirect)) {
258 // If its not a call or return there should be no ras history.
259 assert(ras_history == nullptr);
260 return;
261 }
262
263 DPRINTF(RAS, "RAS::%s Commit Branch inst: %s, tid:%i\n",
264 __func__, toString(brType),tid);
265
266
267 if (ras_history == nullptr) {
283 return;
284 }
285
286 /* Handle all other commited returns and calls */
287 RASHistory *history = static_cast<RASHistory*>(ras_history);
288
289 if (history->poped) {
290 stats.used++;
291 if (misp) {
293 } else {
294 stats.correct++;
295 }
296
297 DPRINTF(RAS, "RAS::%s Commit Return PC %#x, correct:%i, tid:%i\n",
298 __func__, !misp, (history->ras_entry.get() != nullptr)
299 ? history->ras_entry->instAddr() : 0, tid);
300 }
301 delete history;
302 ras_history = nullptr;
303}
304
305
306
308 statistics::Group *parent)
309 : statistics::Group(parent),
310 ADD_STAT(pushes, statistics::units::Count::get(),
311 "Number of times a PC was pushed onto the RAS"),
312 ADD_STAT(pops, statistics::units::Count::get(),
313 "Number of times a PC was poped from the RAS"),
314 ADD_STAT(squashes, statistics::units::Count::get(),
315 "Number of times the stack operation was squashed due to "
316 "wrong speculation."),
317 ADD_STAT(used, statistics::units::Count::get(),
318 "Number of times the RAS is the provider"),
319 ADD_STAT(correct, statistics::units::Count::get(),
320 "Number of times the RAS is the provider and the "
321 "prediction is correct"),
322 ADD_STAT(incorrect, statistics::units::Count::get(),
323 "Number of times the RAS is the provider and the "
324 "prediction is wrong")
325{
326}
327
328} // namespace branch_prediction
329} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Abstract superclass for simulation objects.
const PCStateBase * top()
Returns the top address on the RAS.
Definition ras.cc:73
void pop()
Pops the top address from the RAS.
Definition ras.cc:93
std::string toString(int n)
Returns the top n entries of the stack as string.
Definition ras.cc:116
unsigned numEntries
The number of entries in the RAS.
Definition ras.hh:127
void push(const PCStateBase &return_addr)
Pushes an address onto the RAS.
Definition ras.cc:80
std::vector< std::unique_ptr< PCStateBase > > addrStack
The Stack itself.
Definition ras.hh:124
void restore(unsigned top_of_stack, const PCStateBase *restored)
Changes index to the top of the RAS, and replaces the top address with a new target.
Definition ras.cc:103
void init(unsigned numEntries)
Initializes RAS with a specified number of entries.
Definition ras.cc:55
std::unique_ptr< PCStateBase > ras_entry
The entry that poped from the RAS (only valid if a return).
Definition ras.hh:194
unsigned tos
The RAS index (top of stack pointer) of the instruction.
Definition ras.hh:196
unsigned numThreads
The number of threads.
Definition ras.hh:207
const PCStateBase * pop(ThreadID tid, void *&ras_history)
Pops the top address from the RAS.
Definition ras.cc:188
void makeRASHistory(void *&ras_history)
Definition ras.cc:157
ReturnAddrStackParams Params
Definition ras.hh:143
std::vector< AddrStack > addrStacks
The RAS itself.
Definition ras.hh:202
void squash(ThreadID tid, void *&ras_history)
The branch (call/return) got squashed.
Definition ras.cc:216
gem5::branch_prediction::ReturnAddrStack::ReturnAddrStackStats stats
unsigned numEntries
The number of entries in the RAS.
Definition ras.hh:205
void commit(ThreadID tid, bool misp, const BranchType brType, void *&ras_history)
A branch got finally got finally commited.
Definition ras.cc:251
void push(ThreadID tid, const PCStateBase &pc, void *&ras_history)
Pushes an address onto the RAS.
Definition ras.cc:166
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
Bitfield< 31 > n
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 21 > ss
Definition misc_types.hh:60
Bitfield< 4 > pc
Bitfield< 0 > p
std::string toString(BranchType type)
enums::BranchType BranchType
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0