From: whitequark <whitequark@whitequark.org>
Date: Wed, 4 Dec 2019 11:59:36 +0000 (+0000)
Subject: kernel: require \B_SIGNED=0 on $shl, $sshl, $shr, $sshr.
X-Git-Tag: working-ls180~933^2
X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e97e33d;p=yosys.git

kernel: require \B_SIGNED=0 on $shl, $sshl, $shr, $sshr.

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.
---

diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index daea3b43a..a30935e0a 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -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 {
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index bd2fd91a3..7c73f94c8 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -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;
 			}