fabianschuiki / moore

A hardware compiler based on LLHD and CIRCT
http://www.llhd.io
Apache License 2.0
243 stars 31 forks source link

Non-constant case item not supported #227

Open zyedidia opened 3 years ago

zyedidia commented 3 years ago

It seems like moore requires that case items evaluate to integer constants even though this is more restrictive than the SystemVerilog standard. For example, this code should be valid SystemVerilog:

module test
    (
        input logic current_state,
        output logic [2:0] get_ready, get_set, get_going
    );

    always_comb begin
        {get_ready, get_set, get_going} = 3'b000;
        unique case (1'b1)
            current_state[0]: get_ready = '1;
            current_state[1]: get_set   = '1;
            current_state[2]: get_going = '1;
        endcase
    end
endmodule

But moore reports an error:

error: value is not constant
  --> test.sv:16:13-26:
   | 
   |             current_state[0]: get_ready = '1;
   |             ^^^^^^^^^^^^^                    

thread 'main' panicked at 'case constant evaluates to non-integer', /home/zyedidia/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/macros.rs:13:23
fabianschuiki commented 3 years ago

Thanks @zyedidia for reporting this issue. This is indeed something that should work, and off the top of my head I don't think there is anything technical that prevents having non-constants in this case statement.

The relevant code is here: https://github.com/fabianschuiki/moore/blob/eb4d44cf0da15617b312ada81bd8f5da844f720b/src/svlog/codegen.rs#L2278-L2301 It looks like the only thing that requires a bit of care are casex/casez, where the code generation currently wants a constant value to check for X and Z bits. This is due to the current lack of support for four-/nine-valued logic in LLHD (it's planned, but not implemented yet) -- so the codegen tries to do this ahead of time for the common case of casex/casez.

The above code could instead first check if the value is a constant (there's a compiler query for that), and if yes perform the whole masking/matching magic, and otherwise just use the non-constant value for the comparison.