scc  2022.4.0
SystemC components library
bit_field.h
1 /*---------------------------------------------------------
2 Copyright (c) 2015 Jeff Preshing
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not
13  claim that you wrote the original software. If you use this software
14  in a product, an acknowledgement in the product documentation would be
15  appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17  misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 ---------------------------------------------------------*/
20 
21 #ifndef __CPP11OM_BITFIELD_H__
22 #define __CPP11OM_BITFIELD_H__
23 
24 #include <cassert>
30 namespace util {
39 template <typename T, int Offset, int Bits> struct BitFieldMember {
40  T value;
41 
42  static_assert(Offset + Bits <= (int)sizeof(T) * 8, "Member exceeds bitfield boundaries");
43  static_assert(Bits < (int)sizeof(T) * 8, "Can't fill entire bitfield with one member");
44 
45  static constexpr T Maximum = (T(1) << Bits) - 1;
46  static constexpr T Mask = Maximum << Offset;
47  T maximum() const { return Maximum; }
48  T one() const { return T(1) << Offset; }
49 
50  operator T() const { return (value >> Offset) & Maximum; }
51 
52  BitFieldMember& operator=(T v) {
53  assert(v <= Maximum); // v must fit inside the bitfield member
54  value = (value & ~Mask) | (v << Offset);
55  return *this;
56  }
57 
58  BitFieldMember& operator+=(T v) {
59  assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member
60  value += v << Offset;
61  return *this;
62  }
63 
64  BitFieldMember& operator-=(T v) {
65  assert(T(*this) >= v); // result must not underflow
66  value -= v << Offset;
67  return *this;
68  }
69 
70  BitFieldMember& operator++() { return *this += 1; }
71  BitFieldMember operator++(int) { // postfix form
72  BitFieldMember tmp(*this);
73  operator++();
74  return tmp;
75  }
76  BitFieldMember& operator--() { return *this -= 1; }
77  BitFieldMember operator--(int) { // postfix form
78  BitFieldMember tmp(*this);
79  operator--();
80  return tmp;
81  }
82 };
83 
91 template <typename T, int BaseOffset, int BitsPerItem, int NumItems> class BitFieldArray {
92 public:
93  T value;
94 
95  static_assert(BaseOffset + BitsPerItem * NumItems <= (int)sizeof(T) * 8, "Array exceeds bitfield boundaries");
96  static_assert(BitsPerItem < (int)sizeof(T) * 8, "Can't fill entire bitfield with one array element");
97 
98  static const T Maximum = (T(1) << BitsPerItem) - 1;
99  T maximum() const { return Maximum; }
100  int numItems() const { return NumItems; }
101 
102  class Element {
103  private:
104  T& value;
105  int offset;
106 
107  public:
108  Element(T& value, int offset)
109  : value(value)
110  , offset(offset) {}
111  T mask() const { return Maximum << offset; }
112 
113  operator T() const { return (value >> offset) & Maximum; }
114 
115  Element& operator=(T v) {
116  assert(v <= Maximum); // v must fit inside the bitfield member
117  value = (value & ~mask()) | (v << offset);
118  return *this;
119  }
120 
121  Element& operator+=(T v) {
122  assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member
123  value += v << offset;
124  return *this;
125  }
126 
127  Element& operator-=(T v) {
128  assert(T(*this) >= v); // result must not underflow
129  value -= v << offset;
130  return *this;
131  }
132 
133  Element& operator++() { return *this += 1; }
134  Element operator++(int) { // postfix form
135  Element tmp(*this);
136  operator++();
137  return tmp;
138  }
139  Element& operator--() { return *this -= 1; }
140  Element operator--(int) { // postfix form
141  Element tmp(*this);
142  operator--();
143  return tmp;
144  }
145  };
146 
147  Element operator[](int i) {
148  assert(i >= 0 && i < NumItems); // array index must be in range
149  return Element(value, BaseOffset + BitsPerItem * i);
150  }
151 
152  const Element operator[](int i) const {
153  assert(i >= 0 && i < NumItems); // array index must be in range
154  return Element(value, BaseOffset + BitsPerItem * i);
155  }
156 };
157 } // namespace util
164 #define BEGIN_BF_DECL(typeName, T) \
165  union typeName { \
166  struct { \
167  T val; \
168  } backing; \
169  typeName(T v = 0) { backing.val = v; } \
170  typeName& operator=(T v) { \
171  backing.val = v; \
172  return *this; \
173  } \
174  operator T&() { return backing.val; } \
175  operator T() const { return backing.val; } \
176  using StorageType = T;
177 
178 #define BF_FIELD(memberName, offset, bits) util::BitFieldMember<StorageType, offset, bits> memberName;
179 
180 #define BF_ARRAY(memberName, offset, bits, numItems) util::BitFieldArray<StorageType, offset, bits, numItems> memberName;
181 
182 #define END_BF_DECL() }
184 #endif // __CPP11OM_BITFIELD_H__
array of bit field elements
Definition: bit_field.h:91
SCC common utilities.
Definition: bit_field.h:30
bit field element
Definition: bit_field.h:39