blob: b4e7f9b8e99b057e6112a1e3a1b2528bf8df71ae [file] [log] [blame]
Zane Shelleyfd3f9cc2019-07-29 15:02:24 -05001/* IBM_PROLOG_BEGIN_TAG */
2/* This is an automatically generated prolog. */
3/* */
4/* $Source: src/usr/diag/prdf/common/util/prdfBitString.C $ */
5/* */
6/* OpenPOWER HostBoot Project */
7/* */
8/* Contributors Listed Below - COPYRIGHT 2012,2017 */
9/* [+] International Business Machines Corp. */
10/* */
11/* */
12/* Licensed under the Apache License, Version 2.0 (the "License"); */
13/* you may not use this file except in compliance with the License. */
14/* You may obtain a copy of the License at */
15/* */
16/* http://www.apache.org/licenses/LICENSE-2.0 */
17/* */
18/* Unless required by applicable law or agreed to in writing, software */
19/* distributed under the License is distributed on an "AS IS" BASIS, */
20/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
21/* implied. See the License for the specific language governing */
22/* permissions and limitations under the License. */
23/* */
24/* IBM_PROLOG_END_TAG */
25
26/** @file BitString.C
27 * @brief BitString and BitStringBuffer class Definitions
28 */
29
30#include <prdfBitString.H>
31
32#include <prdfAssert.h>
33
34#include <algorithm>
35
36namespace PRDF
37{
38#if defined(PRDF_HOSTBOOT_ERRL_PLUGIN)
39namespace HOSTBOOT
40{
41#elif defined(PRDF_FSP_ERRL_PLUGIN)
42namespace FSP
43{
44#endif
45
46
47//##############################################################################
48// BitString class
49//##############################################################################
50
51const uint32_t BitString::CPU_WORD_BIT_LEN = sizeof(CPU_WORD) * 8;
52
53const CPU_WORD BitString::CPU_WORD_MASK = static_cast<CPU_WORD>(-1);
54
55//------------------------------------------------------------------------------
56
57CPU_WORD BitString::getField( uint32_t i_pos, uint32_t i_len ) const
58{
59 PRDF_ASSERT( nullptr != getBufAddr() ); // must to have a valid address
60 PRDF_ASSERT( 0 < i_len ); // must have at least one bit
61 PRDF_ASSERT( i_len <= CPU_WORD_BIT_LEN ); // i_len length must be valid
62 PRDF_ASSERT( i_pos + i_len <= getBitLen() ); // field must be within range
63
64 // The returned value.
65 CPU_WORD o_val = 0;
66
67 // Get the relative address and position of the field.
68 uint32_t relPos = 0;
69 CPU_WORD * relAddr = getRelativePosition( relPos, i_pos );
70
71 // The return value may cross two CPU_WORD addresses. Get length of each
72 // chunk, mask to clear the right-handed bits, and the shift value to make
73 // each chunk left-justified.
74 uint32_t len0 = i_len, len1 = 0;
75 if ( CPU_WORD_BIT_LEN < relPos + i_len )
76 {
77 len0 = CPU_WORD_BIT_LEN - relPos;
78 len1 = i_len - len0;
79 }
80
81 CPU_WORD mask0 = CPU_WORD_MASK << (CPU_WORD_BIT_LEN - len0);
82 CPU_WORD mask1 = CPU_WORD_MASK << (CPU_WORD_BIT_LEN - len1);
83
84 uint32_t shift0 = relPos;
85 uint32_t shift1 = CPU_WORD_BIT_LEN - relPos;
86
87 // Get first half of the value.
88 o_val = (*relAddr << shift0) & mask0;
89
90 // Get the second half of the value, if needed
91 if ( CPU_WORD_BIT_LEN < relPos + i_len )
92 {
93 ++relAddr;
94 o_val |= (*relAddr & mask1) >> shift1;
95 }
96
97 return o_val;
98}
99
100//------------------------------------------------------------------------------
101
102void BitString::setField( uint32_t i_pos, uint32_t i_len, CPU_WORD i_val )
103{
104 PRDF_ASSERT( nullptr != getBufAddr() ); // must to have a valid address
105 PRDF_ASSERT( 0 < i_len ); // must have at least one bit
106 PRDF_ASSERT( i_len <= CPU_WORD_BIT_LEN ); // i_len length must be valid
107 PRDF_ASSERT( i_pos + i_len <= getBitLen() ); // field must be within range
108
109 // Get the relative address and position of the field.
110 uint32_t relPos = 0;
111 CPU_WORD * relAddr = getRelativePosition( relPos, i_pos );
112
113 // The value is left-justified. Ignore all other bits.
114 CPU_WORD mask = CPU_WORD_MASK << (CPU_WORD_BIT_LEN - i_len);
115 CPU_WORD val = i_val & mask;
116
117 // Set first half of the value.
118 *relAddr &= ~(mask >> relPos); // Clear field
119 *relAddr |= (val >> relPos); // Set field
120
121 // Get the second half of the value, if needed
122 if ( CPU_WORD_BIT_LEN < relPos + i_len )
123 {
124 relAddr++;
125 *relAddr &= ~(mask << (CPU_WORD_BIT_LEN - relPos)); // Clear field
126 *relAddr |= (val << (CPU_WORD_BIT_LEN - relPos)); // Set field
127 }
128}
129
130//------------------------------------------------------------------------------
131
132void BitString::setPattern( uint32_t i_sPos, uint32_t i_sLen,
133 CPU_WORD i_pattern, uint32_t i_pLen )
134{
135 PRDF_ASSERT(nullptr != getBufAddr()); // must to have a valid address
136 PRDF_ASSERT(0 < i_sLen); // must have at least one bit
137 PRDF_ASSERT(i_sPos + i_sLen <= getBitLen()); // field must be within range
138 PRDF_ASSERT(0 < i_pLen); // must have at least one bit
139 PRDF_ASSERT(i_pLen <= CPU_WORD_BIT_LEN); // i_pLen length must be valid
140
141 // Get a bit string for the pattern subset (right justified).
142 BitString bso ( i_pLen, &i_pattern, CPU_WORD_BIT_LEN - i_pLen );
143
144 // Iterate the range in chunks the size of i_pLen.
145 uint32_t endPos = i_sPos + i_sLen;
146 for ( uint32_t pos = i_sPos; pos < endPos; pos += i_pLen )
147 {
148 // The true chunk size is either i_pLen or the leftovers at the end.
149 uint32_t len = std::min( i_pLen, endPos - pos );
150
151 // Get this chunk's pattern value, truncate (left justified) if needed.
152 CPU_WORD pattern = bso.getField( 0, len );
153
154 // Set the pattern in this string.
155 setField( pos, len, pattern );
156 }
157}
158
159//------------------------------------------------------------------------------
160
161void BitString::setString( const BitString & i_sStr, uint32_t i_sPos,
162 uint32_t i_sLen, uint32_t i_dPos )
163{
164 // Ensure the source parameters are valid.
165 PRDF_ASSERT( nullptr != i_sStr.getBufAddr() );
166 PRDF_ASSERT( 0 < i_sLen ); // at least one bit to copy
167 PRDF_ASSERT( i_sPos + i_sLen <= i_sStr.getBitLen() );
168
169 // Ensure the destination has at least one bit available to copy.
170 PRDF_ASSERT( nullptr != getBufAddr() );
171 PRDF_ASSERT( i_dPos < getBitLen() );
172
173 // If the source length is greater than the destination length than the
174 // extra source bits are ignored.
175 uint32_t actLen = std::min( i_sLen, getBitLen() - i_dPos );
176
177 // The bit strings may be in overlapping memory spaces. So we need to copy
178 // the data in the correct direction to prevent overlapping.
179 uint32_t sRelOffset = 0, dRelOffset = 0;
180 CPU_WORD * sRelAddr = i_sStr.getRelativePosition( sRelOffset, i_sPos );
181 CPU_WORD * dRelAddr = getRelativePosition( dRelOffset, i_dPos );
182
183 // Copy the data.
184 if ( (dRelAddr == sRelAddr) && (dRelOffset == sRelOffset) )
185 {
186 // Do nothing. The source and destination are the same.
187 }
188 else if ( (dRelAddr < sRelAddr) ||
189 ((dRelAddr == sRelAddr) && (dRelOffset < sRelOffset)) )
190 {
191 // Copy the data forward.
192 for ( uint32_t pos = 0; pos < actLen; pos += CPU_WORD_BIT_LEN )
193 {
194 uint32_t len = std::min( actLen - pos, CPU_WORD_BIT_LEN );
195
196 CPU_WORD value = i_sStr.getField( i_sPos + pos, len );
197 setField( i_dPos + pos, len, value );
198 }
199 }
200 else // Copy the data backwards.
201 {
202 // Get the first position of the last chunk (CPU_WORD aligned).
203 uint32_t lastPos = ((actLen-1) / CPU_WORD_BIT_LEN) * CPU_WORD_BIT_LEN;
204
205 // Start with the last chunk and work backwards.
206 for ( int32_t pos = lastPos; 0 <= pos; pos -= CPU_WORD_BIT_LEN )
207 {
208 uint32_t len = std::min( actLen - pos, CPU_WORD_BIT_LEN );
209
210 CPU_WORD value = i_sStr.getField( i_sPos + pos, len );
211 setField( i_dPos + pos, len, value );
212 }
213 }
214}
215
216//------------------------------------------------------------------------------
217
218void BitString::maskString( const BitString & i_mask )
219{
220 // Get the length of the smallest string.
221 uint32_t actLen = std::min( getBitLen(), i_mask.getBitLen() );
222
223 for ( uint32_t pos = 0; pos < actLen; pos += CPU_WORD_BIT_LEN )
224 {
225 uint32_t len = std::min( actLen - pos, CPU_WORD_BIT_LEN );
226
227 CPU_WORD dVal = getField( pos, len );
228 CPU_WORD sVal = i_mask.getField( pos, len );
229
230 setField( pos, len, dVal & ~sVal );
231 }
232}
233
234//------------------------------------------------------------------------------
235
236bool BitString::isEqual( const BitString & i_str ) const
237{
238 if ( getBitLen() != i_str.getBitLen() )
239 return false; // size not equal
240
241 for ( uint32_t pos = 0; pos < getBitLen(); pos += CPU_WORD_BIT_LEN )
242 {
243 uint32_t len = std::min( getBitLen() - pos, CPU_WORD_BIT_LEN );
244
245 if ( getField(pos, len) != i_str.getField(pos, len) )
246 return false; // bit strings do not match
247 }
248
249 return true; // bit strings match
250}
251
252//------------------------------------------------------------------------------
253
254bool BitString::isZero() const
255{
256 for ( uint32_t pos = 0; pos < getBitLen(); pos += CPU_WORD_BIT_LEN )
257 {
258 uint32_t len = std::min( getBitLen() - pos, CPU_WORD_BIT_LEN );
259
260 if ( 0 != getField(pos, len) )
261 return false; // something is non-zero
262 }
263
264 return true; // everything was zero
265}
266
267//------------------------------------------------------------------------------
268
269uint32_t BitString::getSetCount( uint32_t i_pos, uint32_t i_len ) const
270{
271 uint32_t endPos = i_pos + i_len;
272
273 PRDF_ASSERT( endPos <= getBitLen() );
274
275 uint32_t count = 0;
276
277 for ( uint32_t i = i_pos; i < endPos; i++ )
278 {
279 if ( isBitSet(i) ) count++;
280 }
281
282 return count;
283}
284
285//------------------------------------------------------------------------------
286
287BitStringBuffer BitString::operator~() const
288{
289 BitStringBuffer bsb( getBitLen() );
290
291 for ( uint32_t pos = 0; pos < getBitLen(); pos += CPU_WORD_BIT_LEN )
292 {
293 uint32_t len = std::min( getBitLen() - pos, CPU_WORD_BIT_LEN );
294
295 CPU_WORD dVal = getField( pos, len );
296
297 bsb.setField( pos, len, ~dVal );
298 }
299
300 return bsb;
301}
302
303//------------------------------------------------------------------------------
304
305BitStringBuffer BitString::operator&( const BitString & i_bs ) const
306{
307 // Get the length of the smallest string.
308 uint32_t actLen = std::min( getBitLen(), i_bs.getBitLen() );
309
310 BitStringBuffer bsb( actLen );
311
312 for ( uint32_t pos = 0; pos < actLen; pos += CPU_WORD_BIT_LEN )
313 {
314 uint32_t len = std::min( actLen - pos, CPU_WORD_BIT_LEN );
315
316 CPU_WORD dVal = getField( pos, len );
317 CPU_WORD sVal = i_bs.getField( pos, len );
318
319 bsb.setField( pos, len, dVal & sVal );
320 }
321
322 return bsb;
323}
324
325//------------------------------------------------------------------------------
326
327BitStringBuffer BitString::operator|( const BitString & i_bs ) const
328{
329 // Get the length of the smallest string.
330 uint32_t actLen = std::min( getBitLen(), i_bs.getBitLen() );
331
332 BitStringBuffer bsb( actLen );
333
334 for ( uint32_t pos = 0; pos < actLen; pos += CPU_WORD_BIT_LEN )
335 {
336 uint32_t len = std::min( actLen - pos, CPU_WORD_BIT_LEN );
337
338 CPU_WORD dVal = getField( pos, len );
339 CPU_WORD sVal = i_bs.getField( pos, len );
340
341 bsb.setField( pos, len, dVal | sVal );
342 }
343
344 return bsb;
345}
346
347//------------------------------------------------------------------------------
348
349BitStringBuffer BitString::operator>>( uint32_t i_shift ) const
350{
351 BitStringBuffer bsb( getBitLen() ); // default all zeros
352
353 if ( i_shift < getBitLen() )
354 {
355 // bso overlays bsb, containing the shifted offset.
356 BitString bso ( bsb.getBitLen() - i_shift, bsb.getBufAddr(), i_shift );
357
358 // Copy this into bso.
359 bso.setString( *this );
360 }
361
362 return bsb;
363}
364
365//------------------------------------------------------------------------------
366
367BitStringBuffer BitString::operator<<( uint32_t i_shift ) const
368{
369 BitStringBuffer bsb( getBitLen() ); // default all zeros
370
371 if ( i_shift < getBitLen() )
372 {
373 // bso overlays *this, containing the shifted offset.
374 BitString bso ( this->getBitLen() - i_shift, this->getBufAddr(),
375 i_shift );
376
377 // Copy bso into bsb.
378 bsb.setString( bso );
379 }
380
381 return bsb;
382}
383
384//------------------------------------------------------------------------------
385
386CPU_WORD * BitString::getRelativePosition( uint32_t & o_relPos,
387 uint32_t i_absPos ) const
388{
389 PRDF_ASSERT( nullptr != getBufAddr() ); // must to have a valid address
390 PRDF_ASSERT( i_absPos < getBitLen() ); // must be a valid position
391
392 o_relPos = (i_absPos + iv_offset) % CPU_WORD_BIT_LEN;
393
394 return iv_bufAddr + ((i_absPos + iv_offset) / CPU_WORD_BIT_LEN);
395}
396
397//##############################################################################
398// BitStringBuffer class
399//##############################################################################
400
401BitStringBuffer::BitStringBuffer( uint32_t i_bitLen ) :
402 BitString( i_bitLen, nullptr )
403{
404 initBuffer();
405}
406
407//------------------------------------------------------------------------------
408
409BitStringBuffer::~BitStringBuffer()
410{
411 delete [] getBufAddr();
412}
413
414//------------------------------------------------------------------------------
415
416BitStringBuffer::BitStringBuffer( const BitString & i_bs ) :
417 BitString( i_bs.getBitLen(), nullptr )
418{
419 initBuffer();
420 if ( !i_bs.isZero() ) setString( i_bs );
421}
422
423//------------------------------------------------------------------------------
424
425BitStringBuffer::BitStringBuffer( const BitStringBuffer & i_bsb ) :
426 BitString( i_bsb.getBitLen(), nullptr )
427{
428 initBuffer();
429 if ( !i_bsb.isZero() ) setString( i_bsb );
430}
431
432//------------------------------------------------------------------------------
433
434BitStringBuffer & BitStringBuffer::operator=( const BitString & i_bs )
435{
436 // The initBuffer() function will deallocate the buffer as well, however we
437 // also need to deallocate the buffer here before we set the length.
438 delete [] getBufAddr();
439 setBufAddr( nullptr );
440
441 setBitLen( i_bs.getBitLen() );
442 initBuffer();
443 if ( !i_bs.isZero() ) setString( i_bs );
444
445 return *this;
446}
447
448//------------------------------------------------------------------------------
449
450BitStringBuffer & BitStringBuffer::operator=( const BitStringBuffer & i_bsb )
451{
452 if ( this != &i_bsb ) // Check for assignment to self
453 {
454 // The initBuffer() function will deallocate the buffer as well, however
455 // we also need to deallocate the buffer here before we set the length.
456 delete [] getBufAddr();
457 setBufAddr( nullptr );
458
459 setBitLen( i_bsb.getBitLen() );
460 initBuffer();
461 if ( !i_bsb.isZero() ) setString( i_bsb );
462 }
463
464 return *this;
465}
466
467//------------------------------------------------------------------------------
468
469void BitStringBuffer::initBuffer()
470{
471 // Deallocate the current buffer.
472 delete [] getBufAddr();
473
474 // Allocate the new buffer.
475 setBufAddr( new CPU_WORD[ getNumCpuWords(getBitLen()) ] );
476
477 // Clear the new buffer.
478 if ( !isZero() ) clearAll();
479}
480
481/*--------------------------------------------------------------------*/
482/* IO Stream Conditional Support */
483/*--------------------------------------------------------------------*/
484
485#ifdef _USE_IOSTREAMS_
486
487std::ostream & operator<<(std::ostream & out,
488 const BitString & bit_string )
489{
490 const uint32_t bit_field_length = BitString::CPU_WORD_BIT_LEN;
491 out << std::hex;
492 for(uint32_t pos = 0; pos < bit_string.getBitLen(); pos += bit_field_length)
493 {
494 uint32_t len = bit_string.getBitLen() - pos;
495 len = std::min(len,bit_field_length);
496 CPU_WORD value = bit_string.getField(pos,len);
497 out << std::setw(bit_field_length/4) << std::setfill('0') << value << " ";
498 }
499
500 return(out);
501}
502
503#endif
504
505#if defined(PRDF_HOSTBOOT_ERRL_PLUGIN) || defined(PRDF_FSP_ERRL_PLUGIN)
506} // end namespace FSP/HOSTBOOT
507#endif
508} // end namespace PRDF
509