Open
Description
I'm getting a syntax error when using a function call that creates a signal inside an Elif.
I can understand why this kind of function call might be problematic in a Python DSL, however I'm raising a bug because this code looks like it ought to be valid. If it's breaking a rule, I'm not sure what the rule is.
from amaranth import *
from amaranth.back import verilog
class Stepper(Elaboratable):
def __init__(self):
self.output = Signal(3)
self.up = Signal()
self.down = Signal()
self.ports = [self.output, self.up, self.output]
def edge_detect(self, m, input):
last = Signal()
m.d.sync += last.eq(input)
detected = input & ~last
return detected
def elaborate(self, platform):
m = Module()
with m.If(self.edge_detect(m, self.up)):
m.d.sync += self.output.eq(self.output+1)
with m.Elif(self.edge_detect(m, self.down)):
m.d.sync += self.output.eq(self.output-1)
return m
s = Stepper()
verilog.convert(s, name='Top', ports=s.ports)
fails with:
[/usr/local/lib/python3.7/dist-packages/amaranth/back/verilog.py](https://localhost:8080/#) in convert(elaboratable, name, platform, ports, emit_src, strip_internal_attrs, **kwargs)
48 warnings.warn("Implicit port determination is deprecated, specify ports explictly",
49 DeprecationWarning, stacklevel=2)
---> 50 fragment = ir.Fragment.get(elaboratable, platform).prepare(ports=ports, **kwargs)
51 verilog_text, name_map = convert_fragment(fragment, name, emit_src=emit_src)
52 return verilog_text
[/usr/local/lib/python3.7/dist-packages/amaranth/hdl/ir.py](https://localhost:8080/#) in get(obj, platform)
35 code = obj.elaborate.__code__
36 obj._MustUse__used = True
---> 37 new_obj = obj.elaborate(platform)
38 elif hasattr(obj, "elaborate"):
39 warnings.warn(
[<ipython-input-20-74600c1d41a4>](https://localhost:8080/#) in elaborate(self, platform)
19 with m.If(self.edge_detect(m, self.up)):
20 m.d.sync += self.output.eq(self.output+1)
---> 21 with m.Elif(self.edge_detect(m, self.down)):
22 m.d.sync += self.output.eq(self.output-1)
23 return m
[/usr/lib/python3.7/contextlib.py](https://localhost:8080/#) in __enter__(self)
110 del self.argElif s, self.kwds, self.func
111 try:
--> 112 return next(self.gen)
113 except StopIteration:
114 raise RuntimeError("generator didn't yield") from None
[/usr/local/lib/python3.7/dist-packages/amaranth/hdl/dsl.py](https://localhost:8080/#) in Elif(self, cond)
251 if_data = self._get_ctrl("If")
252 if if_data is None or if_data["depth"] != self.domain._depth:
--> 253 raise SyntaxError("Elif without preceding If")
254 try:
255 _outer_case, self._statements = self._statements, []
SyntaxError: Elif without preceding If
However, when the condition is calculated outside the Elif, it works
from amaranth import *
from amaranth.back import verilog
class Stepper(Elaboratable):
def __init__(self):
self.output = Signal(3)
self.up = Signal()
self.down = Signal()
self.ports = [self.output, self.up, self.output]
def edge_detect(self, m, input):
last = Signal()
m.d.sync += last.eq(input)
detected = input & ~last
return detected
def elaborate(self, platform):
m = Module()
is_down = self.edge_detect(m, self.down)
with m.If(self.edge_detect(m, self.up)):
m.d.sync += self.output.eq(self.output+1)
with m.Elif(is_down):
m.d.sync += self.output.eq(self.output-1)
return m
s = Stepper()
verilog.convert(s, name='Top', ports=s.ports)