Closed calebmkim closed 1 year ago
What’s the error message?
The invoke to the register must be compiler into a group since primitive invoked cannot be compiled. I’d recommend disabling group2invoke
sounds good that's what I've been doing. (Also, I've updated the original issue comment to include the error message)
Run with backtrace to see the stack trace
The error is happening in the rewrite_invoke()
function. Specifically, it occurs when we are going through the inputs of the invoke
and we are trying to get the parent name of one of the input ports, that's when it looks like the error is happening.
Can you try looking to which port is the problem? One option is to use VS Code's debugger to step through the program. You can use the "Debug Compiler" option to provide the arguments and the file and step through the program to see where the bug is coming from
The invoke to the register must be compiler into a group since primitive invoked cannot be compiled. I’d recommend disabling group2invoke
Also, to be clear, this is problem with how -x inline:always
works and interacts with group2invoke
. We should expose some option like -x group2invoke:skip-primitives
to ensure that it doesn't turn primitive groups to invokes so that always inlining works correctly
Just tacking on an additional probably-wrong thought, just in case: instead of telling group2invoke
not to deal with primitives, would an alternative be to tell the inline:always
mode to not actually attempt to inline primitives?
Ok, I think I may have a guess for what's going on?
component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
cells {
c = some_user_defined_comp();
r = std_reg(32);
}
wires {
}
control {
seq {
invoke r(in = c.out)();
}
}
}
The error is happening when we are at the invoke r(in = c.out)()
. Specifically, when re come across in = c.out
, we try to get_parent_name()
on the port c.out
. But (I think) since we've already inlined the component c
, the parent cell for the port c.out
is pointing to nothing?
However, if we replace r
to be a user defined component (not a primitive) the program compiles fine; I think because when we actually inline this user defined component, the pass works fine. It just behaves weirdly when we can't inline it (which the register case falls under).
The version of the program with only components doesn't error out:
import "primitives/core.futil";
component foo() -> (out: 32) {
cells {}
wires {}
control {}
}
component bar(in: 32) -> (out: 32) {
cells {}
wires {}
control {}
}
component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
cells {
c = foo();
b = bar();
}
wires {
}
control {
seq {
invoke b(in = c.out)();
}
}
}
I looked at the error and it seems to occur during the final program printing and not the pass itself. This means that the likely problem is that the inlining pass is not rewriting the assignment at all and when the pretty printer attempt to print c.out
, it realizes that c
is no longer defined
Always inlining gives an error in the following Calyx design (this is coming up in the neural network designs, but this is just the minimal case of it):
l.futil.txt
The error is:
Basically, there is a component,
fp_pow
, which itself contains an invoke of a register. That component is read from in the main, which is giving an error when I try to fully inline. I've been trying to figure out what's wrong w/ it but if anyone else that understands thecomponent-inliner
pass better could give their input that would help.