gem5 v24.0.0.0
Loading...
Searching...
No Matches
bitunion.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007-2008 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef __BASE_BITUNION_HH__
30#define __BASE_BITUNION_HH__
31
32#include <functional>
33#include <iostream>
34#include <type_traits>
35#include <typeinfo>
36
37#include "base/bitfield.hh"
38#include "base/compiler.hh"
40
41namespace gem5
42{
43
44// The following implements the BitUnion system of defining bitfields
45//on top of an underlying class. This is done through the pervasive use of
46//both named and unnamed unions which all contain the same actual storage.
47//Since they're unioned with each other, all of these storage locations
48//overlap. This allows all of the bitfields to manipulate the same data
49//without having to have access to each other. More details are provided with
50//the individual components.
51
52//This class wraps around another which defines getter/setter functions which
53//manipulate the underlying data. The type of the underlying data and the type
54//of the bitfield itself are inferred from the argument types of the setter
55//function.
56template<class Base>
57class BitfieldTypeImpl : public Base
58{
59 static_assert(std::is_empty_v<Base>, "Bitfield base class must be empty.");
60
61 private:
62
64 {
65 template<typename>
66 struct T;
67
68 template<typename C, typename Type1, typename Type2>
69 struct T<void (C::*)(Type1 &, Type2)>
70 {
71 typedef Type1 Storage;
72 typedef Type2 Type;
73 };
74
75 struct Wrapper : public Base
76 {
77 using Base::setter;
78 };
79
80 typedef typename T<decltype(&Wrapper::setter)>::Storage Storage;
81 typedef typename T<decltype(&Wrapper::setter)>::Type Type;
82 };
83
84 protected:
85 typedef typename TypeDeducer::Storage Storage;
86 typedef typename TypeDeducer::Type Type;
87
88 Type getter(const Storage &storage) const = delete;
89 void setter(Storage &storage, Type val) = delete;
90
91 BitfieldTypeImpl() = default;
93
95
96 operator Type () const
97 {
98 return Base::getter(__storage);
99 }
100
101 Type
103 {
104 Base::setter(__storage, val);
105 return val;
106 }
107
108 Type
110 {
111 return *this = (Type)other;
112 }
113};
114
115//A wrapper for the above class which allows setting and getting.
116template<class Base>
117class BitfieldType : public BitfieldTypeImpl<Base>
118{
119 protected:
121 using typename Impl::Type;
122
123 public:
124 BitfieldType() = default;
125 BitfieldType(const BitfieldType &) = default;
126
127 operator Type () const { return Impl::operator Type(); }
128
130 Type
132 {
133 return Impl::operator=(other);
134 }
135};
136
137//A wrapper which only supports getting.
138template<class Base>
140{
141 public:
143 using typename Impl::Type;
144
145 BitfieldROType() = default;
146 BitfieldROType(const BitfieldROType &) = default;
147
148 Type operator=(BitfieldROType<Base> const &other) = delete;
149 operator Type () const { return Impl::operator Type(); }
150};
151
152//A wrapper which only supports setting.
153template <class Base>
155{
156 protected:
158 using typename Impl::Type;
159
160 public:
161 BitfieldWOType() = default;
162 BitfieldWOType(const BitfieldWOType &) = default;
163
165 Type
167 {
168 return Impl::operator=(other);
169 }
170};
171
172//This namespace is for classes which implement the backend of the BitUnion
173//stuff. Don't use any of these directly.
174namespace bitfield_backend
175{
176 template<class Storage, int first, int last>
178 {
179 static_assert(first >= last,
180 "Bitfield ranges must be specified as <msb, lsb>");
181
182 protected:
183 uint64_t
184 getter(const Storage &storage) const
185 {
186 return bits(storage, first, last);
187 }
188
189 void
190 setter(Storage &storage, uint64_t val)
191 {
192 replaceBits(storage, first, last, val);
193 }
194 };
195
196 template<class Storage, int first, int last>
197 class Signed
198 {
199 static_assert(first >= last,
200 "Bitfield ranges must be specified as <msb, lsb>");
201
202 protected:
203 int64_t
204 getter(const Storage &storage) const
205 {
206 return sext<first - last + 1>(bits(storage, first, last));
207 }
208
209 void
210 setter(Storage &storage, int64_t val)
211 {
212 replaceBits(storage, first, last, val);
213 }
214 };
215
216 //This class contains the basic bitfield types which are automatically
217 //available within a BitUnion. They inherit their Storage type from the
218 //containing BitUnion.
219 template<class Storage>
221 {
222 protected:
223
224 template<int first, int last=first>
226 template<int first, int last=first>
229 template<int first, int last=first>
232
233 template<int first, int last=first>
236 template<int first, int last=first>
239 template<int first, int last=first>
242 };
243
244 //When a BitUnion is set up, an underlying class is created which holds
245 //the actual union. This class then inherits from it, and provids the
246 //implementations for various operators. Setting things up this way
247 //prevents having to redefine these functions in every different BitUnion
248 //type. More operators could be implemented in the future, as the need
249 //arises.
250 template <class Base>
251 class BitUnionOperators : public Base
252 {
253 static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
254 "BitUnion larger than its storage type.");
255
256 public:
257 BitUnionOperators(typename Base::__StorageType const &val)
258 {
259 Base::__storage = val;
260 }
261
263
264 BitUnionOperators() = default;
265
266 //Conversion operators.
267 operator const typename Base::__StorageType () const
268 {
269 return Base::__storage;
270 }
271
272 //Basic assignment operators.
274 operator=(typename Base::__StorageType const &val)
275 {
276 Base::__storage = val;
277 return *this;
278 }
279
282 {
283 return operator=(other.__storage);
284 }
285
286 //Increment and decrement operators.
289 {
290 Base::__storage++;
291 return *this;
292 }
293
296 {
297 BitUnionOperators ret = *this;
298 operator++();
299 return ret;
300 }
301
304 {
305 Base::__storage--;
306 return *this;
307 }
308
311 {
312 BitUnionOperators ret = *this;
313 operator--();
314 return ret;
315 }
316
317 //Operation and assignment operators
319 operator+=(typename Base::__StorageType const &val)
320 {
321 Base::__storage += val;
322 return *this;
323 }
324
326 operator-=(typename Base::__StorageType const &val)
327 {
328 Base::__storage -= val;
329 return *this;
330 }
331
333 operator*=(typename Base::__StorageType const &val)
334 {
335 Base::__storage *= val;
336 return *this;
337 }
338
340 operator/=(typename Base::__StorageType const &val)
341 {
342 Base::__storage /= val;
343 return *this;
344 }
345
347 operator%=(typename Base::__StorageType const &val)
348 {
349 Base::__storage %= val;
350 return *this;
351 }
352
354 operator&=(typename Base::__StorageType const &val)
355 {
356 Base::__storage &= val;
357 return *this;
358 }
359
361 operator|=(typename Base::__StorageType const &val)
362 {
363 Base::__storage |= val;
364 return *this;
365 }
366
368 operator^=(typename Base::__StorageType const &val)
369 {
370 Base::__storage ^= val;
371 return *this;
372 }
373
375 operator<<=(typename Base::__StorageType const &val)
376 {
377 Base::__storage <<= val;
378 return *this;
379 }
380
382 operator>>=(typename Base::__StorageType const &val)
383 {
384 Base::__storage >>= val;
385 return *this;
386 }
387 };
388} // namespace bitfield_backend
389
390//This macro is a backend for other macros that specialize it slightly.
391//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
392//sticks the class which has the actual union in it, which
393//BitfieldOperators above inherits from. Putting these classes in a special
394//namespace ensures that there will be no collisions with other names as long
395//as the BitUnion names themselves are all distinct and nothing else uses
396//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
397//creates a typedef of the "type" parameter called __StorageType. This allows
398//the type to propagate outside of the macro itself in a controlled way.
399//Finally, the base storage is defined which BitfieldOperators will refer to
400//in the operators it defines. This macro is intended to be followed by
401//bitfield definitions which will end up inside it's union. As explained
402//above, these is overlayed the __storage member in its entirety by each of the
403//bitfields which are defined in the union, creating shared storage with no
404//overhead.
405#define __BitUnion(type, name) \
406 class BitfieldUnderlyingClasses##name : \
407 public gem5::bitfield_backend::BitfieldTypes<type> \
408 { \
409 protected: \
410 typedef type __StorageType; \
411 friend gem5::bitfield_backend::BitUnionBaseType< \
412 gem5::bitfield_backend::BitUnionOperators< \
413 BitfieldUnderlyingClasses##name> >; \
414 friend gem5::bitfield_backend::BitUnionBaseType< \
415 BitfieldUnderlyingClasses##name>; \
416 public: \
417 union { \
418 type __storage;
419
428#define EndBitUnion(name) \
429 }; \
430 }; \
431 typedef gem5::bitfield_backend::BitUnionOperators< \
432 BitfieldUnderlyingClasses##name> name;
433
434//This sets up a bitfield which has other bitfields nested inside of it. The
435//__storage member functions like the "underlying storage" of the top level
436//BitUnion. Like everything else, it overlays with the top level storage, so
437//making it a regular bitfield type makes the entire thing function as a
438//regular bitfield when referred to by itself.
439#define __SubBitUnion(name, fieldType, ...) \
440 class \
441 { \
442 public: \
443 union { \
444 fieldType<__VA_ARGS__> __storage;
445
455#define EndSubBitUnion(name) \
456 }; \
457 inline operator __StorageType () const \
458 { return __storage; } \
459 \
460 inline __StorageType operator = (const __StorageType & _storage) \
461 { return __storage = _storage;} \
462 } name;
463
470#define SubBitUnion(name, first, last) \
471 __SubBitUnion(name, Bitfield, first, last)
472
479#define SignedSubBitUnion(name, first, last) \
480 __SubBitUnion(name, SignedBitfield, first, last)
481
487#define BitUnion(type, name) __BitUnion(type, name)
488
494#define BitUnion64(name) __BitUnion(uint64_t, name)
495#define BitUnion32(name) __BitUnion(uint32_t, name)
496#define BitUnion16(name) __BitUnion(uint16_t, name)
497#define BitUnion8(name) __BitUnion(uint8_t, name)
498
499
500//These templates make it possible to define other templates related to
501//BitUnions without having to refer to internal typedefs or the
502// bitfield_backend namespace.
503
504//To build a template specialization which works for all BitUnions, accept a
505//template argument T, and then use BitUnionType<T> as an argument in the
506//template. To refer to the basic type the BitUnion wraps, use
507//BitUnionBaseType<T>.
508
509//For example:
510//template <typename T>
511//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
512
513//Also, BitUnionBaseType can be used on a BitUnion type directly.
514
518template <typename T>
520
521namespace bitfield_backend
522{
523 template<typename T>
525 {
527 };
528
529 template<typename T>
531 {
533 };
534} // namespace bitfield_backend
535
539template <typename T>
541
542namespace bitfield_backend
543{
544 template<typename T>
545 static inline std::ostream &
546 bitfieldBackendPrinter(std::ostream &os, const T &t)
547 {
548 os << t;
549 return os;
550 }
551
552 //Since BitUnions are generally numerical values and not character codes,
553 //these specializations attempt to ensure that they get cast to integers
554 //of the appropriate type before printing.
555 template <>
556 inline std::ostream &
557 bitfieldBackendPrinter(std::ostream &os, const char &t)
558 {
559 os << (int)t;
560 return os;
561 }
562
563 template <>
564 inline std::ostream &
565 bitfieldBackendPrinter(std::ostream &os, const unsigned char &t)
566 {
567 os << (unsigned int)t;
568 return os;
569 }
570} // namespace bitfield_backend
571
578template <typename T>
579std::ostream &
580operator << (std::ostream &os, const BitUnionType<T> &bu)
581{
584}
585
586// Specialization for BitUnion types.
587template <class T>
589{
590 static bool
591 parse(const std::string &s, BitUnionType<T> &value)
592 {
593 // Zero initialize storage to avoid leaking an uninitialized value
595 auto res = to_number(s, storage);
596 value = storage;
597 return res;
598 }
599};
600
601template <class T>
603{
604 static void
605 show(std::ostream &os, const BitUnionType<T> &value)
606 {
608 os, static_cast<const BitUnionBaseType<T> &>(value));
609 }
610};
611
612} // namespace gem5
613
614//An STL style hash structure for hashing BitUnions based on their base type.
615namespace std
616{
617 template <typename T>
618 struct hash<gem5::BitUnionType<T>> : public hash<gem5::BitUnionBaseType<T>>
619 {
620 size_t
621 operator() (const gem5::BitUnionType<T> &val) const
622 {
623 return hash<gem5::BitUnionBaseType<T> >::operator()(val);
624 }
625 };
626} // namespace std
627
628#endif // __BASE_BITUNION_HH__
Type operator=(BitfieldROType< Base > const &other)=delete
BitfieldROType()=default
BitfieldROType(const BitfieldROType &)=default
TypeDeducer::Type Type
Definition bitunion.hh:86
TypeDeducer::Storage Storage
Definition bitunion.hh:85
Type operator=(const Type val)
Definition bitunion.hh:102
BitfieldTypeImpl(const BitfieldTypeImpl &)=default
TypeDeducer::Type Type
Definition bitunion.hh:86
Type operator=(BitfieldTypeImpl< Base > const &other)
Definition bitunion.hh:109
void setter(Storage &storage, Type val)=delete
Type getter(const Storage &storage) const =delete
Type operator=(const Type val)
Definition bitunion.hh:129
Type operator=(BitfieldType< Base > const &other)
Definition bitunion.hh:131
TypeDeducer::Type Type
Definition bitunion.hh:86
BitfieldType()=default
BitfieldType(const BitfieldType &)=default
BitfieldWOType()=default
Type operator=(const Type val)
Definition bitunion.hh:164
Type operator=(BitfieldWOType< Base > const &other)
Definition bitunion.hh:166
BitfieldWOType(const BitfieldWOType &)=default
TypeDeducer::Type Type
Definition bitunion.hh:86
BitUnionOperators & operator^=(typename Base::__StorageType const &val)
Definition bitunion.hh:368
BitUnionOperators & operator=(BitUnionOperators const &other)
Definition bitunion.hh:281
BitUnionOperators & operator&=(typename Base::__StorageType const &val)
Definition bitunion.hh:354
BitUnionOperators & operator<<=(typename Base::__StorageType const &val)
Definition bitunion.hh:375
BitUnionOperators & operator-=(typename Base::__StorageType const &val)
Definition bitunion.hh:326
BitUnionOperators(typename Base::__StorageType const &val)
Definition bitunion.hh:257
BitUnionOperators & operator>>=(typename Base::__StorageType const &val)
Definition bitunion.hh:382
BitUnionOperators & operator%=(typename Base::__StorageType const &val)
Definition bitunion.hh:347
BitUnionOperators & operator=(typename Base::__StorageType const &val)
Definition bitunion.hh:274
BitUnionOperators & operator+=(typename Base::__StorageType const &val)
Definition bitunion.hh:319
BitUnionOperators & operator|=(typename Base::__StorageType const &val)
Definition bitunion.hh:361
BitUnionOperators(const BitUnionOperators &)=default
BitUnionOperators & operator*=(typename Base::__StorageType const &val)
Definition bitunion.hh:333
BitUnionOperators & operator/=(typename Base::__StorageType const &val)
Definition bitunion.hh:340
int64_t getter(const Storage &storage) const
Definition bitunion.hh:204
void setter(Storage &storage, int64_t val)
Definition bitunion.hh:210
uint64_t getter(const Storage &storage) const
Definition bitunion.hh:184
void setter(Storage &storage, uint64_t val)
Definition bitunion.hh:190
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition bitfield.hh:129
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition bitfield.hh:216
typename bitfield_backend::BitUnionBaseType< T >::Type BitUnionBaseType
Definition bitunion.hh:540
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 4 > s
Bitfield< 17 > os
Definition misc.hh:838
Bitfield< 63 > val
Definition misc.hh:804
static std::ostream & bitfieldBackendPrinter(std::ostream &os, const T &t)
Definition bitunion.hh:546
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
bool to_number(const std::string &value, Pixel &retval)
Definition pixel.hh:217
static std::ostream & operator<<(std::ostream &os, const DummyMatRegContainer &d)
Definition matrix.hh:564
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
T< decltype(&Wrapper::setter)>::Storage Storage
Definition bitunion.hh:80
T< decltype(&Wrapper::setter)>::Type Type
Definition bitunion.hh:81
static bool parse(const std::string &s, BitUnionType< T > &value)
Definition bitunion.hh:591
static void show(std::ostream &os, const BitUnionType< T > &value)
Definition bitunion.hh:605
static void show(std::ostream &os, const T &value)
BitUnionType< T >::__StorageType Type
Definition bitunion.hh:526

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