More fixes in ast expression sign/width handling
authorClifford Wolf <clifford@clifford.at>
Tue, 9 Jul 2013 21:41:28 +0000 (23:41 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 9 Jul 2013 21:41:43 +0000 (23:41 +0200)
frontends/ast/genrtlil.cc
tests/simple/vloghammer.v

index 39f6e90eff8be0f4a286ff2632115e08fc48a8a8..830778227a14c5e43948910ff8826c0fe18193de 100644 (file)
@@ -530,7 +530,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
                break;
 
        case AST_TO_UNSIGNED:
-               children.at(0)->detectSignWidthWorker(width_hint, sign_hint);
+               children.at(0)->detectSignWidthWorker(width_hint, dummy_sign_hint);
                sign_hint = false;
                break;
 
@@ -593,8 +593,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
        case AST_LOGIC_AND:
        case AST_LOGIC_OR:
        case AST_LOGIC_NOT:
-               for (auto child : children)
-                       child->detectSignWidthWorker(width_hint, sign_hint);
+               width_hint = std::max(width_hint, 1);
+               sign_hint = false;
                break;
 
        case AST_TERNARY:
@@ -835,7 +835,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        // just pass thru the signal. the parent will evaluated the is_signed property and inperpret the SigSpec accordingly
        case AST_TO_SIGNED:
        case AST_TO_UNSIGNED: {
-                       RTLIL::SigSpec sig = children[0]->genRTLIL(width_hint, sign_hint);
+                       RTLIL::SigSpec sig = children[0]->genRTLIL();
                        is_signed = type == AST_TO_SIGNED;
                        return sig;
        }
@@ -889,6 +889,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        if (0) { case AST_BIT_XOR:  type_name = "$xor"; }
        if (0) { case AST_BIT_XNOR: type_name = "$xnor"; }
                {
+                       if (width_hint < 0)
+                               detectSignWidth(width_hint, sign_hint);
                        RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
                        RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
                        int width = std::max(left.width, right.width);
@@ -965,12 +967,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        if (width > width_hint && width_hint > 0)
                                width = width_hint;
                        if (width < width_hint) {
-                               if (type == AST_ADD || type == AST_SUB) {
+                               if (type == AST_ADD || type == AST_SUB)
                                        width++;
-                                       if (width < width_hint && children[0]->is_signed != children[1]->is_signed)
-                                               width++;
-                               }
-                               if (type == AST_SUB && !children[0]->is_signed && !children[1]->is_signed)
+                               if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
                                        width = width_hint;
                                if (type == AST_MUL)
                                        width = std::min(left.width + right.width, width_hint);
index 9269ff0505f272312bfdca16fd7fca4cb0ee8a41..09987e7c93c9d2bfff1cb709b455959afe408f86 100644 (file)
@@ -27,19 +27,21 @@ module test04(a, y);
   assign y = ~(a - 1'b0);
 endmodule
 
-module test05(a, y);
-  input a;
-  output y;
-  assign y = 12345 >> {a, 32'd0};
-endmodule
-
-module test06(a, b, c, y);
-  input signed [3:0] a;
-  input signed [1:0] b;
-  input signed [1:0] c;
-  output [5:0] y;
-  assign y = (a >> b) >>> c;
-endmodule
+// .. this test triggers a bug in xilinx isim.
+// module test05(a, y);
+//   input a;
+//   output y;
+//   assign y = 12345 >> {a, 32'd0};
+// endmodule
+
+// .. this test triggers a bug in icarus verilog.
+// module test06(a, b, c, y);
+//   input signed [3:0] a;
+//   input signed [1:0] b;
+//   input signed [1:0] c;
+//   output [5:0] y;
+//   assign y = (a >> b) >>> c;
+// endmodule
 
 module test07(a, b, y);
   input signed [1:0] a;