Coverage for tsfpga/math_utils.py: 100%
42 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-21 20:51 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-21 20:51 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project, a project platform for modern FPGA development.
5# https://tsfpga.com
6# https://github.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
10def to_binary_string(value: int, result_width: int) -> str:
11 """
12 Convert unsigned integer value to a zero-padded string of 1's and 0's.
13 Most significant bit is the first (left-most) character in the string.
15 For example, value 37, width 6, returns ``100101``.
16 For example, value 37, width 8, returns ``00100101``.
18 Arguments:
19 value: The value to be converted.
20 result_width: The supplied ``value`` will be interpreted as an unsigned value with
21 this many bits.
22 The result string will contain this many bit characters.
23 """
24 _check_unsigned_range(value=value, width=result_width)
26 # Cast to binary, pad with zeros on the left.
27 formatting_string = f"{ :0{result_width}b} "
28 padded_binary_string = formatting_string.format(value)
29 assert len(padded_binary_string) == result_width
31 return padded_binary_string
34def to_binary_nibble_string(value: int, result_width_bits: int) -> str:
35 """
36 Convert unsigned integer value to a zero-padded string of 1's and 0's, with each nibble (4 bits)
37 separated by "_".
38 Most significant bit is the first (left-most) character in the string.
40 For example, value 37, width 6, returns ``10_0101``.
41 For example, value 37, width 8, returns ``0010_0101``.
43 Arguments:
44 value: The value to be converted.
45 result_width_bits: The supplied ``value`` will be interpreted as an unsigned value with
46 this many bits.
47 The result string will contain this many bit characters, plus separators.
48 """
49 _check_unsigned_range(value=value, width=result_width_bits)
51 result_width_nibbles = (result_width_bits + 4 - 1) // 4
52 num_separators = result_width_nibbles - 1
53 result_width = result_width_bits + num_separators
55 # Cast to binary, pad with zeros on the left, separate every fourth character.
56 formatting_string = f"{ :0{result_width}_b} "
57 result = formatting_string.format(value)
58 assert len(result) == result_width
60 return result
63def to_hex_string(value: int, result_width_bits: int) -> str:
64 """
65 Convert unsigned integer value to a zero-padded string of 01ABCDEF.
66 Most significant bit is the first (left-most) character in the string.
68 For example, value 60, width 6, returns ``3C``.
69 For example, value 60, width 9, returns ``03C``.
71 Arguments:
72 value: The value to be converted.
73 result_width_bits: The supplied ``value`` will be interpreted as an unsigned value with
74 this many bits.
75 The result string will contain enough hex characters to represent this many
76 bits (rounded up).
77 """
78 _check_unsigned_range(value=value, width=result_width_bits)
80 result_width_nibbles = (result_width_bits + 4 - 1) // 4
82 # Cast to hex, pad with zeros on the left.
83 formatting_string = f"{ :0{result_width_nibbles}X} "
84 result = formatting_string.format(value)
85 assert len(result) == result_width_nibbles
87 return result
90def to_hex_byte_string(value: int, result_width_bits: int) -> str:
91 """
92 Convert unsigned integer value to a zero-padded string of 01ABCDEF, with each byte
93 (8 bits, 2 result characters) separated by "_".
94 Most significant bit is the first (left-most) character in the string.
96 For example, value 60, width 6, returns ``3C``.
97 For example, value 60, width 9, returns ``0_3C``.
99 Arguments:
100 value: The value to be converted.
101 result_width_bits: The supplied ``value`` will be interpreted as an unsigned value with
102 this many bits.
103 The result string will contain enough hex characters to represent this many
104 bits (rounded up), plus separators.
105 """
106 hex_string = to_hex_string(value=value, result_width_bits=result_width_bits)
108 result_width_nibbles = (result_width_bits + 4 - 1) // 4
109 assert len(hex_string) % result_width_nibbles == 0, hex_string
111 byte_strings = []
112 if result_width_nibbles % 2 == 1:
113 byte_strings.append(hex_string[0])
114 for i in range(result_width_nibbles % 2, result_width_nibbles, 2):
115 byte_strings.append(hex_string[i : i + 2])
117 result = "_".join(byte_strings)
119 result_width_bytes = (result_width_bits + 8 - 1) // 8
120 num_separators = result_width_bytes - 1
121 result_width = result_width_nibbles + num_separators
122 assert len(result) == result_width, result
124 return result
127def _check_unsigned_range(value: int, width: int) -> None:
128 if width < 1:
129 raise ValueError(f'Invalid result width "{width}".')
131 if not 0 <= value < 2**width:
132 raise ValueError(f'Value "{value}" out of {width}-bit range.')