calyx
calyx copied to clipboard
`comb-prop` pass incorrectly inlines and elides assignment
Hello
When passing this code to calyx -p no-opt -p comb-prop:
import "primitives/core.futil";
comb component alu_bitwise<"toplevel"=1>(op: 2, lhs: 32, rhs: 32, invert_rhs: 1) -> (out: 32) {
cells {
right = std_wire(32);
not_1 = std_not(32);
A = std_and(32);
B = std_or(32);
C = std_xor(32);
}
wires {
not_1.in = rhs;
right.in = !invert_rhs ? rhs;
right.in = invert_rhs ? not_1.out;
A.left = lhs;
B.left = lhs;
C.left = lhs;
A.right = right.out;
B.right = right.out;
C.right = right.out;
out = (op == 2'd0) ? A.out;
out = (op == 2'd1) ? B.out;
out = (op == 2'd2) ? C.out;
}
}
The output is:
...
comb component alu_bitwise<"toplevel"=1>(op: 2, lhs: 32, rhs: 32, invert_rhs: 1) -> (out: 32) {
cells {
right = std_wire(32);
not_1 = std_not(32);
A = std_and(32);
B = std_or(32);
C = std_xor(32);
}
wires {
not_1.in = rhs;
A.left = lhs;
A.right = right.out;
out = op == 2'd0 ? A.out;
out = op == 2'd2 ? C.out;
out = op == 2'd1 ? B.out;
C.left = lhs;
C.right = right.out;
B.left = lhs;
B.right = invert_rhs ? not_1.out;
B.right = !invert_rhs ? rhs;
}
}
The expressions for right.in got inlined for B.right, but C.right and A.right still reference right.out, which now is undriven.
Interestingly, commenting any of A.right, B.right or C.right out avoids this issue, e.g.:
...
//A.right = right.out;
B.right = right.out;
C.right = right.out;
...
gives:
...
wires {
not_1.in = rhs;
A.left = lhs;
out = op == 2'd0 ? A.out;
out = op == 2'd2 ? C.out;
out = op == 2'd1 ? B.out;
C.left = lhs;
C.right = right.out;
B.left = lhs;
B.right = right.out;
right.in = invert_rhs ? not_1.out;
right.in = !invert_rhs ? rhs;
}
...
Calyx version: compiled from source, commit e44fbd7b8bfbef02bea32d08facc05c433cd9bb3.