Deleted Added
sdiff udiff text old ( 13762:36d5a1d9f5e6 ) new ( 14025:3a133070aa2e )
full compact
1/*
2 * Copyright (c) 2016-2018 ARM Limited
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) 2013 Advanced Micro Devices, Inc.
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 * Authors: Steve Reinhardt
41 * Nathanael Premillieu
42 * Rekai Gonzalez
43 */
44
45#ifndef __CPU__REG_CLASS_HH__
46#define __CPU__REG_CLASS_HH__
47
48#include <cassert>
49#include <cstddef>
50
51#include "arch/generic/types.hh"
52#include "arch/registers.hh"
53#include "config/the_isa.hh"
54
55/** Enumerate the classes of registers. */
56enum RegClass {
57 IntRegClass, ///< Integer register
58 FloatRegClass, ///< Floating-point register
59 /** Vector Register. */
60 VecRegClass,
61 /** Vector Register Native Elem lane. */
62 VecElemClass,
63 VecPredRegClass,
64 CCRegClass, ///< Condition-code register
65 MiscRegClass ///< Control (misc) register
66};
67
68/** Number of register classes.
69 * This value is not part of the enum, because putting it there makes the
70 * compiler complain about unhandled cases in some switch statements.
71 */
72const int NumRegClasses = MiscRegClass + 1;
73
74/** Register ID: describe an architectural register with its class and index.
75 * This structure is used instead of just the register index to disambiguate
76 * between different classes of registers. For example, a integer register with
77 * index 3 is represented by Regid(IntRegClass, 3).
78 */
79class RegId {
80 protected:
81 static const char* regClassStrings[];
82 RegClass regClass;
83 RegIndex regIdx;
84 ElemIndex elemIdx;
85 static constexpr size_t Scale = TheISA::NumVecElemPerVecReg;
86 int numPinnedWrites;
87
88 friend struct std::hash<RegId>;
89
90 public:
91 RegId() : regClass(IntRegClass), regIdx(0), elemIdx(-1) {}
92 RegId(RegClass reg_class, RegIndex reg_idx)
93 : regClass(reg_class), regIdx(reg_idx), elemIdx(-1),
94 numPinnedWrites(0)
95 {
96 panic_if(regClass == VecElemClass,
97 "Creating vector physical index w/o element index");
98 }
99
100 explicit RegId(RegClass reg_class, RegIndex reg_idx, ElemIndex elem_idx)
101 : regClass(reg_class), regIdx(reg_idx), elemIdx(elem_idx),
102 numPinnedWrites(0)
103 {
104 panic_if(regClass != VecElemClass,
105 "Creating non-vector physical index w/ element index");
106 }
107
108 bool operator==(const RegId& that) const {
109 return regClass == that.classValue() && regIdx == that.index()
110 && elemIdx == that.elemIndex();
111 }
112
113 bool operator!=(const RegId& that) const {
114 return !(*this==that);
115 }
116
117 /** Order operator.
118 * The order is required to implement maps with key type RegId
119 */
120 bool operator<(const RegId& that) const {
121 return regClass < that.classValue() ||
122 (regClass == that.classValue() && (
123 regIdx < that.index() ||
124 (regIdx == that.index() && elemIdx < that.elemIndex())));
125 }
126
127 /**
128 * Return true if this register can be renamed
129 */
130 bool isRenameable() const
131 {
132 return regClass != MiscRegClass;
133 }
134
135 /**
136 * Check if this is the zero register.
137 * Returns true if this register is a zero register (needs to have a
138 * constant zero value throughout the execution).
139 */
140
141 inline bool isZeroReg() const
142 {
143 return ((regClass == IntRegClass && regIdx == TheISA::ZeroReg) ||
144 (THE_ISA == ALPHA_ISA && regClass == FloatRegClass &&
145 regIdx == TheISA::ZeroReg));
146 }
147
148 /** @return true if it is an integer physical register. */
149 bool isIntReg() const { return regClass == IntRegClass; }
150
151 /** @return true if it is a floating-point physical register. */
152 bool isFloatReg() const { return regClass == FloatRegClass; }
153
154 /** @Return true if it is a condition-code physical register. */
155 bool isVecReg() const { return regClass == VecRegClass; }
156
157 /** @Return true if it is a condition-code physical register. */
158 bool isVecElem() const { return regClass == VecElemClass; }
159
160 /** @Return true if it is a predicate physical register. */
161 bool isVecPredReg() const { return regClass == VecPredRegClass; }
162
163 /** @Return true if it is a condition-code physical register. */
164 bool isCCReg() const { return regClass == CCRegClass; }
165
166 /** @Return true if it is a condition-code physical register. */
167 bool isMiscReg() const { return regClass == MiscRegClass; }
168
169 /**
170 * Return true if this register can be renamed
171 */
172 bool isRenameable()
173 {
174 return regClass != MiscRegClass;
175 }
176
177 /** Index accessors */
178 /** @{ */
179 const RegIndex& index() const { return regIdx; }
180 RegIndex& index() { return regIdx; }
181
182 /** Index flattening.
183 * Required to be able to use a vector for the register mapping.
184 */
185 inline RegIndex flatIndex() const
186 {
187 switch (regClass) {
188 case IntRegClass:
189 case FloatRegClass:
190 case VecRegClass:
191 case VecPredRegClass:
192 case CCRegClass:
193 case MiscRegClass:
194 return regIdx;
195 case VecElemClass:
196 return Scale*regIdx + elemIdx;
197 }
198 panic("Trying to flatten a register without class!");
199 return -1;
200 }
201 /** @} */
202
203 /** Elem accessor */
204 const RegIndex& elemIndex() const { return elemIdx; }
205 /** Class accessor */
206 const RegClass& classValue() const { return regClass; }
207 /** Return a const char* with the register class name. */
208 const char* className() const { return regClassStrings[regClass]; }
209
210 int getNumPinnedWrites() const { return numPinnedWrites; }
211 void setNumPinnedWrites(int num_writes) { numPinnedWrites = num_writes; }
212
213 friend std::ostream&
214 operator<<(std::ostream& os, const RegId& rid) {
215 return os << rid.className() << "{" << rid.index() << "}";
216 }
217};
218
219/** Physical register index type.
220 * Although the Impl might be a better for this, but there are a few classes
221 * that need this typedef yet are not templated on the Impl.
222 */
223using PhysRegIndex = short int;
224
225/** Physical register ID.
226 * Like a register ID but physical. The inheritance is private because the
227 * only relationship between this types is functional, and it is done to
228 * prevent code replication. */
229class PhysRegId : private RegId {
230 private:
231 PhysRegIndex flatIdx;
232 int numPinnedWritesToComplete;
233 bool pinned;
234
235 public:
236 explicit PhysRegId() : RegId(IntRegClass, -1), flatIdx(-1),
237 numPinnedWritesToComplete(0)
238 {}
239
240 /** Scalar PhysRegId constructor. */
241 explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
242 PhysRegIndex _flatIdx)
243 : RegId(_regClass, _regIdx), flatIdx(_flatIdx),
244 numPinnedWritesToComplete(0), pinned(false)
245 {}
246
247 /** Vector PhysRegId constructor (w/ elemIndex). */
248 explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
249 ElemIndex elem_idx, PhysRegIndex flat_idx)
250 : RegId(_regClass, _regIdx, elem_idx), flatIdx(flat_idx),
251 numPinnedWritesToComplete(0), pinned(false)
252 {}
253
254 /** Visible RegId methods */
255 /** @{ */
256 using RegId::index;
257 using RegId::classValue;
258 using RegId::isZeroReg;
259 using RegId::className;
260 using RegId::elemIndex;
261 /** @} */
262 /**
263 * Explicit forward methods, to prevent comparisons of PhysRegId with
264 * RegIds.
265 */
266 /** @{ */
267 bool operator<(const PhysRegId& that) const {
268 return RegId::operator<(that);
269 }
270
271 bool operator==(const PhysRegId& that) const {
272 return RegId::operator==(that);
273 }
274
275 bool operator!=(const PhysRegId& that) const {
276 return RegId::operator!=(that);
277 }
278 /** @} */
279
280 /** @return true if it is an integer physical register. */
281 bool isIntPhysReg() const { return isIntReg(); }
282
283 /** @return true if it is a floating-point physical register. */
284 bool isFloatPhysReg() const { return isFloatReg(); }
285
286 /** @Return true if it is a condition-code physical register. */
287 bool isCCPhysReg() const { return isCCReg(); }
288
289 /** @Return true if it is a vector physical register. */
290 bool isVectorPhysReg() const { return isVecReg(); }
291
292 /** @Return true if it is a vector element physical register. */
293 bool isVectorPhysElem() const { return isVecElem(); }
294
295 /** @return true if it is a vector predicate physical register. */
296 bool isVecPredPhysReg() const { return isVecPredReg(); }
297
298 /** @Return true if it is a condition-code physical register. */
299 bool isMiscPhysReg() const { return isMiscReg(); }
300
301 /**
302 * Returns true if this register is always associated to the same
303 * architectural register.
304 */
305 bool isFixedMapping() const
306 {
307 return !isRenameable();
308 }
309
310 /** Flat index accessor */
311 const PhysRegIndex& flatIndex() const { return flatIdx; }
312
313 static PhysRegId elemId(PhysRegId* vid, ElemIndex elem)
314 {
315 assert(vid->isVectorPhysReg());
316 return PhysRegId(VecElemClass, vid->index(), elem);
317 }
318
319 int getNumPinnedWrites() const { return numPinnedWrites; }
320
321 void setNumPinnedWrites(int numWrites)
322 {
323 // An instruction with a pinned destination reg can get
324 // squashed. The numPinnedWrites counter may be zero when
325 // the squash happens but we need to know if the dest reg
326 // was pinned originally in order to reset counters properly
327 // for a possible re-rename using the same physical reg (which
328 // may be required in case of a mem access order violation).
329 pinned = (numWrites != 0);
330 numPinnedWrites = numWrites;
331 }
332
333 void decrNumPinnedWrites() { --numPinnedWrites; }
334 void incrNumPinnedWrites() { ++numPinnedWrites; }
335
336 bool isPinned() const { return pinned; }
337
338 int getNumPinnedWritesToComplete() const
339 {
340 return numPinnedWritesToComplete;
341 }
342
343 void setNumPinnedWritesToComplete(int numWrites)
344 {
345 numPinnedWritesToComplete = numWrites;
346 }
347
348 void decrNumPinnedWritesToComplete() { --numPinnedWritesToComplete; }
349 void incrNumPinnedWritesToComplete() { ++numPinnedWritesToComplete; }
350};
351
352using PhysRegIdPtr = PhysRegId*;
353
354namespace std
355{
356template<>
357struct hash<RegId>
358{
359 size_t operator()(const RegId& reg_id) const
360 {
361 // Extract unique integral values for the effective fields of a RegId.
362 const size_t flat_index = static_cast<size_t>(reg_id.flatIndex());
363 const size_t class_num = static_cast<size_t>(reg_id.regClass);
364
365 const size_t shifted_class_num = class_num << (sizeof(RegIndex) << 3);
366
367 // Concatenate the class_num to the end of the flat_index, in order to
368 // maximize information retained.
369 const size_t concatenated_hash = flat_index | shifted_class_num;
370
371 // If RegIndex is larger than size_t, then class_num will not be
372 // considered by this hash function, so we may wish to perform a
373 // different operation to include that information in the hash.
374 static_assert(sizeof(RegIndex) < sizeof(size_t),
375 "sizeof(RegIndex) should be less than sizeof(size_t)");
376
377 return concatenated_hash;
378 }
379};
380}
381
382#endif // __CPU__REG_CLASS_HH__