Bit Slicing¶
Sometimes you want to access only certain bits of a FixedPoint
number.
The FixedPoint.bits
attribute returns a FixedPointBits
object,
which is an int
that support square bracket access.
Bit Random Access¶
One or more contiguous bits in the FixedPointBits
can be accessed
with an int
or slice
key.
Single-Bit Random Access¶
To access a single bit use an integer key. Bits are indexed with the MSb being
index m+n-1
and the LSb being index 0.
>>> x = FixedPoint('0b001001', signed=0, m=3, n=3, str_base=2)
>>> bin(x.bits), x.bits[3]
('0b1001', 1)
You can also access a single bit using a slice
when start and stop
values are equal. The slice step must be either
-1 (indicating a descending range with the MSb as index
m+n-1
and the LSb as index 0)+1 (indicating an ascending range with the MSb as index 0 and the LSb as index
m+n-1
)
>>> x = FixedPoint('0b001000', signed=0, m=3, n=3)
>>> x.bits[3:3:-1] # the middle '1' with a descending range
1
>>> x.bits[2:2:1] # the middle '1' with an ascending range
1
Attempting to access a single bit in this fashion (the slice start and stop are equal) without specifying a step results in an error.
>>> x.bits[3:3]
Traceback (most recent call last):
...
IndexError: Step must be 1 or -1 for equivalent start and stop bound 3.
Multi-Bit Random Access¶
To access multiple bits at a time, slice
s are employed. Both
ascending and descending ranges are supported.
>>> x = FixedPoint(0b0001100, m=7)
>>> x.bits[3:2] # Access the middle two 1s using a descending range
3
>>> x.bits[3:2:-1] # The step can be -1 for clarity but is unnecessary
3
>>> x.bits[3:4] # Access the middle two 1s using an ascending range
3
>>> x.bits[3:4:1] # The step can be +1 for clarity but is unnecessary
3
When a step is used that is not 1 or -1, or when the start/stop index is
negative, the slice accesses the bits as if they were a str
.
>>> x = FixedPoint(0b100_100_100_100)
>>> x.bits[::3] # Get every 3rd bit starting from the first
15
>>> bin(x.bits[:-6]) # Get the last 6 bits
'0b100100'
Bit Mappings¶
Common parts of the FixedPoint
bit string are mapped to keys, specified as
strings (like a dict
).
These include:
integer bits (
'm'
or'int'
)fractional bits (
'n'
or'frac'
)sign bit (
's'
or'sign'
)most significant bit (
'msb'
)least significant bit (
'lsb'
)
If the portion of the FixedPoint
bits does not exist (e.g., the sign bit of
an unsigned number), a KeyError
is raised.
>>> intonly = signed = FixedPoint("0b1110", 1, 4, 0)
>>> fraconly = unsigned = FixedPoint("0b0001", 0, 0, 4)
>>> intonly.bits['m']
14
>>> fraconly.bits['int']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'int' for UQ0.4 format."
>>> intonly.bits['n']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'n' for Q4.0 format."
>>> signed.bits['sign']
1
>>> (-signed).bits['s']
0
>>> unsigned.bits['sign']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'sign' for UQ0.4 format."
>>> intonly.bits['msb'], intonly.bits['lsb']
(1, 0)
>>> fraconly.bits['msb'], fraconly.bits['lsb']
(0, 1)
When the mappings are uppercased, a str
type is returned corresponding
to the binary bits.
>>> intonly = signed = FixedPoint("0b1110", 1, 4, 0)
>>> fraconly = unsigned = FixedPoint("0b0001", 0, 0, 4)
>>> intonly.bits['M']
'1110'
>>> fraconly.bits['INT']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'INT' for UQ0.4 format."
>>> intonly.bits['N']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'N' for Q4.0 format."
>>> signed.bits['SIGN']
'1'
>>> (-signed).bits['S']
'0'
>>> unsigned.bits['SIGN']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'SIGN' for UQ0.4 format."
>>> intonly.bits['MSB'], intonly.bits['LSB']
('1', '0')
>>> fraconly.bits['MSB'], fraconly.bits['LSB']
('0', '1')