migen
migen copied to clipboard
Python logical operator 'and' silently dropped
The following migen snippet:
If((self.addr == 0x18a) and (self.joy_enabled == 1),
produces the following Verilog:
if ((addr_1 == 9'd394)) begin
Yes, you cannot use and - it cannot be redefined in Python.
Is there any way to make it a hard error?
Actually it should raise TypeError("Attempted to convert Migen value to boolean") (see fhdl/structure.py). Can you find out why that does not happen?
@sbourdeauducq Because of the special case in __bool__:
# Special case: Constants and Signals are part of a set or used as
# dictionary keys, and Python needs to check for equality.
if isinstance(self, _Operator) and self.op == "==":
a, b = self.operands
if isinstance(a, Constant) and isinstance(b, Constant):
return a.value == b.value
if isinstance(a, Signal) and isinstance(b, Signal):
return a is b
if (isinstance(a, Constant) and isinstance(b, Signal)
or isinstance(a, Signal) and isinstance(b, Constant)):
return False
I don't understand why it lives in __bool__ though.
Where should it be instead?
@sbourdeauducq Is it realistic to make only Signal and Constant hashable in the first place? AFAICT Migen does not rely on other values being hashable, but I might be wrong.
Maybe, can you test it (including with ARTIQ)?
OK
I also just ran into this problem:
class OrderTest(Module):
def __init__(self):
counter = Signal(8)
sig = Signal()
self.sync += [
counter.eq(counter + 1),
If((counter == 1) or (counter == 2) or (counter == 3),
sig.eq(1)
)
]
print(str(verilog.convert(OrderTest())))
This results in:
...
if ((counter == 2'd3)) begin
sig <= 1'd1;
end
...
FYI this (and many other issues) are fixed in https://github.com/m-labs/nmigen/. But nMigen is not yet quite ready.
Triage: fixed in nMigen.
@sbourdeauducq @whitequark What is the correct way of doing logical AND or logical OR in Migen then? and_(a, b)? I couldn't find any example with something similar to _Operator("and", [a, b]) or _Operator("||", [a, b]) in the repository.
(x == 2) & (y > 9)
It does. For one bit expressions they are the same.
In nMigen you can use x.bool() & y.bool() to get an equivalent of the logical AND that works regardless of the width of x and y.
Thanks for your answers! Is there a bool() equivalent in Migen or should we use something like reduce(or_, a)?
a != 0