kernel: require \B_SIGNED=0 on $shl, $sshl, $shr, $sshr.
authorwhitequark <whitequark@whitequark.org>
Wed, 4 Dec 2019 11:59:36 +0000 (11:59 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 4 Dec 2019 11:59:36 +0000 (11:59 +0000)
Before this commit, these cells would accept any \B_SIGNED and in
case of \B_SIGNED=1, would still treat the \B input as unsigned.

Also fix the Verilog frontend to never emit such constructs.

frontends/verilog/verilog_parser.y
kernel/rtlil.cc

index daea3b43ab99f27cc4c014a7437edb881be438d6..a30935e0a3d2a0312edb9478bf61c39eb689b79a 100644 (file)
@@ -2242,7 +2242,7 @@ gen_stmt:
                ast_stack.back()->children.push_back(node);
                ast_stack.push_back(node);
        } opt_arg_list ';'{
-               ast_stack.pop_back();           
+               ast_stack.pop_back();
        };
 
 gen_stmt_block:
@@ -2413,19 +2413,19 @@ basic_expr:
                append_attr($$, $2);
        } |
        basic_expr OP_SHL attr basic_expr {
-               $$ = new AstNode(AST_SHIFT_LEFT, $1, $4);
+               $$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
                append_attr($$, $3);
        } |
        basic_expr OP_SHR attr basic_expr {
-               $$ = new AstNode(AST_SHIFT_RIGHT, $1, $4);
+               $$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
                append_attr($$, $3);
        } |
        basic_expr OP_SSHL attr basic_expr {
-               $$ = new AstNode(AST_SHIFT_SLEFT, $1, $4);
+               $$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
                append_attr($$, $3);
        } |
        basic_expr OP_SSHR attr basic_expr {
-               $$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4);
+               $$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
                append_attr($$, $3);
        } |
        basic_expr '<' attr basic_expr {
index bd2fd91a300c9e8609f56e0e37bd2c1711b681dc..7c73f94c8a141d8bba33d37c9e5d01a89543d388 100644 (file)
@@ -783,6 +783,14 @@ namespace {
                        return v;
                }
 
+               int param_bool(RTLIL::IdString name, bool expected)
+               {
+                       int v = param_bool(name);
+                       if (v != expected)
+                               error(__LINE__);
+                       return v;
+               }
+
                void param_bits(RTLIL::IdString name, int width)
                {
                        param(name);
@@ -869,13 +877,23 @@ namespace {
                                return;
                        }
 
-                       if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
+                       if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
+                               param_bool(ID(A_SIGNED));
+                               param_bool(ID(B_SIGNED), /*expected=*/false);
+                               port(ID::A, param(ID(A_WIDTH)));
+                               port(ID::B, param(ID(B_WIDTH)));
+                               port(ID::Y, param(ID(Y_WIDTH)));
+                               check_expected(/*check_matched_sign=*/false);
+                               return;
+                       }
+
+                       if (cell->type.in(ID($shift), ID($shiftx))) {
                                param_bool(ID(A_SIGNED));
                                param_bool(ID(B_SIGNED));
                                port(ID::A, param(ID(A_WIDTH)));
                                port(ID::B, param(ID(B_WIDTH)));
                                port(ID::Y, param(ID(Y_WIDTH)));
-                               check_expected(false);
+                               check_expected(/*check_matched_sign=*/false);
                                return;
                        }
 
@@ -957,7 +975,7 @@ namespace {
                                port(ID::A, param(ID(A_WIDTH)));
                                port(ID::B, param(ID(B_WIDTH)));
                                port(ID::Y, param(ID(Y_WIDTH)));
-                               check_expected(false);
+                               check_expected(/*check_matched_sign=*/false);
                                return;
                        }