AssertionError: Unexpected callable

I get an AssertionError: Unexpected callable when I try converting my project. I’ve never seen this before that I recall and it does not provide any indication what might be the problem. Can any of you help?

from myhdl import *
from comparator import comparator

@block
def channel(reset, clock, data, count, enable, load_rising, load_falling, output):

	rising_edge = Signal(False)
	falling_edge = Signal(False)
	output = Signal(False)

	@always_seq(clock.posedge, reset=reset)
	def logic():
		rising_comparator = comparator(reset, clock, clear=False, load=load_rising, register_input=data, match_input=count, match=rising_edge)
		falling_comparator = comparator(reset, clock, clear=False, load=load_falling, register_input=data, match_input=count, match=falling_edge)
		if rising_edge and enable:
			output.next = True
		elif falling_edge:
			output.next = False
	return logic

WIDTH = 32
PERIOD = 20

def convert(hdl='Verilog'):

	clock = Signal(False)
	reset = ResetSignal(False, active=True, isasync=True)
	load_rising = Signal(False)
	load_falling = Signal(False)
	enable = Signal(False)
	output = Signal(False)

	data = Signal(intbv(0)[WIDTH:0])
	count = Signal(intbv(0)[WIDTH:0])

	inst = channel(reset, clock, data, count, enable, load_rising, load_falling, output)
	inst.convert(hdl=hdl)


if __name__ == '__main__':
	convert()

(.venv) C:\project\source\pulser>py channel.py
Traceback (most recent call last):
  File "channel.py", line 135, in <module>
	convert()
  File "channel.py", line 130, in convert
	inst.convert(hdl=hdl)
  File "C:\project\.venv\lib\site-packages\myhdl\_block.py", line 342, in convert
	return converter(self)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_toVerilog.py", line 177, in __call__
	genlist = _analyzeGens(arglist, h.absnames)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_analyze.py", line 170, in _analyzeGens
	v.visit(tree)
  File "C:\python_v3.8.5\lib\ast.py", line 363, in visit
	return visitor(node)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_analyze.py", line 1070, in visit_Module
	self.generic_visit(node)
  File "C:\python_v3.8.5\lib\ast.py", line 371, in generic_visit
	self.visit(item)
  File "C:\python_v3.8.5\lib\ast.py", line 363, in visit
	return visitor(node)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_analyze.py", line 1141, in visit_FunctionDef
	self.visit(n)
  File "C:\python_v3.8.5\lib\ast.py", line 363, in visit
	return visitor(node)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_analyze.py", line 528, in visit_Assign
	self.visit(value)
  File "C:\python_v3.8.5\lib\ast.py", line 363, in visit
	return visitor(node)
  File "C:\project\.venv\lib\site-packages\myhdl\conversion\_analyze.py", line 656, in visit_Call
	raise AssertionError("Unexpected callable %s" % str(debug_info))
AssertionError: Unexpected callable [('id', 'comparator'), ('ctx', <_ast.Load object at 0x000001C6CCA75280>)]

I am afraid that the answer lies in comparator.py?

How did you derive at that? You must be better at parsing the traceback than I am. :slight_smile: Incidentally, the comparator code converts and functions correctly standalone.

# comparator.py

from myhdl import *


@block
def comparator(reset, clock, clear, load, register_input, match_input, match, WIDTH=32):

	register = Signal(intbv(0)[WIDTH:0])

	@always_comb
	def compare_logic():
		match.next = register == match_input

	@always_seq(clock.posedge, reset=reset)
	def compare_register():
		if clear:
			register.next = 0
		elif load:
			register.next = register_input

	return instances()

The last trace line mentions comparator so I assumed there may have been a problem there.
The first trace line says that the error shows up when processing line 135 of your source file. I now assume the error lies inside your top-level module. But your snippet is a lot shorter …

The following lines must be moved outside the logic process .

		rising_comparator = comparator(reset, clock, clear=False, load=load_rising, register_input=data, match_input=count, match=rising_edge)
		falling_comparator = comparator(reset, clock, clear=False, load=load_falling, register_input=data, match_input=count, match=falling_edge)

You’ll also have to add rising_comparator and falling_comparator to the return list.

Thanks to both of you for your kind and expert help. I moved the comparators out of the logic block and added them to the return list and it is now converting!

Oops, I should have seen that … I must be getting old :slight_smile:

It took me some time to find the error. I’m a little less old :wink: