icdutil.num module

Hardware Related Numeric Calculations.

exception icdutil.num.AlignError[source]

Bases: RuntimeError

Alignment Error.

icdutil.num.align(value: int, offset: Optional[int] = None, align: Optional[int] = None, minalign: int = 1, rewind=False)[source]

Forward value to offset and align and minalign.

Without offset and align nothing happens.

>>> align(5)
5
>>> align(7)
7

An offset forwards the count if necessary or raises an AlignError.

>>> align(5, offset=8)
8
>>> align(5, offset=3)
Traceback (most recent call last):
    ...
icdutil.num.AlignError: Cannot use offset 3 as we are already at 5

A align forwards the value to the next multiple of align.

>>> align(5, align=4)
8
>>> align(8, align=4)
8
>>> align(9, align=4)
12

A minalign without align forwards the value to the next multiple of minalign

>>> align(5, minalign=4)
8
>>> align(8, minalign=4)
8
>>> align(9, minalign=4)
12

If both align and minalign are given, then the value is moved to the next multiple of whichever of the both align values is bigger

>>> align(8, align=5, minalign=4)
10
>>> align(8, align=4, minalign=6)
12

If offset is given it is dominant over both align and minalign

>>> align(8, offset=9, align=4, minalign=6)
9
icdutil.num.bytes2word(bytes_: Sequence[int]) int[source]

Convert list of bytes to one word.

>>> print("0x%X" % bytes2word([0x11, 0x22, 0x33, 0x44, 0x55, 0x66]))
0x665544332211
icdutil.num.bytes2words(bytes_: Sequence[int], bytesperword=4) Sequence[int][source]

Convert list of bytes to list of words.

>>> for word in bytes2words([0x11, 0x22, 0x33, 0x44, 0x55, 0x66]):
...    print("0x%X" % word)
0x44332211
0x6655
>>> for word in bytes2words(bytes.fromhex("112233445566")):
...    print("0x%X" % word)
0x44332211
0x6655
>>> for word in bytes2words([0x11, 0x22, 0x33, 0x44, 0x55, 0x66], bytesperword=2):
...    print("0x%X" % word)
0x2211
0x4433
0x6655
>>> for word in bytes2words([]):
...    print("0x%X" % word)
icdutil.num.calc_addrwinmasks(baseaddr, size, addrwidth=32, dontcare='?') Tuple[str, ...][source]

Return tuple of binary compare wildcard masks for address window of size starting at baseaddr.

Parameters:
  • baseaddr (int) – Address window start addresss

  • size (int) – Address window size

Keyword Arguments:
  • addrwidth – Address width in bits

  • dontcare – Character used for don’t care bits

Example:

>>> calc_addrwinmasks(0, 1, addrwidth=4)
('0000',)
>>> calc_addrwinmasks(0xF000, 0x10, addrwidth=16)
('111100000000????',)
>>> calc_addrwinmasks(0xF000, 0x180, addrwidth=16, dontcare='x')
('11110000xxxxxxxx', '111100010xxxxxxx')
>>> calc_addrwinmasks(0xEFF0, 0x100, addrwidth=16)
('111011111111????', '111100000???????', '1111000010??????', '11110000110?????', '111100001110????')
icdutil.num.calc_lowest_bit_set(num: int) Optional[int][source]

Return bit number which is not zero.

Example:

>>> calc_lowest_bit_set(0xE0)
5
>>> calc_lowest_bit_set(-8)
3
>>> calc_lowest_bit_set(0)
icdutil.num.calc_next_power_of(value: int, base: int = 2)[source]

Return next power of base.

The returned value fulfills the rule base**ceil(log_base(value)) >= value.

>>> calc_next_power_of(1)
2
>>> calc_next_power_of(1, base=5)
5
>>> calc_next_power_of(10)
16
>>> calc_next_power_of(10, base=3)
27
>>> calc_next_power_of(16)
16
>>> calc_next_power_of(9, base=3)
9
>>> calc_next_power_of(17)
32
>>> calc_next_power_of(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be positive. -5 is not.
icdutil.num.calc_next_power_of2(value: int)[source]

Return next power of 2.

The returned value fulfills the rule 2**ceil(log2(value)) >= value.

>>> calc_next_power_of2(1)
2
>>> calc_next_power_of2(10)
16
>>> calc_next_power_of2(16)
16
>>> calc_next_power_of2(17)
32
>>> calc_next_power_of2(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be positive. -5 is not.
icdutil.num.calc_prev_power_of(value: int, base: int = 2)[source]

Return previous power of base.

The returned value fulfills the rule base**exp <= value.

>>> calc_prev_power_of(1)
1
>>> calc_prev_power_of(1, base=7)
1
>>> calc_prev_power_of(15)
8
>>> calc_prev_power_of(16)
16
>>> calc_prev_power_of(17)
16
>>> calc_prev_power_of(10, base=3)
9
>>> calc_prev_power_of(27, base=3)
27
>>> calc_prev_power_of(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be positive. -5 is not.
icdutil.num.calc_prev_power_of2(value: int)[source]

Return previous power of base.

The returned value fulfills the rule 2**floor(log2(value)) <= value.

>>> calc_prev_power_of2(1)
1
>>> calc_prev_power_of2(15)
8
>>> calc_prev_power_of2(16)
16
>>> calc_prev_power_of2(17)
16
>>> calc_prev_power_of2(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be positive. -5 is not.
icdutil.num.calc_signed_width(value: int) int[source]

Return width in bits for value.

>>> calc_signed_width(15)
5
>>> calc_signed_width(16)
6
>>> calc_signed_width(8191)
14
>>> calc_signed_width(-7)
4
>>> calc_signed_width(-8)
4
>>> calc_signed_width(-9)
5
>>> calc_signed_width(0)
1
icdutil.num.calc_unsigned_width(value: int) int[source]

Return width in bits for value.

>>> calc_unsigned_width(3)
2
>>> calc_unsigned_width(4)
3
>>> calc_unsigned_width(7)
3
>>> calc_unsigned_width(8)
4
>>> calc_unsigned_width(15)
4
>>> calc_unsigned_width(16)
5
>>> calc_unsigned_width(8191)
13
>>> calc_unsigned_width(0)
1
>>> calc_unsigned_width(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be not negative. -5 is not.
icdutil.num.convwidth(iterable, srcwidth=32, destwidth=8)[source]

Convert iterable with values of srcwidth to list of values of destwidth.

>>> [hex(i) for i in convwidth([0x04030201, 0x08070605], 32, 16)]
['0x201', '0x403', '0x605', '0x807']
>>> [hex(i) for i in convwidth([0x0807060504030201], 64, 16)]
['0x201', '0x403', '0x605', '0x807']
>>> [hex(i) for i in convwidth([0x0807060504030201], 64, 8)]
['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7', '0x8']
>>> [hex(i) for i in convwidth([], 32, 16)]
[]
>>> [hex(i) for i in convwidth([0x201, 0x403, 0x605, 0x807], 16, 32)]
['0x4030201', '0x8070605']
>>> [hex(i) for i in convwidth([0x201, 0x403, 0x605, 0x807], 16, 64)]
['0x807060504030201']
>>> [hex(i) for i in convwidth([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8], 8, 64)]
['0x807060504030201']
>>> [hex(i) for i in convwidth([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8], 8, 56)]
['0x7060504030201', '0x8']
>>> [hex(i) for i in convwidth([], 16, 32)]
[]
>>> [hex(i) for i in convwidth([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8], 8, 8)]
['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7', '0x8']
icdutil.num.is_power_of(value: int, base: int = 2) int[source]

Return True if value is power of base.

>>> is_power_of(15)
False
>>> is_power_of(16)
True
>>> is_power_of(17)
False
>>> is_power_of(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be larger than zero. -5 is not.
>>> is_power_of(8, base=3)
False
>>> is_power_of(9, base=3)
True
>>> is_power_of(-9, base=3)
Traceback (most recent call last):
    ...
AssertionError: Value must be larger than zero. -9 is not.
>>> is_power_of(0)
False
>>> is_power_of(0, base=6)
False
icdutil.num.is_power_of2(value: int) int[source]

Return True if value is power of 2.

>>> is_power_of2(15)
False
>>> is_power_of2(16)
True
>>> is_power_of2(17)
False
>>> is_power_of2(-5)
Traceback (most recent call last):
    ...
AssertionError: Value must be larger than zero. -5 is not.
>>> is_power_of2(0)
False
icdutil.num.signed_to_hex(value: int, width: int, prefix: str = '') str[source]

Convert signed value to width bit hex.

Example:

>>> signed_to_hex(15, 8)
'0F'
>>> signed_to_hex(-3, 6)
'3D'
>>> signed_to_hex(5, 9)
'005'
>>> signed_to_hex(-9, 4)
Traceback (most recent call last):
    ...
ValueError: -9 is not a signed 4 bit integer
>>> signed_to_hex(8, 4)
Traceback (most recent call last):
    ...
ValueError: 8 is not a signed 4 bit integer
>>> signed_to_hex(5, 9, prefix="{width}'h")
"9'h005"
icdutil.num.signed_to_unsigned(value: int, width: int) int[source]

Convert signed value to unsigned with width.

Example:

>>> signed_to_unsigned(3, 4)
3
>>> signed_to_unsigned(-3, 4)
13
>>> signed_to_unsigned(-3, 8)
253
>>> signed_to_unsigned(-9, 4)
Traceback (most recent call last):
    ...
ValueError: -9 is not a signed 4 bit integer
>>> signed_to_unsigned(8, 4)
Traceback (most recent call last):
    ...
ValueError: 8 is not a signed 4 bit integer
icdutil.num.split_aligned_segs(baseaddr: int, size: int) Tuple[AddrRange, ...][source]

Split address window starting at baseaddr with size into segments with aligned base addresses.

The base addresses of the segments are aligned to calc_next_power_of2(size).

Returns tuple of AddrRange. Segment starting at baseaddr with size.

Parameters:
  • baseaddr (int) – Address window start addresss

  • size (int) – Address window size

Example:

>>> split_aligned_segs(0, 1)
(AddrRange(0x0, '1 byte'),)
>>> split_aligned_segs(1024, 16)
(AddrRange(0x400, '16 bytes'),)
>>> split_aligned_segs(1024, 1024)
(AddrRange(0x400, '1 KB'),)
>>> split_aligned_segs(1024, 1024+768)
(AddrRange(0x400, '1 KB'), AddrRange(0x800, '768 bytes'))
>>> split_aligned_segs(256, 1024+768)
(AddrRange(0x100, '256 bytes'), AddrRange(0x200, '512 bytes'), AddrRange(0x400, '1 KB'))
>>> split_aligned_segs(1000, 1024)  
(AddrRange(0x3E8, '8 bytes'), AddrRange(0x3F0, '16 bytes'), AddrRange(0x400, '512 bytes'), ...(0x600, '488 bytes'))
icdutil.num.to_mask(addrwidth: int, baseaddr: int, exp: int, dontcare='?') str[source]

Convert address range starting at baseaddr with 2**`exp` elements to mask with addrwidth using the dontcare character as mask bits.

>>> to_mask(16, 0x4000, 6)
'0100000000??????'
>>> to_mask(16, 0x6000, 4, 'x')
'011000000000xxxx'
>>> to_mask(16, 0x4004, 6)
Traceback (most recent call last):
    ...
AssertionError: 6 LSBs of '0100000000000100' shall be '000000', not '000100'
icdutil.num.unsigned_to_hex(value: int, width: int, prefix: str = '') str[source]

Convert unsigned value to width bit hex.

Example:

>>> unsigned_to_hex(166, 8)
'A6'
>>> unsigned_to_hex(3, 6)
'03'
>>> unsigned_to_hex(5, 9)
'005'
>>> unsigned_to_hex(26000000, 32)
'018CBA80'
>>> unsigned_to_hex(16, 4)
Traceback (most recent call last):
    ...
ValueError: 16 is not a unsigned 4 bit integer
>>> unsigned_to_hex(-1, 4)
Traceback (most recent call last):
    ...
ValueError: -1 is not a unsigned 4 bit integer
>>> unsigned_to_hex(26000000, 32, prefix="{width}'h")
"32'h018CBA80"
>>> unsigned_to_hex(248, 8, prefix="0x")
'0xF8'
icdutil.num.unsigned_to_signed(value: int, width: int) int[source]

Convert unsigned value to signed with width.

Example:

>>> unsigned_to_signed(3, 4)
3
>>> unsigned_to_signed(13, 4)
-3
>>> unsigned_to_signed(253, 8)
-3
>>> unsigned_to_signed(-9, 4)
Traceback (most recent call last):
    ...
ValueError: -9 is not a unsigned 4 bit integer
icdutil.num.words2bytes(words: Sequence[int], bytesperword: int = 4) Sequence[int][source]

Convert list of words to list of bytes.

>>> for byte_ in words2bytes([0x44332211, 0x6655]):
...    print("0x%X" % byte_)
0x11
0x22
0x33
0x44
0x55
0x66
0x0
0x0
>>> for byte_ in words2bytes([0x44332211, 0x6655], bytesperword=6):
...    print("0x%X" % byte_)
0x11
0x22
0x33
0x44
0x0
0x0
0x55
0x66
0x0
0x0
0x0
0x0