google / xls

XLS: Accelerated HW Synthesis
http://google.github.io/xls/
Apache License 2.0
1.21k stars 179 forks source link

unroll_for does not unroll constants #1721

Open mikex-oss opened 6 days ago

mikex-oss commented 6 days ago

Describe the bug Constants can not be declared in unroll_for loops, even though they work with let binding or used inline.

TypeMissingError: node: 0x30d27fe5f6c0 user: 0x30d27e4e4d98 internal error: AST node is missing a corresponding type: B 0x30d27fe5f6c0 (kind: NameDef) defined @ foo.x10:15-10:16. This may be due to recursion, which is not supported.

To Reproduce

fn main() -> bool {
    unroll_for! (i, b): (u32, bool) in u32:0..u32:10 {
        const B: bool = i == u32:1;
        b ^ B
    }(true)
}

The following work:

fn main() -> bool {
    unroll_for! (i, b): (u32, bool) in u32:0..u32:10 {
        let B: bool = i == u32:1;
        b ^ B
    }(true)
}
fn main() -> bool {
    unroll_for! (i, b): (u32, bool) in u32:0..u32:10 {
        b ^ (i == u32:1)
    }(true)
}

Expected behavior Since the loop index is constexpr, it seems reasonable to define a const that depends on it. I would expect it to work like variables.

Additional context Above is for minimal repro, but a more realistic example would be where B is defined for multiple parametric function invocations.

fn foo<B: bool>(x: u32) -> u32 { if B { x } else { u32:0 } }

fn bar<B: bool>(x: u32) -> bool { if B { x != u32:0 } else { x != u32:1 } }

fn main(x: u32) {
    unroll_for! (i, _): (u32, ()) in u32:0..u32:10 {
        const B = (i % u32:2 == u32:1);
        foo<B>(x);
        bar<B>(x);
    }(());
}