File indexing completed on 2025-07-02 07:53:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <DDSegmentation/BitFieldCoder.h>
0012
0013 #include <cmath>
0014 #include <algorithm>
0015 #include <sstream>
0016 #include <stdexcept>
0017
0018 namespace dd4hep{
0019
0020 namespace DDSegmentation {
0021
0022 BitFieldElement::BitFieldElement( const std::string& fieldName,
0023 unsigned fieldOffset, int signedWidth ) :
0024 _mask(0),
0025 _offset( fieldOffset ),
0026 _width( abs( signedWidth ) ),
0027 _minVal(0),
0028 _maxVal(0),
0029 _isSigned( signedWidth < 0 ),
0030 _name( fieldName ) {
0031
0032
0033 if( _offset > 63 || _offset+_width > 64 ) {
0034
0035 std::stringstream s ;
0036 s << " BitFieldElement '" << _name << "': out of range - offset : "
0037 << _offset << " width " << _width ;
0038
0039 throw( std::runtime_error( s.str() ) ) ;
0040 }
0041
0042 _mask = ( ( 0x0001LL << _width ) - 1 ) << _offset ;
0043
0044
0045
0046 if( _isSigned ){
0047
0048 _minVal = ( 1LL << ( _width - 1 ) ) - ( 1LL << _width ) ;
0049 _maxVal = ( 1LL << ( _width - 1 ) ) - 1 ;
0050
0051 } else {
0052 _maxVal = 0x0001<<_width ;
0053 }
0054 }
0055
0056 FieldID BitFieldElement::value(CellID id) const {
0057 if( _isSigned ) {
0058 FieldID val = ( id & _mask ) >> _offset ;
0059 if( ( val & ( 1LL << ( _width - 1 ) ) ) != 0 ) {
0060 val -= ( 1LL << _width );
0061 }
0062 return val ;
0063 } else {
0064 return ( id & _mask ) >> _offset ;
0065 }
0066 }
0067
0068 void BitFieldElement::set(CellID& field, FieldID in) const {
0069
0070
0071 if( in < _minVal || in > _maxVal ) {
0072 std::stringstream s ;
0073 s << " BitFieldElement '" << _name << "': out of range : " << in
0074 << " for width " << _width ;
0075 throw( std::runtime_error( s.str() ) );
0076 }
0077
0078 field &= ~_mask ;
0079 field |= ( ( in << _offset ) & _mask ) ;
0080 }
0081
0082
0083
0084
0085 size_t BitFieldCoder::index( const std::string& name) const {
0086
0087 IndexMap::const_iterator it = _map.find( name ) ;
0088
0089 if( it != _map.end() )
0090
0091 return it->second ;
0092
0093 else
0094 throw std::runtime_error(" BitFieldElement: unknown name: " + name ) ;
0095 }
0096
0097 unsigned BitFieldCoder::highestBit() const {
0098
0099 unsigned hb(0) ;
0100
0101 for(unsigned i=0;i<_fields.size();i++){
0102
0103 if( hb < ( _fields[i].offset() + _fields[i].width() ) )
0104 hb = _fields[i].offset() + _fields[i].width() ;
0105 }
0106 return hb ;
0107 }
0108
0109
0110 std::string BitFieldCoder::valueString(CellID bitfield) const {
0111
0112 std::stringstream os ;
0113
0114 for(unsigned i=0;i<_fields.size();i++){
0115
0116 if( i != 0 ) os << "," ;
0117
0118 os << _fields[i].name() << ":" << _fields[i].value(bitfield) ;
0119
0120 }
0121 return os.str() ;
0122 }
0123
0124 std::string BitFieldCoder::fieldDescription() const {
0125
0126 std::stringstream os ;
0127
0128 for(unsigned i=0;i<_fields.size();i++){
0129
0130 if( i != 0 ) os << "," ;
0131
0132 os << _fields[i].name() << ":"
0133 << _fields[i].offset() << ":" ;
0134
0135 if( _fields[i].isSigned() )
0136 os << "-" ;
0137
0138 os << _fields[i].width() ;
0139
0140 }
0141
0142 return os.str() ;
0143 }
0144
0145 void BitFieldCoder::addField( const std::string& name, unsigned offset, int width ){
0146
0147
0148 _fields.emplace_back(name, offset, width);
0149 BitFieldElement& bfv = _fields.back() ;
0150
0151 _map[ name ] = _fields.size()-1 ;
0152
0153 if( _joined & bfv.mask() ) {
0154
0155 std::stringstream s ;
0156 s << " BitFieldElement::addField(" << name << "): bits already used " << std::hex << _joined
0157 << " for mask " << bfv.mask() ;
0158
0159 throw( std::runtime_error( s.str() ) ) ;
0160
0161 }
0162
0163 _joined |= bfv.mask() ;
0164
0165 }
0166
0167 void BitFieldCoder::init( const std::string& initString) {
0168
0169 unsigned offset = 0 ;
0170
0171
0172 std::vector<std::string> fieldDescriptors ;
0173 StringTokenizer t( fieldDescriptors ,',') ;
0174
0175 std::for_each( initString.begin(), initString.end(), t ) ;
0176
0177 for(unsigned i=0; i< fieldDescriptors.size() ; i++ ){
0178
0179 std::vector<std::string> subfields ;
0180 StringTokenizer ts( subfields ,':') ;
0181
0182 std::for_each( fieldDescriptors[i].begin(), fieldDescriptors[i].end(), ts );
0183
0184 std::string name ;
0185 int width ;
0186 unsigned thisOffset ;
0187
0188 switch( subfields.size() ){
0189
0190 case 2:
0191
0192 name = subfields[0] ;
0193 width = atol( subfields[1].c_str() ) ;
0194 thisOffset = offset ;
0195
0196 offset += abs( width ) ;
0197
0198 break ;
0199
0200 case 3:
0201 name = subfields[0] ;
0202 thisOffset = atol( subfields[1].c_str() ) ;
0203 width = atol( subfields[2].c_str() ) ;
0204
0205 offset = thisOffset + abs( width ) ;
0206
0207 break ;
0208
0209 default:
0210
0211 std::stringstream s ;
0212 s << " BitFieldCoder: invalid number of subfields "
0213 << fieldDescriptors[i] ;
0214
0215 throw( std::runtime_error( s.str() ) ) ;
0216 }
0217
0218 addField( name , thisOffset, width ) ;
0219 }
0220 }
0221
0222
0223
0224
0225 }
0226
0227 }