gem5  v20.1.0.0
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 
39 // The following implements the BitUnion system of defining bitfields
40 //on top of an underlying class. This is done through the pervasive use of
41 //both named and unnamed unions which all contain the same actual storage.
42 //Since they're unioned with each other, all of these storage locations
43 //overlap. This allows all of the bitfields to manipulate the same data
44 //without having to have access to each other. More details are provided with
45 //the individual components.
46 
47 //This class wraps around another which defines getter/setter functions which
48 //manipulate the underlying data. The type of the underlying data and the type
49 //of the bitfield itself are inferred from the argument types of the setter
50 //function.
51 template<class Base>
52 class BitfieldTypeImpl : public Base
53 {
54  static_assert(std::is_empty<Base>::value,
55  "Bitfield base class must be empty.");
56 
57  private:
58 
59  struct TypeDeducer
60  {
61  template<typename>
62  struct T;
63 
64  template<typename C, typename Type1, typename Type2>
65  struct T<void (C::*)(Type1 &, Type2)>
66  {
67  typedef Type1 Storage;
68  typedef Type2 Type;
69  };
70 
71  struct Wrapper : public Base
72  {
73  using Base::setter;
74  };
75 
76  typedef typename T<decltype(&Wrapper::setter)>::Storage Storage;
77  typedef typename T<decltype(&Wrapper::setter)>::Type Type;
78  };
79 
80  protected:
81  typedef typename TypeDeducer::Storage Storage;
82  typedef typename TypeDeducer::Type Type;
83 
84  Type getter(const Storage &storage) const = delete;
85  void setter(Storage &storage, Type val) = delete;
86 
87  BitfieldTypeImpl() = default;
88  BitfieldTypeImpl(const BitfieldTypeImpl &) = default;
89 
91 
92  operator Type () const
93  {
94  return Base::getter(__storage);
95  }
96 
97  Type
99  {
100  Base::setter(__storage, val);
101  return val;
102  }
103 
104  Type
106  {
107  return *this = (Type)other;
108  }
109 };
110 
111 //A wrapper for the above class which allows setting and getting.
112 template<class Base>
113 class BitfieldType : public BitfieldTypeImpl<Base>
114 {
115  protected:
117  using typename Impl::Type;
118 
119  public:
120  BitfieldType() = default;
121  BitfieldType(const BitfieldType &) = default;
122 
123  operator Type () const { return Impl::operator Type(); }
124 
125  Type operator=(const Type val) { return Impl::operator=(val); }
126  Type
128  {
129  return Impl::operator=(other);
130  }
131 };
132 
133 //A wrapper which only supports getting.
134 template<class Base>
135 class BitfieldROType : public BitfieldTypeImpl<Base>
136 {
137  public:
139  using typename Impl::Type;
140 
141  BitfieldROType() = default;
142  BitfieldROType(const BitfieldROType &) = default;
143 
144  Type operator=(BitfieldROType<Base> const &other) = delete;
145  operator Type () const { return Impl::operator Type(); }
146 };
147 
148 //A wrapper which only supports setting.
149 template <class Base>
150 class BitfieldWOType : public BitfieldTypeImpl<Base>
151 {
152  protected:
154  using typename Impl::Type;
155 
156  public:
157  BitfieldWOType() = default;
158  BitfieldWOType(const BitfieldWOType &) = default;
159 
160  Type operator=(const Type val) { return Impl::operator=(val); }
161  Type
163  {
164  return Impl::operator=(other);
165  }
166 };
167 
168 //This namespace is for classes which implement the backend of the BitUnion
169 //stuff. Don't use any of these directly.
171 {
172  template<class Storage, int first, int last>
173  class Unsigned
174  {
175  static_assert(first >= last,
176  "Bitfield ranges must be specified as <msb, lsb>");
177 
178  protected:
179  uint64_t
180  getter(const Storage &storage) const
181  {
182  return bits(storage, first, last);
183  }
184 
185  void
186  setter(Storage &storage, uint64_t val)
187  {
188  replaceBits(storage, first, last, val);
189  }
190  };
191 
192  template<class Storage, int first, int last>
193  class Signed
194  {
195  static_assert(first >= last,
196  "Bitfield ranges must be specified as <msb, lsb>");
197 
198  protected:
199  int64_t
200  getter(const Storage &storage) const
201  {
202  return sext<first - last + 1>(bits(storage, first, last));
203  }
204 
205  void
206  setter(Storage &storage, int64_t val)
207  {
208  replaceBits(storage, first, last, val);
209  }
210  };
211 
212  //This class contains the basic bitfield types which are automatically
213  //available within a BitUnion. They inherit their Storage type from the
214  //containing BitUnion.
215  template<class Storage>
217  {
218  protected:
219 
220  template<int first, int last=first>
222  template<int first, int last=first>
223  using BitfieldRO =
225  template<int first, int last=first>
226  using BitfieldWO =
228 
229  template<int first, int last=first>
230  using SignedBitfield =
232  template<int first, int last=first>
233  using SignedBitfieldRO =
235  template<int first, int last=first>
236  using SignedBitfieldWO =
238  };
239 
240  //When a BitUnion is set up, an underlying class is created which holds
241  //the actual union. This class then inherits from it, and provids the
242  //implementations for various operators. Setting things up this way
243  //prevents having to redefine these functions in every different BitUnion
244  //type. More operators could be implemented in the future, as the need
245  //arises.
246  template <class Base>
247  class BitUnionOperators : public Base
248  {
249  static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
250  "BitUnion larger than its storage type.");
251 
252  public:
253  BitUnionOperators(typename Base::__StorageType const &val)
254  {
255  Base::__storage = val;
256  }
257 
258  BitUnionOperators(const BitUnionOperators &) = default;
259 
261 
262  operator const typename Base::__StorageType () const
263  {
264  return Base::__storage;
265  }
266 
267  typename Base::__StorageType
268  operator=(typename Base::__StorageType const &val)
269  {
270  Base::__storage = val;
271  return val;
272  }
273 
274  typename Base::__StorageType
276  {
277  Base::__storage = other;
278  return Base::__storage;
279  }
280 
281  bool
282  operator<(Base const &base) const
283  {
284  return Base::__storage < base.__storage;
285  }
286 
287  bool
288  operator==(Base const &base) const
289  {
290  return Base::__storage == base.__storage;
291  }
292  };
293 }
294 
295 //This macro is a backend for other macros that specialize it slightly.
296 //First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
297 //sticks the class which has the actual union in it, which
298 //BitfieldOperators above inherits from. Putting these classes in a special
299 //namespace ensures that there will be no collisions with other names as long
300 //as the BitUnion names themselves are all distinct and nothing else uses
301 //the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
302 //creates a typedef of the "type" parameter called __StorageType. This allows
303 //the type to propagate outside of the macro itself in a controlled way.
304 //Finally, the base storage is defined which BitfieldOperators will refer to
305 //in the operators it defines. This macro is intended to be followed by
306 //bitfield definitions which will end up inside it's union. As explained
307 //above, these is overlayed the __storage member in its entirety by each of the
308 //bitfields which are defined in the union, creating shared storage with no
309 //overhead.
310 #define __BitUnion(type, name) \
311  class BitfieldUnderlyingClasses##name : \
312  public BitfieldBackend::BitfieldTypes<type> \
313  { \
314  protected: \
315  typedef type __StorageType; \
316  friend BitfieldBackend::BitUnionBaseType< \
317  BitfieldBackend::BitUnionOperators< \
318  BitfieldUnderlyingClasses##name> >; \
319  friend BitfieldBackend::BitUnionBaseType< \
320  BitfieldUnderlyingClasses##name>; \
321  public: \
322  union { \
323  type __storage;
324 
333 #define EndBitUnion(name) \
334  }; \
335  }; \
336  typedef BitfieldBackend::BitUnionOperators< \
337  BitfieldUnderlyingClasses##name> name;
338 
339 //This sets up a bitfield which has other bitfields nested inside of it. The
340 //__storage member functions like the "underlying storage" of the top level
341 //BitUnion. Like everything else, it overlays with the top level storage, so
342 //making it a regular bitfield type makes the entire thing function as a
343 //regular bitfield when referred to by itself.
344 #define __SubBitUnion(name, fieldType, ...) \
345  class \
346  { \
347  public: \
348  union { \
349  fieldType<__VA_ARGS__> __storage;
350 
360 #define EndSubBitUnion(name) \
361  }; \
362  inline operator __StorageType () const \
363  { return __storage; } \
364  \
365  inline __StorageType operator = (const __StorageType & _storage) \
366  { return __storage = _storage;} \
367  } name;
368 
375 #define SubBitUnion(name, first, last) \
376  __SubBitUnion(name, Bitfield, first, last)
377 
384 #define SignedSubBitUnion(name, first, last) \
385  __SubBitUnion(name, SignedBitfield, first, last)
386 
392 #define BitUnion(type, name) __BitUnion(type, name)
393 
399 #define BitUnion64(name) __BitUnion(uint64_t, name)
400 #define BitUnion32(name) __BitUnion(uint32_t, name)
401 #define BitUnion16(name) __BitUnion(uint16_t, name)
402 #define BitUnion8(name) __BitUnion(uint8_t, name)
403 
404 
405 //These templates make it possible to define other templates related to
406 //BitUnions without having to refer to internal typedefs or the BitfieldBackend
407 //namespace.
408 
409 //To build a template specialization which works for all BitUnions, accept a
410 //template argument T, and then use BitUnionType<T> as an argument in the
411 //template. To refer to the basic type the BitUnion wraps, use
412 //BitUnionBaseType<T>.
413 
414 //For example:
415 //template <typename T>
416 //void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
417 
418 //Also, BitUnionBaseType can be used on a BitUnion type directly.
419 
423 template <typename T>
425 
426 namespace BitfieldBackend
427 {
428  template<typename T>
430  {
432  };
433 
434  template<typename T>
436  {
438  };
439 }
440 
444 template <typename T>
446 
447 
448 //An STL style hash structure for hashing BitUnions based on their base type.
449 namespace std
450 {
451  template <typename T>
452  struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
453  {
454  size_t
455  operator() (const BitUnionType<T> &val) const
456  {
457  return hash<BitUnionBaseType<T> >::operator()(val);
458  }
459  };
460 }
461 
462 
463 namespace BitfieldBackend
464 {
465 
466  template<typename T>
467  static inline std::ostream &
468  bitfieldBackendPrinter(std::ostream &os, const T &t)
469  {
470  os << t;
471  return os;
472  }
473 
474  //Since BitUnions are generally numerical values and not character codes,
475  //these specializations attempt to ensure that they get cast to integers
476  //of the appropriate type before printing.
477  template <>
478  inline std::ostream &
479  bitfieldBackendPrinter(std::ostream &os, const char &t)
480  {
481  os << (int)t;
482  return os;
483  }
484 
485  template <>
486  inline std::ostream &
487  bitfieldBackendPrinter(std::ostream &os, const unsigned char &t)
488  {
489  os << (unsigned int)t;
490  return os;
491  }
492 }
493 
500 template <typename T>
501 std::ostream &
502 operator << (std::ostream &os, const BitUnionType<T> &bu)
503 {
505  os, (BitUnionBaseType<T>)bu);
506 }
507 
508 #endif // __BASE_BITUNION_HH__
BitfieldBackend::BitUnionOperators::BitUnionOperators
BitUnionOperators(typename Base::__StorageType const &val)
Definition: bitunion.hh:253
BitfieldBackend::BitUnionOperators::operator==
bool operator==(Base const &base) const
Definition: bitunion.hh:288
BitfieldTypeImpl::TypeDeducer
Definition: bitunion.hh:59
BitfieldTypeImpl::TypeDeducer::T
Definition: bitunion.hh:62
X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:803
replaceBits
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:179
BitfieldType::BitfieldType
BitfieldType()=default
BitfieldBackend::BitUnionOperators::operator<
bool operator<(Base const &base) const
Definition: bitunion.hh:282
BitfieldBackend::BitUnionOperators::operator=
Base::__StorageType operator=(BitUnionOperators const &other)
Definition: bitunion.hh:275
BitfieldTypeImpl::__storage
Storage __storage
Definition: bitunion.hh:90
BitfieldTypeImpl::TypeDeducer::Storage
T< decltype(&Wrapper::setter)>::Storage Storage
Definition: bitunion.hh:76
BitfieldROType::BitfieldROType
BitfieldROType()=default
sext
uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition: bitfield.hh:126
X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
BitfieldBackend::Signed::getter
int64_t getter(const Storage &storage) const
Definition: bitunion.hh:200
BitfieldBackend::BitUnionBaseType
Definition: bitunion.hh:429
BitfieldTypeImpl::TypeDeducer::T< void(C::*)(Type1 &, Type2)>::Type
Type2 Type
Definition: bitunion.hh:68
BitfieldTypeImpl::BitfieldTypeImpl
BitfieldTypeImpl()=default
BitfieldTypeImpl::Storage
TypeDeducer::Storage Storage
Definition: bitunion.hh:81
BitfieldTypeImpl::TypeDeducer::Wrapper
Definition: bitunion.hh:71
BitfieldTypeImpl::getter
Type getter(const Storage &storage) const =delete
BitfieldTypeImpl::Type
TypeDeducer::Type Type
Definition: bitunion.hh:82
BitfieldWOType::operator=
Type operator=(const Type val)
Definition: bitunion.hh:160
BitfieldBackend::Unsigned::setter
void setter(Storage &storage, uint64_t val)
Definition: bitunion.hh:186
bitfield.hh
BitfieldBackend::Signed::setter
void setter(Storage &storage, int64_t val)
Definition: bitunion.hh:206
BitfieldTypeImpl::setter
void setter(Storage &storage, Type val)=delete
BitfieldTypeImpl::TypeDeducer::Type
T< decltype(&Wrapper::setter)>::Type Type
Definition: bitunion.hh:77
BitfieldBackend::BitUnionOperators::BitUnionOperators
BitUnionOperators()
Definition: bitunion.hh:260
BitfieldType
Definition: bitunion.hh:113
BitfieldBackend::BitUnionOperators
Definition: bitunion.hh:247
X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
BitfieldBackend::Signed
Definition: bitunion.hh:193
BitfieldTypeImpl::TypeDeducer::T< void(C::*)(Type1 &, Type2)>::Storage
Type1 Storage
Definition: bitunion.hh:67
BitfieldBackend::BitUnionBaseType< BitUnionType< T > >::Type
BitUnionType< T >::__StorageType Type
Definition: bitunion.hh:437
BitfieldBackend::Unsigned::getter
uint64_t getter(const Storage &storage) const
Definition: bitunion.hh:180
BitfieldTypeImpl::operator=
Type operator=(const Type val)
Definition: bitunion.hh:98
BitfieldBackend::BitUnionOperators::operator=
Base::__StorageType operator=(typename Base::__StorageType const &val)
Definition: bitunion.hh:268
BitfieldType::operator=
Type operator=(BitfieldType< Base > const &other)
Definition: bitunion.hh:127
BitfieldTypeImpl
Definition: bitunion.hh:52
BitfieldWOType::BitfieldWOType
BitfieldWOType()=default
BitfieldBackend::Unsigned
Definition: bitunion.hh:173
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
ArmISA::t
Bitfield< 5 > t
Definition: miscregs_types.hh:67
BitfieldBackend::bitfieldBackendPrinter
static std::ostream & bitfieldBackendPrinter(std::ostream &os, const T &t)
Definition: bitunion.hh:468
operator<<
std::ostream & operator<<(std::ostream &os, const BitUnionType< T > &bu)
A default << operator which casts a bitunion to its underlying type and passes it to BitfieldBackend:...
Definition: bitunion.hh:502
BitfieldROType
Definition: bitunion.hh:135
BitfieldType::operator=
Type operator=(const Type val)
Definition: bitunion.hh:125
BitfieldWOType
Definition: bitunion.hh:150
BitfieldROType::operator=
Type operator=(BitfieldROType< Base > const &other)=delete
BitfieldBackend::BitUnionBaseType::Type
BitUnionType< T >::__StorageType Type
Definition: bitunion.hh:431
BitfieldBackend::BitfieldTypes
Definition: bitunion.hh:216
BitfieldTypeImpl::operator=
Type operator=(BitfieldTypeImpl< Base > const &other)
Definition: bitunion.hh:105
BitfieldWOType::operator=
Type operator=(BitfieldWOType< Base > const &other)
Definition: bitunion.hh:162
BitUnionBaseType
typename BitfieldBackend::BitUnionBaseType< T >::Type BitUnionBaseType
Definition: bitunion.hh:445
BitfieldBackend
Definition: bitunion.hh:170
bits
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:75

Generated on Wed Sep 30 2020 14:02:07 for gem5 by doxygen 1.8.17