phanrahan/magma

m.Enum giving IndexError and 'Can not instance a circuit outside a definition' exception

Closed this issue · 4 comments

I am trying to use m.Enum to code the states of an FSM. https://github.com/phanrahan/mantle/blob/master/examples/fsm/top.py#L5 is the reference being used. Unlike the reference which uses @m.circuit.combinational, I am defining the design using m.Circuit. Code snippet:

import magma as m

class State(m.Enum):
    IDLE = m.uint(0, 2)
    CONFIG = m.uint(1, 2)
    LOOP = m.uint(2, 2)
    FLAG_RESET = m.uint(3, 2)

class LoopState(m.Enum):
    LOOP_READ = m.uint(0, 1)
    LOOP_STIM = m.uint(1, 1)

class axisMaster(m.Product):
    tdata = m.Out(m.UInt[32])
    tvalid = m.Out(m.Bit)
    tready = m.In(m.Bit)
    
class ClThreshStim(m.Circuit):
    io = m.IO(
            hclk=m.In(m.Clock),
            resetn=m.In(m.ResetN),

            config_stim=m.In(m.Bit),
            config_done=m.Out(m.Bit),
            cl_enable=m.In(m.Bit),
            fifo_err=m.Out(m.Bit),

            stim_step=m.In(m.UInt[32]),
            # Skipping...
            cmd_fifo=m.Flip(axisMaster),
            neural=axisMaster
    )

    state = m.Register(m.UInt[2], init=State.IDLE, reset_type=m.ResetN)()
    loop_state = m.Register(m.UInt[1], init=LoopState.LOOP_READ, reset_type=m.ResetN)()
    # Skipping...
    with m.when(state.O == State.IDLE):

This is giving a compile error:

Traceback (most recent call last):
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/circuit.py", line 547, in __init__
    context = get_definition_context()
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/definition_context.py", line 156, in get_definition_context
    return _get_definition_context_stack().peek()
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/common.py", line 23, in peek
    return self._stack[-1]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/giambla2/ws/magma_examples/magma_examples/cl_thresh_stim.py", line 3, in <module>
    class State(m.Enum):
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/enum.py", line 23, in __new__
    max_value = max(value for value in fields.values())
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/bits.py", line 35, in _wrapper
    return fn(*args, **kwargs)
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/bits.py", line 721, in __gt__
    return self.bvugt(other)
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/bits.py", line 70, in wrapped
    return fn(self, other)
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/bits.py", line 425, in bvugt
    return type(self).undirected_t._declare_compare_op("ugt")()(self, other)
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/circuit.py", line 270, in __call__
    self = super(CircuitKind, cls).__call__(*largs, **kwargs)
  File "/home/giambla2/.local/lib/python3.9/site-packages/magma/circuit.py", line 550, in __init__
    raise Exception("Can not instance a circuit outside a definition")
Exception: Can not instance a circuit outside a definition

What is the right way of using Enum with Circuit?

Hmm, looks like that example is out of date.

Looking at the tests, https://github.com/phanrahan/magma/blob/master/tests/test_type/test_enum.py

You can try using it without the explicit type cast, for example:

class State(m.Enum):
    IDLE = 0
    CONFIG = 1
    LOOP = 2
    FLAG_RESET = 3

class LoopState(m.Enum):
    LOOP_READ = 0
    LOOP_STIM = 1

Please leave this open and I will close it when I have updated the documentation

Thanks, @leonardt. Leaving this open.

This just reminded me, https://github.com/phanrahan/magma/blob/master/docs/cheat_sheet.md is a good quick reference guide, please let me know if you see something confusing or out of date, I just did a quick update pass.

Thanks you for updating it. I will let you know in case there is anything.