-
Notifications
You must be signed in to change notification settings - Fork 585
-
Notifications
You must be signed in to change notification settings - Fork 585
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
False Signal unoptimizable: circular logic warning #63
Comments
Original Redmine Comment Similar UNOPTFLAT woes are also discussed in http://www.veripool.org/boards/2/topics/show/373-UNOPTFLAT-Error |
Original Redmine Comment Also ran into this problem. I can contribute a very simple reproduction case (attached). |
Is this issue still valid? If yes, can you post the mentioned attached file of the post here? |
#2066 is an in-flight workaround for these sort of issues. |
Will these patches also fix UNOPTFLAT warnings related to packed structs? In the meanwhile, is it safe to just use /* verilator lint_off UNOPTFLAT */ ? |
Yes & yes. UNOPTFLAT is only performance; see the manual. |
I have reproduce the problem with a Dlatch at gate_level. then for demonstrate i have writed 2x the code with only change example 1 (no crash) module Dlatch (a, clk, reset, s1, s2);
input a, clk, reset;
output s1, s2;
wire line0;
wire line1;
wire line2;
wire line3;
/* verilator lint_off UNOPTFLAT */
wire line4;
wire line5;
wire line6;
wire line7;
gate_xor xor1(a, reset, line5);
gate_and and1(a, line5, line6);
gate_nand nand1(line6, clk, line0);
gate_not not1(line6, line1);
gate_nand nand2(line1, clk, line2);
gate_nand nand3(line0, line7, line3);
gate_nand nand4(line2, line3, line4);
gate_or or1(reset, line4, line7);
gate_buf buf1(line3, s1);
gate_buf buf2(line4, s2);
endmodule example 2 (crash) module Dlatch (a, clk, reset, s1, s2);
input a, clk, reset;
/* verilator lint_off UNOPTFLAT */
wire [7:0] line;
output s1, s2;
gate_xor xor1(a, reset, line[5]);
gate_and and1(a, line[5], line[6]);
gate_nand nand1(line[6], clk, line[0]);
gate_not not1(line[6], line[1]);
gate_nand nand2(line[1], clk, line[2]);
gate_nand nand3(line[0], line[7], line[3]);
gate_nand nand4(line[2], line[3], line[4]);
gate_or or1(reset, line[4], line[7]);
gate_buf buf1(line[3], s1);
gate_buf buf2(line[4], s2);
endmodule the message of crash
|
Thanks for tracking this down. Strictly speaking DIDNOTCONVERGE is an error not a crash. You might get around this by de-vectorizing "line", but then you'll likely find incorrect results. Verilator doesn't support making latches out of individual primitives using Verilator, you must use a behavioral latch construct. I will update the documentation to mention this. |
Thanks for your response, if you indicate me where i can start my analyze for implementing primitive support maybe can i make an pull request for adding this (essential) functionalities. |
Primitives are supported, UDPs are not (yet), the problem is the loop between primitives or UDPs. We need to first get the event model working, then this will be fairly easy. If you'd like to help with UDPs or event, or other issues that would certainly be welcome. |
We're getting burned by this pretty badly now in CIRCT. Specifically, we're working towards emitting Verilog from Chisel which preserves the structure of aggregate types described in Chisel. This is intended to be available for any front-end language that uses CIRCT infra, e.g., PyCDE or Calyx. We have our own bit-level combinational loop detection implemented so we are extremely confident that we don't have combinational cycles. However, there is a lot of concern about globally disabling UNOPTFLAT. Is there any possibility of improvements to Verilator that will do the bit-level analysis to avoid the UNOPTFLAT warnings here and/or automatically split variables when necessary? An example of something showing this: Chisel SourceContents of //> using scala "2.13.10"
//> using lib "edu.berkeley.cs::chisel3::3.6.0-M2"
//> using plugin "edu.berkeley.cs:::chisel3-plugin::3.6.0-M2"
import chisel3._
import circt.stage.ChiselStage
class Foo extends RawModule {
val a = IO(Input(Bool()))
val b = IO(Output(Bool()))
val w = Wire(Vec(2, Bool()))
dontTouch(w)
w(0) := a
w(1) := w(0)
b := w(1)
}
object Main extends App {
println(
ChiselStage.emitSystemVerilog(
new Foo,
Array(),
Array("-preserve-aggregate=1d-vec", "-strip-debug-info")
)
)
} For the curious, you can run this if you install Scala CLI and run:
We're producing Verilog like the following: module Foo(
input a,
output b);
wire [1:0] w;
assign w = {{w[1'h0]}, {a}};
assign b = w[1'h1];
endmodule We are reluctant to investigate options that involve E.g., the following errors, but can be escaped with module Foo(
input a,
output b);
wire [1:0] w;
assign w[0] = a;
assign w[1] = w[0];
assign b = w[1];
endmodule E.g., the following (which is what we produce now with an added module Foo(
input a,
output b);
wire [1:0] w /*verilator split_var*/;
assign w = {{w[1'h0]}, {a}};
assign b = w[1'h1];
endmodule |
Chisel should be able to use
and verilator will bitblast that signal and so you won't get UNOPTFLAT. Don't use that where you don't need it or the signal count would explode. |
🤔 We tried module Foo(
input a,
output b);
wire [1:0] w /*verilator split_var*/;
assign w = {{w[1'h0]}, {a}};
assign b = w[1'h1];
endmodule This is still throwing the UNOPTFLAT warning:
Is this supposed to work? |
Our main concern with selective application of the module Foo(
input a,
output b);
wire [1:0] w /*verilator split_var*/;
assign w[0] = a;
assign w[1] = w[0];
assign b = w[1];
endmodule
|
The split_var isn't operating because it sees the single assignment and doesn't see any point, that's probably generally the right decision but not here. Splitting the assigns fixes that problem. We could improve split_var but that doesn't seem to solve your larger problem. Even adding bit-by-bit unopt flat processing would still result in the statement executing multiple times - that is what event based simulators are doing too. I don't have any good recommendations beyond not creating code like this. |
Author Name: Lane Brooks
Original Redmine Issue: 63 from https://www.veripool.org
Original Date: 2009-01-30
See attached test case showing the problem. This example shows how bit 0 of a bus is used to generate bit 1 of the same bus. Verilator is falsly detecting this as circular logic. Also shown in this test case is that this example works if the signals are not part of a bus (the `ifdef T_WORKS section).
The text was updated successfully, but these errors were encountered: