summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/common/util/prdfBitString.H
blob: 70f04875f245cdbb2b1291774d8a3b90bea5e3ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/util/prdfBitString.H $               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef PRDFBITSTRING_H
#define PRDFBITSTRING_H

/** @file prdBitString.H
 *  @brief BitString and BitStringBuffer class declarations
 */

#if !defined(PRDF_TYPES_H)
#include <prdf_types.h>
#endif

#if defined(ESW_SIM_COMPILE)
#define _USE_IOSTREAMS_
#endif

#ifdef _USE_IOSTREAMS_
  #include <iostream>
  #include <iomanip>
#endif

#include <prdfAssert.h>

namespace PRDF
{

class BitStringBuffer;

/** This type is used to take advantage of the most efficient memory reference
 *  size for a specific CPU architecture. */
typedef uint32_t CPU_WORD;

/** Size of a CPU_WORD */
constexpr uint32_t CPU_WORD_SIZE = sizeof(CPU_WORD);

/** Bit length of a CPU_WORD */
constexpr uint32_t CPU_WORD_BIT_LEN = CPU_WORD_SIZE * 8;

/** A CPU_WORD with all of the bits set to 1. */
constexpr CPU_WORD CPU_WORD_MASK = static_cast<CPU_WORD>(-1);

//##############################################################################
//                             BitString class
//##############################################################################

/**
 * A BitString is general purpose class providing the ability to manipulate
 * individual bits within an allocated section of contiguous memory.
 *
 * A BitString does not "own" the memory, it only accesses and manipulates the
 * bits in the range specified. Users will need to ensure memory is allocated
 * and deallocated appropriately. As an alternative, a BitStringBuffer is a
 * BitString that will allocate and maintain its own memory.
 *
 * The length of a BitString is only limited by the amount of memory that
 * contains the data buffer.
 *
 * The CPU_WORD type is used internally to reference memory and as the interface
 * type for the field. Ensure that any buffer allocated for a BitString is
 * CPU_WORD aligned so that the BitString does not accidentally access memory
 * beyond availability. For example, say we have a buffer allocated for 6 byte
 * (48 bits) and those 6 bytes are allocated at the very end of accessible
 * memory. When the BitString tries to access the second CPU_WORD, which
 * contains the last 2 bytes of the buffer, an expection will be thrown because
 * the BitString always access an entire CPU_WORD (4 bytes) at a time and the
 * last two bytes are not accessible. Utilize the static function
 * getNumCpuWords() to get the minimum number of CPU_WORDs required to allocate
 * sufficient space in the buffer. For example, getNumCpuWords(48) returns 2.
 *
 * The bit positions are ordered 0 to n (left to right), where n is the bit
 * length minus one. Be default, position 0 will be the first bit of the
 * buffer's start address. The BitStringOffset class allows users to input an
 * offset anywhere within the buffer, which is then used as position 0. This is
 * useful when the data within the buffer is a right-justified.
 */
class BitString
{
  public: // functions

    /**
     * @brief Constructor
     * @param i_bitLen  The number of bits in the bit string.
     * @param i_bufAddr The starting address of the memory buffer.
     * @post  It is possible that i_bitLen may not be CPU_WORD
     *        aligned, however, the memory space allocated for i_bufAddr must be
     *        CPU_WORD aligned to avoid functions in this class accessing memory
     *        outside the available memory space. Use getNumCpuWords() to
     *        calulate the number of CPU_WORDs needed to allocate sufficient
     *        memory space.
     */
    BitString( uint32_t i_bitLen, CPU_WORD * i_bufAddr ) :
        iv_bitLen(i_bitLen), iv_bufAddr(i_bufAddr)
    {}

    /** @brief Destructor */
    virtual ~BitString() {}

    /** @return The number of bits in the bit string buffer. */
    uint32_t getBitLen() const { return iv_bitLen; }

    /** @return The address of the bit string buffer. Note that this may
     *          return nullptr. */
    CPU_WORD * getBufAddr() const { return iv_bufAddr; }

    /**
     * @param i_bitLen The number of bits for a bit string.
     * @param i_offset Optional starting position of the bit string within the
     *                 memory buffer.
     * @return The minimum number of CPU_WORDs required to allocate sufficient
     *         memory space for a bit string.
     */
    static uint32_t getNumCpuWords( uint32_t i_bitLen, uint32_t i_offset = 0 )
    {
        return (i_bitLen + i_offset + CPU_WORD_BIT_LEN-1) / CPU_WORD_BIT_LEN;
    }

    /**
     * @brief  Returns a left-justified value of the given length from the bit
     *         string starting at the given position.
     * @param  i_pos The starting position of the target range.
     * @param  i_len The number of bits of the target range.
     * @return The value of the field range specified (left-justified).
     * @pre    nullptr != getBufAddr()
     * @pre    0 < i_len
     * @pre    i_len <= CPU_WORD_BIT_LEN
     * @pre    i_pos + i_len <= getBitLen()
     */
    CPU_WORD getField( uint32_t i_pos, uint32_t i_len ) const;

    /**
     * @brief  Returns a right-justified value of the given length from the bit
     *         string starting at the given position.
     * @param  i_pos The starting position of the target range.
     * @param  i_len The number of bits of the target range.
     * @return The value of the field range specified (right-justified).
     * @pre    nullptr != getBufAddr()
     * @pre    0 < i_len
     * @pre    i_len <= CPU_WORD_BIT_LEN
     * @pre    i_pos + i_len <= getBitLen()
     */
    CPU_WORD getFieldJustify( uint32_t i_pos, uint32_t i_len ) const
    {
        return getField(i_pos, i_len) >> (CPU_WORD_BIT_LEN - i_len);
    }

    /**
     * @brief  Sets a left-justified value of the given length into the bit
     *         string starting at the given position.
     * @param i_pos The starting position of the target range.
     * @param i_len The number of bits of the target range.
     * @param i_val The left-justified value to set.
     * @pre   nullptr != getBufAddr()
     * @pre   0 < i_len
     * @pre   i_len <= CPU_WORD_BIT_LEN
     * @pre   i_pos + i_len <= getBitLen()
     */
    void setField( uint32_t i_pos, uint32_t i_len, CPU_WORD i_val );

    /**
     * @brief  Sets a right-justified value of the given length into the bit
     *         string starting at the given position.
     * @param i_pos The starting position of the target range.
     * @param i_len The number of bits of the target range.
     * @param i_val The right-justified value to set.
     * @pre   nullptr != getBufAddr()
     * @pre   0 < i_len
     * @pre   i_len <= CPU_WORD_BIT_LEN
     * @pre   i_pos + i_len <= getBitLen()
     */
    void setFieldJustify( uint32_t i_pos, uint32_t i_len, CPU_WORD i_val )
    {
        setField( i_pos, i_len, i_val << (CPU_WORD_BIT_LEN - i_len) );
    }

    /** @brief Sets the entire bit string to 1's. */
    void setAll() { setPattern(CPU_WORD_MASK); }

    /** @brief Sets the entire bit string to 0's. */
    void clearAll() { setPattern(0); }

    /**
     * @brief Sets a range within the string based on the pattern and length
     *        provided.
     * @param i_sPos    Starting position of this string.
     * @param i_sLen    The length of the target range.
     * @param i_pattern The pattern to set (right justified).
     * @param i_pLen    The length of the pattern.
     * @pre   nullptr != getBufAddr()
     * @pre   0 < i_sLen
     * @pre   i_sPos + i_sLen <= getBitLen()
     * @pre   0 < i_pLen <= CPU_WORD_BIT_LEN
     * @post  The pattern is repeated/truncated as needed.
     *
     * Examples:  i_sPos(0), i_sLen(10), i_pattern(0xA), i_pLen(4)
     *            Old String: 0000000000
     *            New String: 1010101010
     *
     *            i_sPos(3), i_sLen(4), i_pattern(0x3), i_pLen(3)
     *            Old String: 0001001000
     *            New String: 0000110000
     */
    void setPattern( uint32_t i_sPos, uint32_t i_sLen,
                     CPU_WORD i_pattern, uint32_t i_pLen );

    /**
     * @brief Sets entire string based on the pattern and length provided.
     * @param i_pattern The pattern to set (right justified).
     * @param i_pLen    The length of the pattern.
     * @note  See definition above for prerequisites.
     * @post  The entire string is filled with the pattern.
     * @post  The pattern is repeated/truncated as needed.
     */
    void setPattern( CPU_WORD i_pattern, uint32_t i_pLen )
    {
        setPattern( 0, getBitLen(), i_pattern, i_pLen );
    }

    /**
     * @brief Sets entire string based on the pattern provided (length of
     *        CPU_WORD).
     * @param i_pattern The pattern to set.
     * @note  See definition above for prerequisites.
     * @post  The entire string is filled with the pattern.
     * @post  The pattern is repeated/truncated as needed.
     */
    void setPattern( CPU_WORD i_pattern )
    {
        setPattern( i_pattern, CPU_WORD_BIT_LEN );
    }

    /**
     * @brief Set bits in this string based on the given string.
     * @param i_sStr The source string.
     * @param i_sPos The starting position of the source string.
     * @param i_sLen The number of bits to copy from the source string.
     * @param i_dPos The starting position of the this string.
     * @pre   nullptr != getBufAddr()
     * @pre   nullptr != i_sStr.getBufAddr()
     * @pre   0 < i_sLen
     * @pre   i_sPos + i_sLen <= i_sStr.getBitLen()
     * @pre   i_dPos < getBitLen()
     * @post  Source bits in given range are copied to this starting at i_dPos.
     * @note  If the length of the given string is greater than the length of
     *        this string, then the extra bits are ignored.
     * @note  If the length of the given string is less than the length of this
     *        string, then the extra bits in this string are not modified.
     * @note  This string and the source string may specify overlapping memory.
     */
    void setString( const BitString & i_sStr, uint32_t i_sPos,
                    uint32_t i_sLen, uint32_t i_dPos = 0 );

    /**
     * @brief Set bits in this string based on the provided string.
     * @param i_sStr The source string.
     * @note  This will try to copy as much of the source as possible to this
     *        string, starting with the first bit in each string.
     * @note  See the other definition of this function for details and
     *        restrictions.
     */
    void setString( const BitString & i_sStr )
    {
        setString( i_sStr, 0, i_sStr.getBitLen() );
    }

    /**
     * @brief Masks (clears) any bits set in this string that correspond to bits
     *        set in the given string (this & ~mask).
     * @param i_mask The mask string.
     * @note  If the length of the given string is greater than the length of
     *        this string, then the extra bits are ignored.
     * @note  If the length of the given string is less than the length of this
     *        string, then the extra bits in this string are not modified.
     */
    void maskString( const BitString & i_mask );

  /*!
   Comparison
   \remarks The bitstrings must be the same length and have the same bits set to be equal
   */
  int operator==(const BitString & string) const
  {
    return(IsEqual(string));
  }

  /*!
   Get the number of bits that are set ("1")
   */
  uint32_t GetSetCount(void) const;

  /*!
   Get the number of bits that are set ("1") in a specific range
   \param starting bit position
   \param # of bits in the range
   \pre bit_position + leng <= getBitLen();
   \post none
   */
  uint32_t GetSetCount(uint32_t bit_position, uint32_t leng) const;

  /*!
   Query if bit is set (1)
   \returns [true|false]
   \param iPos: bit position to test
   */
  bool IsSet(uint32_t iPos) const;

  /*!
   Set a bit (1) at the specified position
   \param iPos: bit position to test
   \post IsSet(iPos) == true
   */
  void Set( uint32_t iPos);

  /*!
   Clear or ReSet a bit (0) at the specified position
   \param iPos: bit position to clear
   \post IsSet(iPos) == false
   */
  void Clear(uint32_t bit_position);

  /*!
   Test equivalence
   \returns [true | false]
   \notes Both strings must be of equal length and have same values to be equal
   */
  bool IsEqual( const BitString & string) const;

  /*!
   Query state of no bits set(1)
   \returns [true | false]
   */
  bool IsZero(void) const;

  /*!
   bitwise NOT
   \returns a bit-wise inverted copy of the specified bit string
   */

  friend BitStringBuffer operator~(const BitString & bs);
  BitStringBuffer operator&(const BitString & bs) const;
  BitStringBuffer operator|(const BitString & bs) const;

  /*!
   Left shift
   \returns bitstring left shifted by count
   \note: the returned bit string is the same length as the source.
   \verbatim
    Example:
                       |---|---|---|---|---|---|---|---|
    BitString content: | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
                       |---|---|---|---|---|---|---|---|
           bit offset   0   1   2   3   4   5   6   7

    operator>>(5)

                       |---|---|---|---|---|---|---|---|
    BitString result:  | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
                       |---|---|---|---|---|---|---|---|


   \endverbatim
   */
  BitStringBuffer operator>>(uint32_t count) const;

  /*!
   Right shift
   \returns a bitstring left shifted by count
   \note: the returned bit string is the same length as the source.
   \verbatim
    Example:
                       |---|---|---|---|---|---|---|---|
    BitString content: | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
                       |---|---|---|---|---|---|---|---|
           bit offset   0   1   2   3   4   5   6   7

    operator<<(4)

                       |---|---|---|---|---|---|---|---|
    BitString result:  | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
                       |---|---|---|---|---|---|---|---|

   \endverbatim
   */
  BitStringBuffer operator<<(uint32_t count) const;

  protected: // functions

    /**
     * @param i_newBufAddr The starting address of the new bit string buffer.
     * @pre   Before calling this function, make sure you deallocate the old
     *        buffer to avoid memory leaks.
     */
    void setBufAddr( CPU_WORD * i_newBufAddr ) { iv_bufAddr = i_newBufAddr; }

    /** @param i_newBitLen The new bit length of this bit string buffer. */
    void setBitLen( uint32_t i_newBitLen ) { iv_bitLen = i_newBitLen; }

  /*!
   Assignment operator
   \param string Reference bit string
   */
  virtual BitString & operator=(const BitString & string);

  /*!
   Gets the CPU_WORD bounded memory address and the relative bit offset within the CPU_WORD
   that corresponds to the provided bit position in the bit string.
   \returns memory address of CPU_WORD
   \returns relative bit offset in the CPU_WORD
   \param iBitPos Bit position in the bit string
   */
  virtual CPU_WORD * GetRelativePosition(uint32_t & oBitOffset, uint32_t iBitPos) const;

  private: // instance variables

    uint32_t   iv_bitLen;  ///< The bit length of this buffer.
    CPU_WORD * iv_bufAddr; ///< The beginning address of this buffer.
};

//##############################################################################
//                          BitStringBuffer class
//##############################################################################

/** A BitStringBuffer is a BitString that maintains its own buffer in memory. It
 *  guarantees that sufficient memory is allocated and deallocated in the
 *  constructor and destructor, respectively. In addition, the assignment
 *  operator will adjust the amount of memory needed, as necessary, for the
 *  assignment. */
class BitStringBuffer : public BitString
{
  public: // functions

    /**
     * @brief Constructor
     * @param i_bitLen Number of bits in the string.
     */
    explicit BitStringBuffer( uint32_t i_bitLen );

    /** @brief Destructor */
    ~BitStringBuffer();

    /** @brief Copy constructor from BitString */
    BitStringBuffer( const BitString & i_bs );

    /** @brief Copy constructor from BitStringBuffer */
    BitStringBuffer( const BitStringBuffer & i_bsb );

    /** @brief Assignment from BitString */
    BitStringBuffer & operator=( const BitString & i_bs );

    /** @brief Assignment from BitStringBuffer */
    BitStringBuffer & operator=( const BitStringBuffer & i_bsb );

  private: // functions

    /** @brief Deallocates the old buffer, if needed, and initializes the new
     *         buffer. */
    void initBuffer();
};

//! BitStringOffset
/*!
 BitStringOffset provides a Bit String that allows a starting position that
 is not limited to a memory aligned boundary.
 \remarks
 The Bit String Offset provides the ability to specify a start bit offset from the
 address provided as the start position of the bit string. The class will
 not modify memory outside the bit string range.
*/
class BitStringOffset:public BitString
{
public:
  /*!
   Constructor
   \param i_offset The bit offset from address of the start of the bitstring
   \param i_len The number of bits in the bitstring
   \param i_address The memory address to base the bitstring on
   */
  BitStringOffset(uint32_t i_offset, uint32_t i_len, CPU_WORD * i_address)
  : BitString(i_len,i_address), ivOffset(i_offset) {}

  /*!
   Destructor - this class does not own it's storage
   */
  virtual ~BitStringOffset(void);

  /*!
   Copy Constructor
   */
   BitStringOffset(const BitStringOffset &i_bs);

   /*!
    Assignment
    */
   BitStringOffset & operator=(const BitStringOffset & i_bs);

   /*!
    Assignment
    */
   virtual BitStringOffset & operator=(const BitString & i_bs);


protected:  // functions

  /*!
   Gets the CPU_WORD bounded memory address and the relative bit offset within the CPU_WORD
   that corresponds to the provided bit position in the bit string.
   \returns memory address of CPU_WORD
   \returns relative bit offset in the CPU_WORD
   \param iBitPos Bit position in the bit string
   */
  virtual CPU_WORD * GetRelativePosition(uint32_t & oBitOffset, uint32_t iBitPos) const;
private:  // data

  uint32_t ivOffset;
};


/*--------------------------------------------------------------------*/
/*  IO Stream Conditional Support                                     */
/*--------------------------------------------------------------------*/

#ifdef _USE_IOSTREAMS_


std::ostream & operator<<( std::ostream & out,
                      const BitString & bit_string);

#endif

inline
BitString & BitString::operator=
(
 const BitString & string
 )
{
  iv_bitLen = string.iv_bitLen;
  iv_bufAddr = string.iv_bufAddr;
  return(*this);
}

inline uint32_t BitString::GetSetCount(void) const
{
  return(GetSetCount(0, getBitLen()));
}

} // end namespace PRDF

#endif
OpenPOWER on IntegriCloud