Using always_comb with an instance that reads signals from a class does not work (not even in simulation) because those signals do not get included in the sensitivity list. The proposed patch below fixes this problem for the simulation.
Example/test code:
https://github.com/sbourdeauducq/TokenEngine/blob/master/myhdl-limits/slclass.py
Correct result:
Setting object signal to False
Value outside object: False
Setting object signal to True
Value outside object: True
Incorrect result (currently what MyHDL does without the patch):
Setting object signal to False
Value outside object: False
Setting object signal to True
Value outside object: False
^^^^^
diff -r e18493b5f0ad myhdl/_always_comb.py
--- a/myhdl/_always_comb.py Fri May 20 21:07:24 2011 +0200
+++ b/myhdl/_always_comb.py Mon Sep 12 17:06:06 2011 +0200
@@ -76,6 +75,7 @@
self.toplevel = 1
self.symdict = symdict
self.context = INPUT
+ self.attrs = []
def visit_Module(self, node):
inputs = self.inputs
@@ -106,15 +106,27 @@
if id not in self.symdict:
return
s = self.symdict[id]
- if isinstance(s, _Signal) or _isListOfSigs(s):
- if self.context == INPUT:
- self.inputs.add(id)
- elif self.context == OUTPUT:
- self.outputs.add(id)
- elif self.context == INOUT:
- raise AlwaysCombError(_error.SignalAsInout % id)
- else:
- raise AssertionError("bug in always_comb")
+ ia = iter(self.attrs)
+ while True:
+ if isinstance(s, _Signal) or _isListOfSigs(s):
+ if self.context == INPUT:
+ self.inputs.add(id)
+ self.symdict[id] = s
+ break
+ elif self.context == OUTPUT:
+ self.outputs.add(id)
+ self.symdict[id] = s
+ break
+ elif self.context == INOUT:
+ raise AlwaysCombError(_error.SignalAsInout % id)
+ else:
+ raise AssertionError("bug in always_comb")
+ try:
+ a = ia.next()
+ except StopIteration:
+ break
+ id += "." + a
+ s = getattr(s, a)
def visit_Assign(self, node):
self.context = OUTPUT
@@ -124,7 +136,9 @@
self.visit(node.value)
def visit_Attribute(self, node):
+ self.attrs.insert(0, node.attr)
self.visit(node.value)
+ self.attrs.pop(0)
def visit_Subscript(self, node, access=INPUT):
self.visit(node.value)
|