calyx: Error for comparions that are always true/false
Problem
When I wanted to loop only 4 times using 2-bit number representation for loop counts and 2-bit le
operator, I ran into a problem where after checking that the count is 2'b11
, it overflows to 2'b00
on the next iteration, causing the loop to run forever and simulation to run until the maximum number of clock cycle is reached.
Below is a simple example illustrating such problem. Here, I am attempting to simply update the value in dest
with the value stored in register r0
that gets incremented by 1 in each iteration of the loop. When producing the outputs, the maximum number of clock cycles were configured to 500
.
import "primitives/std.lib";
component main() -> () {
cells {
@external(1) dest = std_mem_d1(32, 1, 1);
r0 = std_reg(32);
const11 = std_const(32, 1);
add = std_add(32);
// Problem
// i0 = std_reg(2);
// le = std_le(2);
// add_cnt = std_add(2);
// const0 = std_const(2, 0);
// const1 = std_const(2, 3);
// const2 = std_const(2, 1);
// Resolved by,
i0 = std_reg(3);
le = std_le(3);
add_cnt = std_add(3);
const0 = std_const(3, 0);
const1 = std_const(3, 3);
const2 = std_const(3, 1);
}
wires {
group init {
r0.write_en = 1'd1;
r0.in = 32'd0;
i0.write_en = 1'b1;
i0.in = const0.out;
init[done] = r0.done & i0.done ? 1'd1;
}
group cond {
le.left = i0.out;
le.right = const1.out;
cond[done] = 1'd1;
}
group upd {
dest.write_en = 1'd1;
dest.addr0 = 1'd0;
dest.write_data = r0.out;
upd[done] = dest.done ? 1'd1;
}
group incr {
add.left = r0.out;
add.right = const11.out;
r0.write_en = 1'd1;
r0.in = add.out;
add_cnt.left = i0.out;
add_cnt.right = const2.out;
i0.write_en = 1'd1;
i0.in = add_cnt.out;
incr[done] = r0.done & i0.done ? 1'd1;
}
}
control {
seq {
init;
while le.out with cond {
seq {
upd;
incr;
}
}
}
}
}
Output
Using the 2-bit configurations for primitive components, the output looks like such:
{
"cycles": 500,
"memories": {
"dest": [
81
]
}
}
By increasing the width to 3 to take overflow issues into account, the output becomes more reasonable:
{
"cycles": 35,
"memories": {
"dest": [
3
]
}
}
Thoughts
It seems that the current implementation of different primitives ignores overflow bits?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (9 by maintainers)
A paper cut pass detects common mistakes found when writing a Calyx program. The current pass can be found here.
For example, https://github.com/cucapra/calyx/blob/9b76900d7f0e25df2aa09e55b5e868a02409b2ba/calyx/src/passes/papercut.rs#L19-L21
whenever you write to a
std_reg
, you need to drive thewrite_en(able)
signal. This paper cut pass catches this case, and gives a descriptive compilation error. This makes the user’s life easier, since it is a small bug that is not immediately obvious.Edit: Here’s an example program with the corresponding error message.
Perhaps something similar can be incorporated for simpler cases of overflow as described in your example program.