DD4hep  1.28.0
Detector Description Toolkit for High Energy Physics
BitFieldCoder.cpp
Go to the documentation of this file.
2 
3 #include <cmath>
4 #include <algorithm>
5 #include <stdexcept>
6 
7 namespace dd4hep{
8 
9  namespace DDSegmentation {
10 
11  BitFieldElement::BitFieldElement( const std::string& fieldName,
12  unsigned fieldOffset, int signedWidth ) :
13  _mask(0),
14  _offset( fieldOffset ),
15  _width( abs( signedWidth ) ),
16  _minVal(0),
17  _maxVal(0),
18  _isSigned( signedWidth < 0 ),
19  _name( fieldName ) {
20 
21  // sanity check
22  if( _offset > 63 || _offset+_width > 64 ) {
23 
24  std::stringstream s ;
25  s << " BitFieldElement '" << _name << "': out of range - offset : "
26  << _offset << " width " << _width ;
27 
28  throw( std::runtime_error( s.str() ) ) ;
29  }
30 
31  _mask = ( ( 0x0001LL << _width ) - 1 ) << _offset ;
32 
33 
34  // compute extreme values for later checks
35  if( _isSigned ){
36 
37  _minVal = ( 1LL << ( _width - 1 ) ) - ( 1LL << _width ) ;
38  _maxVal = ( 1LL << ( _width - 1 ) ) - 1 ;
39 
40  } else {
41  _maxVal = 0x0001<<_width ;
42  }
43  }
44 
46  if( _isSigned ) {
47  FieldID val = ( id & _mask ) >> _offset ;
48  if( ( val & ( 1LL << ( _width - 1 ) ) ) != 0 ) { // negative value
49  val -= ( 1LL << _width );
50  }
51  return val ;
52  } else {
53  return ( id & _mask ) >> _offset ;
54  }
55  }
56 
57  void BitFieldElement::set(CellID& field, FieldID in) const {
58 
59  // check range
60  if( in < _minVal || in > _maxVal ) {
61  std::stringstream s ;
62  s << " BitFieldElement '" << _name << "': out of range : " << in
63  << " for width " << _width ;
64  throw( std::runtime_error( s.str() ) );
65  }
66 
67  field &= ~_mask ; // zero out the field's range
68  field |= ( ( in << _offset ) & _mask ) ;
69  }
70 
71 
72 
73 
74  size_t BitFieldCoder::index( const std::string& name) const {
75 
76  IndexMap::const_iterator it = _map.find( name ) ;
77 
78  if( it != _map.end() )
79 
80  return it->second ;
81 
82  else
83  throw std::runtime_error(" BitFieldElement: unknown name: " + name ) ;
84  }
85 
86  unsigned BitFieldCoder::highestBit() const {
87 
88  unsigned hb(0) ;
89 
90  for(unsigned i=0;i<_fields.size();i++){
91 
92  if( hb < ( _fields[i].offset() + _fields[i].width() ) )
93  hb = _fields[i].offset() + _fields[i].width() ;
94  }
95  return hb ;
96  }
97 
98 
99  std::string BitFieldCoder::valueString(CellID bitfield) const {
100 
101  std::stringstream os ;
102 
103  for(unsigned i=0;i<_fields.size();i++){
104 
105  if( i != 0 ) os << "," ;
106 
107  os << _fields[i].name() << ":" << _fields[i].value(bitfield) ;
108 
109  }
110  return os.str() ;
111  }
112 
113  std::string BitFieldCoder::fieldDescription() const {
114 
115  std::stringstream os ;
116 
117  for(unsigned i=0;i<_fields.size();i++){
118 
119  if( i != 0 ) os << "," ;
120 
121  os << _fields[i].name() << ":"
122  << _fields[i].offset() << ":" ;
123 
124  if( _fields[i].isSigned() )
125  os << "-" ;
126 
127  os << _fields[i].width() ;
128 
129  }
130 
131  return os.str() ;
132  }
133 
134  void BitFieldCoder::addField( const std::string& name, unsigned offset, int width ){
135 
136 
137  _fields.emplace_back(name, offset, width);
138  BitFieldElement& bfv = _fields.back() ;
139 
140  _map[ name ] = _fields.size()-1 ;
141 
142  if( _joined & bfv.mask() ) {
143 
144  std::stringstream s ;
145  s << " BitFieldElement::addField(" << name << "): bits already used " << std::hex << _joined
146  << " for mask " << bfv.mask() ;
147 
148  throw( std::runtime_error( s.str() ) ) ;
149 
150  }
151 
152  _joined |= bfv.mask() ;
153 
154  }
155 
156  void BitFieldCoder::init( const std::string& initString) {
157 
158  unsigned offset = 0 ;
159 
160  // need to compute bit field masks and offsets ...
161  std::vector<std::string> fieldDescriptors ;
162  StringTokenizer t( fieldDescriptors ,',') ;
163 
164  std::for_each( initString.begin(), initString.end(), t ) ;
165 
166  for(unsigned i=0; i< fieldDescriptors.size() ; i++ ){
167 
168  std::vector<std::string> subfields ;
169  StringTokenizer ts( subfields ,':') ;
170 
171  std::for_each( fieldDescriptors[i].begin(), fieldDescriptors[i].end(), ts );
172 
173  std::string name ;
174  int width ;
175  unsigned thisOffset ;
176 
177  switch( subfields.size() ){
178 
179  case 2:
180 
181  name = subfields[0] ;
182  width = atol( subfields[1].c_str() ) ;
183  thisOffset = offset ;
184 
185  offset += abs( width ) ;
186 
187  break ;
188 
189  case 3:
190  name = subfields[0] ;
191  thisOffset = atol( subfields[1].c_str() ) ;
192  width = atol( subfields[2].c_str() ) ;
193 
194  offset = thisOffset + abs( width ) ;
195 
196  break ;
197 
198  default:
199 
200  std::stringstream s ;
201  s << " BitFieldCoder: invalid number of subfields "
202  << fieldDescriptors[i] ;
203 
204  throw( std::runtime_error( s.str() ) ) ;
205  }
206 
207  addField( name , thisOffset, width ) ;
208  }
209  }
210 
211 
212 
213 
214  } // namespace
215 
216 } // namespace
dd4hep::DDSegmentation::BitFieldElement::_minVal
int _minVal
Definition: BitFieldCoder.h:86
dd4hep::DDSegmentation::BitFieldElement
Helper class for BitFieldCoder that corresponds to one field value.
Definition: BitFieldCoder.h:32
dd4hep::DDSegmentation::BitFieldElement::_name
std::string _name
Definition: BitFieldCoder.h:89
dd4hep::DDSegmentation::BitFieldElement::_mask
CellID _mask
Definition: BitFieldCoder.h:83
dd4hep::DDSegmentation::StringTokenizer
Helper class for string tokenization.
Definition: BitFieldCoder.h:253
dd4hep::DDSegmentation::BitFieldElement::value
FieldID value(CellID bitfield) const
calculate this field's value given an external 64 bit bitmap
Definition: BitFieldCoder.cpp:45
dd4hep::DDSegmentation::BitFieldElement::_isSigned
bool _isSigned
Definition: BitFieldCoder.h:88
dd4hep::DDSegmentation::BitFieldCoder::_map
IndexMap _map
Definition: BitFieldCoder.h:239
dd4hep::DDSegmentation::BitFieldCoder::_fields
std::vector< BitFieldElement > _fields
Definition: BitFieldCoder.h:238
dd4hep::DDSegmentation::BitFieldCoder::highestBit
unsigned highestBit() const
Definition: BitFieldCoder.cpp:86
dd4hep::DDSegmentation::BitFieldCoder::valueString
std::string valueString(CellID bitfield) const
Definition: BitFieldCoder.cpp:99
dd4hep::DDSegmentation::BitFieldCoder::addField
void addField(const std::string &name, unsigned offset, int width)
Definition: BitFieldCoder.cpp:134
dd4hep::DDSegmentation::FieldID
int64_t FieldID
Definition: BitFieldCoder.h:25
dd4hep::DDSegmentation::BitFieldElement::set
void set(CellID &bitfield, FieldID value) const
Definition: BitFieldCoder.cpp:57
BitFieldCoder.h
dd4hep::DDSegmentation::BitFieldElement::mask
CellID mask() const
Definition: BitFieldCoder.h:73
dd4hep::DDSegmentation::CellID
uint64_t CellID
Definition: BitFieldCoder.h:26
dd4hep::DDSegmentation::BitFieldCoder::index
size_t index(const std::string &name) const
Definition: BitFieldCoder.cpp:74
dd4hep::DDSegmentation::BitFieldElement::_maxVal
int _maxVal
Definition: BitFieldCoder.h:87
dd4hep::DDSegmentation::BitFieldElement::_width
unsigned _width
Definition: BitFieldCoder.h:85
dd4hep::DDSegmentation::BitFieldCoder::_joined
CellID _joined
Definition: BitFieldCoder.h:240
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::DDSegmentation::BitFieldCoder::init
void init(const std::string &initString)
Definition: BitFieldCoder.cpp:156
dd4hep::DDSegmentation::BitFieldCoder::fieldDescription
std::string fieldDescription() const
Definition: BitFieldCoder.cpp:113
dd4hep::DDSegmentation::BitFieldElement::BitFieldElement
BitFieldElement()=default
Default constructor.
dd4hep::DDSegmentation::BitFieldElement::_offset
unsigned _offset
Definition: BitFieldCoder.h:84