- PYNQ version: all current versions
- Board name: any, pure Python issue
- Pull request type: bug fix
- Pull request number: N/A
- Description:
MMIO.write uses type(data) is int to check whether the supplied data is an integer, which excludes IntEnum and IntFlag values despite them being fully int-compatible (isinstance(data, int) returns True for both). This means that passing an IntEnum or IntFlag value directly raises a ValueError: Data type must be int or bytes, requiring an explicit int() cast at the call site as a workaround.
Reproduction:
from enum import IntEnum
from pynq import MMIO
class MyReg(IntEnum):
ENABLE = 1
mmio = MMIO(0x40000000, 0x1000)
mmio.write(0x0, MyReg.ENABLE) # raises ValueError: Data type must be int or bytes.
mmio.write(0x0, int(MyReg.ENABLE)) # workaround
The relevant check in mmio.py:
if type(data) is int:
self.array[idx] = data
elif type(data) is bytes:
self._hook.write(offset, data)
else:
raise ValueError("Data type must be int or bytes.")
The numpy assignment (self.array[idx] = np.uint32(data)) on the integer path handles IntEnum/IntFlag values without issue, so there is no technical reason to exclude them. The fix is to replace the strict identity checks with isinstance checks:
if isinstance(data, int):
self.array[idx] = data
elif isinstance(data, bytes):
self._hook.write(offset, data)
else:
raise ValueError("Data type must be int or bytes.")
This is consistent with Python's duck-typing conventions and would allow IntEnum and IntFlag values to be passed without requiring the caller to manually cast them.
MMIO.writeusestype(data) is intto check whether the supplied data is an integer, which excludesIntEnumandIntFlagvalues despite them being fully int-compatible (isinstance(data, int)returnsTruefor both). This means that passing anIntEnumorIntFlagvalue directly raises aValueError: Data type must be int or bytes, requiring an explicitint()cast at the call site as a workaround.Reproduction:
The relevant check in
mmio.py:The numpy assignment (
self.array[idx] = np.uint32(data)) on the integer path handlesIntEnum/IntFlagvalues without issue, so there is no technical reason to exclude them. The fix is to replace the strict identity checks withisinstancechecks:This is consistent with Python's duck-typing conventions and would allow
IntEnumandIntFlagvalues to be passed without requiring the caller to manually cast them.