1
0
mirror of https://github.com/myhdl/myhdl.git synced 2025-01-24 21:52:56 +08:00

Binops convert in VHDL fix (#404)

* Add tests that shows failing case, in VHDL. When many unsigned, single bit signals are BinOped together (Or'ed in this case) to a boolean (std_logic). Verilog works

* Remove clk from design where it is not used

* Update tests to find more corner cases

* Add dest to rhs signal to allow the destination signal to be rippled along the chain if there are multiple elements/signals being assigned
This commit is contained in:
Dave Keeshan 2023-01-19 16:42:54 +00:00 committed by GitHub
parent 7c6a5fda54
commit 0c38f9441b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 465 additions and 3 deletions

View File

@ -881,14 +881,25 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(suf)
def BitOp(self, node):
pre, suf = self.inferCast(node.vhd, node.vhdOri)
self.write(pre)
lpre = lsuf = ""
rpre = rsuf = ""
if hasattr(node, 'dest'):
node.left.dest = node.dest
node.right.dest = node.dest
if isinstance(node.left, ast.Name):
lpre, lsuf = self.inferCast(node.dest.vhd, node.left.vhd)
if isinstance(node.right, ast.Name):
rpre, rsuf = self.inferCast(node.dest.vhd, node.right.vhd)
self.write("(")
self.write(lpre)
self.visit(node.left)
self.write(lsuf)
self.write(" %s " % opmap[type(node.op)])
self.write(rpre)
self.visit(node.right)
self.write(rsuf)
self.write(")")
self.write(suf)
def visit_BoolOp(self, node):
if isinstance(node.vhd, vhd_std_logic):
@ -1031,6 +1042,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(lhs)
self.isLhs = False
if self.SigAss:
rhs.dest = lhs.value
if isinstance(lhs.value, ast.Name):
sig = self.tree.symdict[lhs.value.id]
self.write(' <= ')

View File

@ -0,0 +1,450 @@
from myhdl import *
@block
def binOpsCheck0(
a,
b,
c,
x,
y,
z,
):
@always_comb
def outputs():
x.next = a
y.next = a | b
z.next = a | b | c
return instances()
@block
def binOpsCheck1(
a,
x,
y,
z,
):
@always_comb
def outputs():
x.next = a[0]
y.next = a[0] | a[1]
z.next = a[0] | a[1] | a[2]
return instances()
@block
def binOpsCheck2(
a,
z,
):
@always_comb
def outputs():
z[0].next = a[0]
z[1].next = a[0] | a[1]
z[2].next = a[0] | a[1] | a[2]
return instances()
@block
def binOpsCheckBench0():
clk = Signal(bool(0))
a = Signal(modbv(0)[1:])
b = Signal(modbv(0)[1:])
c = Signal(modbv(0)[1:])
x = Signal(modbv(0)[1:])
y = Signal(modbv(0)[1:])
z = Signal(modbv(0)[1:])
@instance
def clkgen():
clk.next = 1
for i in range(400):
yield delay(10)
clk.next = not clk
@instance
def stimulus():
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
raise StopSimulation
@instance
def check():
yield clk.posedge
yield clk.posedge
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
i_binOpsCheck = binOpsCheck0(a, b, c, x, y, z)
return instances()
@block
def binOpsCheckBench1():
clk = Signal(bool(0))
a = Signal(modbv(0)[1:])
b = Signal(modbv(0)[1:])
c = Signal(modbv(0)[1:])
x = Signal(False)
y = Signal(False)
z = Signal(False)
@instance
def clkgen():
clk.next = 1
for i in range(400):
yield delay(10)
clk.next = not clk
@instance
def stimulus():
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
raise StopSimulation
@instance
def check():
yield clk.posedge
yield clk.posedge
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
i_binOpsCheck = binOpsCheck0(a, b, c, x, y, z)
return instances()
@block
def binOpsCheckBench2():
clk = Signal(bool(0))
a = Signal(modbv(0)[2:])
b = Signal(modbv(0)[2:])
c = Signal(modbv(0)[2:])
x = Signal(modbv(0)[2:])
y = Signal(modbv(0)[2:])
z = Signal(modbv(0)[2:])
@instance
def clkgen():
clk.next = 1
for i in range(400):
yield delay(10)
clk.next = not clk
@instance
def stimulus():
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x1
b.next = 0x0
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x1
c.next = 0x0
yield clk.posedge
a.next = 0x1
b.next = 0x1
c.next = 0x1
yield clk.posedge
a.next = 0x0
b.next = 0x0
c.next = 0x0
yield clk.posedge
raise StopSimulation
@instance
def check():
yield clk.posedge
yield clk.posedge
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x1
assert y == 0x1
assert z == 0x1
yield clk.posedge
assert x == 0x0
assert y == 0x0
assert z == 0x0
yield clk.posedge
i_binOpsCheck = binOpsCheck0(a, b, c, x, y, z)
return instances()
def test_binOps0():
sim = binOpsCheckBench0()
sim.run_sim()
def test_binOps0_convert():
i_dut = binOpsCheckBench0()
assert i_dut.analyze_convert() == 0
#assert i_dut.verify_simulator() == 0
#assert i_dut.verify_convert() == 0
def test_binOps1():
sim = binOpsCheckBench1()
sim.run_sim()
def test_binOps1_convert():
i_dut = binOpsCheckBench1()
assert i_dut.analyze_convert() == 0
#assert i_dut.verify_simulator() == 0
def test_binOps1b_convert():
a = Signal(modbv(0)[1:])
b = Signal(modbv(0)[1:])
c = Signal(modbv(0)[1:])
x = Signal(False)
y = Signal(False)
z = Signal(False)
i_dut = binOpsCheck0(a, b, c, x, y, z)
assert i_dut.analyze_convert() == 0
def test_binOps1c_convert():
a = Signal(intbv(0)[1:])
b = Signal(intbv(0)[1:])
c = Signal(intbv(0)[1:])
x = Signal(False)
y = Signal(False)
z = Signal(False)
i_dut = binOpsCheck0(a, b, c, x, y, z)
assert i_dut.analyze_convert() == 0
def test_binOps1d_convert():
a = Signal(intbv(0)[3:])
x = Signal(False)
y = Signal(False)
z = Signal(False)
i_dut = binOpsCheck1(a, x, y, z)
assert i_dut.analyze_convert() == 0
def test_binOps1e_convert():
a = Signal(intbv(0)[3:])
z = Signal(intbv(0)[3:])
i_dut = binOpsCheck2(a, z)
assert i_dut.analyze_convert() == 0
def test_binOps2():
sim = binOpsCheckBench2()
sim.run_sim()
def test_binOps2_convert():
i_dut = binOpsCheckBench2()
assert i_dut.analyze_convert() == 0
#assert i_dut.verify_convert() == 0
#assert i_dut.verify_simulator() == 0