glasgow
glasgow copied to clipboard
AttributeError: 'EnumView' object has no attribute 'name' when using an `amaranth.lib.enum.Enum` with `glasgow.hardware.assembly.add_rw_register()`
Raising bug as requested by @whitequark in Mastodon thread https://aus.social/@jpm/114933922761154443
I'm trying to use an amaranth.lib.enum.Enum with glasgow.hardware.assembly.add_rw_register(), and it is failing with errors:
joel@Joels-iMac-Pro bitstreams % glasgow -vvv run shift-register-cd4021 -V 5
D: g.cli: Glasgow 0.1.dev2601+g7943521.d20250729 (CPython 3.13.5 on macOS-15.5-x86_64-i386-64bit-Mach-O)
D: g.hardware.device: found revC3 device with serial C3-20240518T195949Z
W: g.applet.interface.CD4021: applet is PREVIEW QUALITY and may CORRUPT DATA
D: g.applet.interface.CD4021: setting port A voltage to 5.00 V
D: g.applet.interface.CD4021: setting port B voltage to 5.00 V
D: g.applet.interface.CD4021: assigning pin clock to A1
D: g.applet.interface.CD4021: assigning pin data to A0
D: g.applet.interface.CD4021: assigning pin latch to A2
Traceback (most recent call last):
File "/Users/joel/.local/pipx/venvs/glasgow/bin/glasgow", line 8, in <module>
sys.exit(run_main())
~~~~~~~~^^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/cli.py", line 1056, in run_main
exit(asyncio.new_event_loop().run_until_complete(main()))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "/usr/local/Cellar/[email protected]/3.13.5/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/cli.py", line 653, in main
applet, target = _applet(assembly, args)
~~~~~~~^^^^^^^^^^^^^^^^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/cli.py", line 469, in _applet
applet.build(args)
~~~~~~~~~~~~^^^^^^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/applet/interface/CD4021/__init__.py", line 259, in build
self.ShiftRegisterCD4021_iface = ShiftRegisterCD4021Interface(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
self.logger,
^^^^^^^^^^^^
...<4 lines>...
num_bits=args.num_bits,
^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/applet/interface/CD4021/__init__.py", line 169, in __init__
self._reg_mode = assembly.add_rw_register(component.reg_mode)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "/Users/joel/.local/pipx/venvs/glasgow/lib/python3.13/site-packages/glasgow/hardware/assembly.py", line 555, in add_rw_register
address=2 + len(self._registers), shape=signal.shape(), name=signal.name)
^^^^^^^^^^^
AttributeError: 'EnumView' object has no attribute 'name'
Turning these into a Python enum.Enum works fine, with the appropriate code adjustments to use enum.Enum.value where necessary.
Code snippets in question:
class CD4021Mode(enum.Enum, shape=range(4)):
IDLE = 0 # No command, component is allowed to run
STOP = 1 # Stop processing
LATCH = 2 # Perform latch + data reads
DATA = 3 # Perform data reads only
...
class ShiftRegisterCD4021Component(wiring.Component):
def __init__(self, ports, num_bits: int = 8):
if num_bits < 2:
raise ValueError("num_bits must be 2 or more")
self._ports = ports
self._num_bits = num_bits
self._reg_state = Signal(CD4021State, init=CD4021State.LATCH)
self._reg_data = Signal(self._num_bits + 1, init=0)
super().__init__(
{
"reg_active": Out(
1,
init=0,
), # will be set to 1 when component is busy sampling data
"reg_mode": In(
CD4021Mode,
), # requested working mode, reset to IDLE to start working
"stream_result": Out(
stream.Signature(self._num_bits),
), # output data stream
}
)
...
class ShiftRegisterCD4021Interface:
def __init__(
self,
logger: logging.Logger,
assembly: AbstractAssembly,
*,
clock: GlasgowPin,
data: GlasgowPin,
latch: GlasgowPin,
num_bits: int,
):
self._logger = logger
self._level = logging.DEBUG if self._logger.name == __name__ else logging.TRACE
ports = assembly.add_port_group(clock=clock, data=data, latch=latch)
component = assembly.add_submodule(
ShiftRegisterCD4021Component(ports, num_bits=num_bits), name="cd4021"
)
self._result_pipe = assembly.add_in_pipe(component.stream_result)
self._reg_mode = assembly.add_rw_register(component.reg_mode)
self._reg_active = assembly.add_ro_register(component.reg_active)
...
class ShiftRegisterCD4021Applet(GlasgowAppletV2):
...
def build(self, args):
with self.assembly.add_applet(self):
# FIXME - detect requested voltage, info if < 5V, warn if < 3V
self.assembly.use_voltage(args.voltage)
self.ShiftRegisterCD4021_iface = ShiftRegisterCD4021Interface(
self.logger,
self.assembly,
clock=args.clock,
data=args.data,
latch=args.latch,
num_bits=args.num_bits,
)
...