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

Generated on Fri Feb 28 2020 16:26:58 for gem5 by doxygen 1.8.13