Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components that do a single read/write to a seq_mem generate circular combinational logic #1963

Open
nathanielnrn opened this issue Mar 9, 2024 · 2 comments
Labels
C: Calyx Extension or change to the Calyx IL Type: Bug Bug in the implementation

Comments

@nathanielnrn
Copy link
Contributor

nathanielnrn commented Mar 9, 2024

The following program, when run through fud with fud e <program> --from calyx --to vcd --through verilog creates a circular combinational logic error (Simulating with icarus-verilog just hangs):

=====STDERR=====
%Warning-UNOPTFLAT: /tmp/tmp_n0qtzxz:1260:7: Signal unoptimizable: Circular combinational logic: 'TOP.main.my_reader_ref_mem_done'
                                           : ... In instance TOP.main
 1260 | logic my_reader_ref_mem_done;
      |       ^~~~~~~~~~~~~~~~~~~~~~
                    ... For warning description see https://verilator.org/warn/UNOPTFLAT?v=5.006
                    ... Use "/* verilator lint_off UNOPTFLAT */" and lint_on around source to disable this message.
                    /tmp/tmp_n0qtzxz:1260:7:      Example path: TOP.main.my_reader_ref_mem_done
                    /tmp/tmp_n0qtzxz:1474:22:      Example path: ASSIGNW
                    /tmp/tmp_n0qtzxz:1294:7:      Example path: TOP.main.invoke1_go_in
                    /tmp/tmp_n0qtzxz:1465:31:      Example path: ASSIGNW
                    /tmp/tmp_n0qtzxz:1260:7:      Example path: TOP.main.my_reader_ref_mem_done
%Warning-UNOPTFLAT: /tmp/tmp_n0qtzxz:1274:7: Signal unoptimizable: Circular combinational logic: 'TOP.main.my_writer_ref_mem_done'
                                           : ... In instance TOP.main
 1274 | logic my_writer_ref_mem_done;
      |       ^~~~~~~~~~~~~~~~~~~~~~
                    /tmp/tmp_n0qtzxz:1274:7:      Example path: TOP.main.my_writer_ref_mem_done
                    /tmp/tmp_n0qtzxz:1471:22:      Example path: ASSIGNW
                    /tmp/tmp_n0qtzxz:1290:7:      Example path: TOP.main.invoke0_go_in
                    /tmp/tmp_n0qtzxz:1456:31:      Example path: ASSIGNW
                    /tmp/tmp_n0qtzxz:1274:7:      Example path: TOP.main.my_writer_ref_mem_done
%Error: Exiting due to 2 warning(s)

=====STDOUT=====

The program in question:

import "primitives/core.futil";
import "primitives/binary_operators.futil";
import "primitives/memories/seq.futil";

component main () -> (){
    cells {
        my_reader = reader();
        my_writer = writer();
        real_mem = seq_mem_d1(32, 2, 1);
    }
    wires{}

    control{
        seq{
            invoke my_writer[ref_mem = real_mem]()();
            invoke my_reader[ref_mem=real_mem]()();
        }
    }
}



component reader () -> () {
    cells {
        ref ref_mem = seq_mem_d1(32, 2, 1);
    }
    wires{
        group read1 {
            ref_mem.content_en = 1'b1;
            ref_mem.addr0 = 1'b0;
            read1[done] = ref_mem.done;
        }
    }
    control{
        read1;
    }
}

component writer () -> () {
    cells {
        ref ref_mem = seq_mem_d1(32, 2, 1);
    }

    wires{
        group write1 {
            ref_mem.content_en = 1'b1;
            ref_mem.write_en  =1'b1;
            ref_mem.write_data = 32'b1;
            ref_mem.addr0 = 1'b0;
            write1[done] = ref_mem.done;
        }
    }

    control{
        write1;
    }
}

This does not happen if the reader and writer components both have another group thats reads/writes to the second address of the seq_mem_d1. i.e the program listed in this comment of #1955.

cc @rachitnigam

@nathanielnrn nathanielnrn added Type: Bug Bug in the implementation C: Calyx Extension or change to the Calyx IL labels Mar 9, 2024
@rachitnigam
Copy link
Contributor

@nathanielnrn, can you try dumping out the version of the program from lowering fud e --to calyx-lowered ... and without optimizations fud e -s calyx.flags ' -p no-opt' ... and see if the error persists. For the former program, you can try reading the final code generated before we emit Verilog and see if there is an obvious problem. Otherwise, we'll have to stare at the Verilog and figure out the problem.

I will not have any debugging cycles so please take a shot and let me know what you learn. I can try to provide async help.

@nathanielnrn nathanielnrn changed the title Components that do a single write/read to a seq_mem generate circular combinational logic Components that do a single write to a seq_mem generate circular combinational logic Mar 10, 2024
@nathanielnrn nathanielnrn changed the title Components that do a single write to a seq_mem generate circular combinational logic Components that do a single read/write to a seq_mem generate circular combinational logic Mar 11, 2024
@nathanielnrn
Copy link
Contributor Author

Just posting some updates as I find them. If we disable optimizations the following program also does not simulate (with optimizations this is fine). It produces an error similar to that in the original issue:

import "primitives/core.futil";
import "primitives/binary_operators.futil";
import "primitives/memories/seq.futil";

component main () -> (){
    cells {
        my_writer = writer();
        real_mem = seq_mem_d1(32, 2, 1);
    }
    wires{}
    control{
        seq{
            invoke my_writer[ref_mem = real_mem]()();
        }
    }
}

component writer () -> () {
    cells {
        ref ref_mem = seq_mem_d1(32, 2, 1);
    }

    wires{
        group write1 {
            write1[done] = ref_mem.done;
        }
    }

    control{
        write1;
    }
}

With the following error

=====STDERR=====
%Warning-UNOPTFLAT: /tmp/tmp78bk0ii7:1263:7: Signal unoptimizable: Circular combinational logic: 'TOP.main.my_writer_ref_mem_done'
                                           : ... In instance TOP.main
 1263 | logic my_writer_ref_mem_done;
      |       ^~~~~~~~~~~~~~~~~~~~~~
                    ... For warning description see https://verilator.org/warn/UNOPTFLAT?v=5.006
                    ... Use "/* verilator lint_off UNOPTFLAT */" and lint_on around source to disable this message.
                    /tmp/tmp78bk0ii7:1263:7:      Example path: TOP.main.my_writer_ref_mem_done
                    /tmp/tmp78bk0ii7:1399:22:      Example path: ASSIGNW
                    /tmp/tmp78bk0ii7:1280:7:      Example path: TOP.main.invoke0_go_in
                    /tmp/tmp78bk0ii7:1393:31:      Example path: ASSIGNW
                    /tmp/tmp78bk0ii7:1263:7:      Example path: TOP.main.my_writer_ref_mem_done
%Error: Exiting due to 1 warning(s)

=====STDOUT=====

However, the same program with the seq{} removed in main does seem to simulate (at least, verilator doesn't throw any combinational loop errors.

control{
     invoke my_writer[ref_mem = real_mem]()();
}

So perhaps something is going wrong in some control sequence pass?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: Calyx Extension or change to the Calyx IL Type: Bug Bug in the implementation
Projects
None yet
Development

No branches or pull requests

2 participants