From 9770ece187f11482eb8e86d66765881a781a5f01 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Thu, 22 May 2025 19:12:35 -0600 Subject: [PATCH] Accept (and ignore) SystemVerilog unique/priority if. Add support to the "read_verilog -sv" parser to validate the "unique", "unique0", and "priority" keywords in contexts where they're legal according to 1800-2012 12.4.2. This affects only the grammar accepted; the behaviour of conditionals is not changed. (But accepting this syntax will provide scope for possible optimisations as future work.) Three test cases ("unique_if", "unique_if_else", and "unique_if_else_begin") verify that the keywords are accepted where legal and rejected where illegal, as described in the final paragraph of 12.4.2. --- docs/source/yosys_internals/verilog.rst | 6 ++++++ frontends/verilog/verilog_parser.y | 28 +++++++++++++++++++++++-- kernel/constids.inc | 1 + tests/verilog/unique_if.ys | 10 +++++++++ tests/verilog/unique_if_else.ys | 11 ++++++++++ tests/verilog/unique_if_else_begin.ys | 12 +++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/verilog/unique_if.ys create mode 100644 tests/verilog/unique_if_else.ys create mode 100644 tests/verilog/unique_if_else_begin.ys diff --git a/docs/source/yosys_internals/verilog.rst b/docs/source/yosys_internals/verilog.rst index a1941963d..eef215e5d 100644 --- a/docs/source/yosys_internals/verilog.rst +++ b/docs/source/yosys_internals/verilog.rst @@ -375,3 +375,9 @@ from SystemVerilog: ports are inputs or outputs are supported. - Assignments within expressions are supported. + +- The ``unique``, ``unique0``, and ``priority`` SystemVerilog keywords are + accepted on ``if`` and ``case`` conditionals. (Those keywords are currently + handled in the same way as their equivalent ``full_case`` and + ``parallel_case`` attributes on ``case`` statements, and checked + for syntactic validity but otherwise ignored on ``if`` statements.) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9d0956c8e..e70542a92 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -426,7 +426,7 @@ static const AstNode *addAsgnBinopStmt(dict *attr, AstNode * %type opt_property always_comb_or_latch always_or_always_ff %type opt_signedness_default_signed opt_signedness_default_unsigned %type integer_atom_type integer_vector_type -%type attr case_attr +%type attr if_attr case_attr %type struct_union %type asgn_binop inc_or_dec_op %type genvar_identifier @@ -2871,7 +2871,7 @@ behavioral_stmt: ast_stack.pop_back(); ast_stack.pop_back(); } | - attr TOK_IF '(' expr ')' { + if_attr TOK_IF '(' expr ')' { AstNode *node = new AstNode(AST_CASE); AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block); @@ -2901,6 +2901,29 @@ behavioral_stmt: ast_stack.pop_back(); }; +if_attr: + attr { + $$ = $1; + } | + attr TOK_UNIQUE0 { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("unique0 keyword cannot be used for 'else if' branch."); + $$ = $1; // accept unique0 keyword, but ignore it for now + } | + attr TOK_PRIORITY { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("priority keyword cannot be used for 'else if' branch."); + $$ = $1; // accept priority keyword, but ignore it for now + } | + attr TOK_UNIQUE { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("unique keyword cannot be used for 'else if' branch."); + $$ = $1; // accept unique keyword, but ignore it for now + }; + case_attr: attr { $$ = $1; @@ -2948,6 +2971,7 @@ behavioral_stmt_list: optional_else: TOK_ELSE { AstNode *block = new AstNode(AST_BLOCK); + block->attributes[ID::promoted_if] = AstNode::mkconst_int(1, false ); AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block); SET_AST_NODE_LOC(cond, @1, @1); diff --git a/kernel/constids.inc b/kernel/constids.inc index 4fdbb3dc8..c9b645d53 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -153,6 +153,7 @@ X(parameter) X(PORTID) X(PRIORITY) X(PRIORITY_MASK) +X(promoted_if) X(Q) X(R) X(ram_block) diff --git a/tests/verilog/unique_if.ys b/tests/verilog/unique_if.ys new file mode 100644 index 000000000..07140b195 --- /dev/null +++ b/tests/verilog/unique_if.ys @@ -0,0 +1,10 @@ +read_verilog -sv <