ast: fixes #1710; do not generate RTLIL for unreachable ternary
authorEddie Hung <eddie@fpgeh.com>
Fri, 28 Feb 2020 00:55:55 +0000 (16:55 -0800)
committerEddie Hung <eddie@fpgeh.com>
Fri, 28 Feb 2020 00:55:55 +0000 (16:55 -0800)
frontends/ast/genrtlil.cc
tests/various/bug1710.ys [new file with mode: 0644]

index 3fb6b3e5cb7571fa1438c2914ecd546a137127eb..1dfcf3e0e584d1a9df021eb8975265ff80745b6e 100644 (file)
@@ -1338,18 +1338,31 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                detectSignWidth(width_hint, sign_hint);
 
                        RTLIL::SigSpec cond = children[0]->genRTLIL();
-                       RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
-                       RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
+                       RTLIL::SigSpec sig;
+                       if (cond.is_fully_const()) {
+                               if (cond.as_bool()) {
+                                       sig = children[1]->genRTLIL(width_hint, sign_hint);
+                                       widthExtend(this, sig, sig.size(), children[1]->is_signed);
+                               }
+                               else {
+                                       sig = children[2]->genRTLIL(width_hint, sign_hint);
+                                       widthExtend(this, sig, sig.size(), children[2]->is_signed);
+                               }
+                       }
+                       else {
+                               RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
+                               RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
 
-                       if (cond.size() > 1)
-                               cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
+                               if (cond.size() > 1)
+                                       cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
 
-                       int width = max(val1.size(), val2.size());
-                       is_signed = children[1]->is_signed && children[2]->is_signed;
-                       widthExtend(this, val1, width, is_signed);
-                       widthExtend(this, val2, width, is_signed);
+                               int width = max(val1.size(), val2.size());
+                               is_signed = children[1]->is_signed && children[2]->is_signed;
+                               widthExtend(this, val1, width, is_signed);
+                               widthExtend(this, val2, width, is_signed);
 
-                       RTLIL::SigSpec sig = mux2rtlil(this, cond, val1, val2);
+                               sig = mux2rtlil(this, cond, val1, val2);
+                       }
 
                        if (sig.size() < width_hint)
                                sig.extend_u0(width_hint, sign_hint);
diff --git a/tests/various/bug1710.ys b/tests/various/bug1710.ys
new file mode 100644 (file)
index 0000000..c2ecf3c
--- /dev/null
@@ -0,0 +1,30 @@
+logger -werror "out of bounds"
+read_verilog <<EOT
+module Example;
+
+    parameter FLAG = 1;
+    wire [3:0] inp;
+
+    reg out1;
+    initial out1 = FLAG ? &inp[2:0] : &inp[4:0];
+
+    reg out2;
+    initial
+        if (FLAG)
+            out2 = &inp[2:0];
+        else
+            out2 = &inp[4:0];
+
+    wire out3;
+    assign out3 = FLAG ? &inp[2:0] : &inp[4:0];
+
+    wire out4;
+    generate
+        if (FLAG)
+            assign out4 = &inp[2:0];
+        else
+            assign out4 = &inp[4:0];
+    endgenerate
+
+endmodule
+EOT