aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/verilog/verilog_lexer.l59
-rw-r--r--frontends/verilog/verilog_parser.y99
2 files changed, 66 insertions, 92 deletions
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index e51a12f76..6ef38252a 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -189,57 +189,18 @@ YOSYS_NAMESPACE_END
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
- /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex
- to do it in the parser (because we force the parser too early to reduce when parsing cells..) */
-([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] {
- frontend_verilog_yylval.string = new std::string(yytext);
- auto &str = *frontend_verilog_yylval.string;
- std::string keyword;
- int cursor = 0;
-
- while (1) {
- if (cursor == GetSize(str)) {
- keyword = str;
- delete frontend_verilog_yylval.string;
- frontend_verilog_yylval.string = nullptr;
- goto sva_without_label;
- }
- char c = str[cursor];
- if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') {
- cursor++;
- continue;
- }
-
- keyword = str.substr(cursor);
- str = "\\" + str.substr(0, cursor);
- break;
- }
-
- cursor = 0;
- while (1) {
- log_assert(cursor < GetSize(keyword));
- char c = keyword[cursor];
- if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') {
- keyword = keyword.substr(cursor);
- break;
- }
- cursor++;
- }
-
- if (keyword == "assert") { return TOK_ASSERT; }
- else if (keyword == "assume") { return TOK_ASSUME; }
- else if (keyword == "cover") { return TOK_COVER; }
- else if (keyword == "restrict") { return TOK_RESTRICT; }
- else log_abort();
-
-sva_without_label:
- if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
- else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
- else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
- else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
- else log_abort();
+ /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
+ to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
+ global state.. its a mess) */
+[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
+ frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
+ return TOK_SVA_LABEL;
}
+"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
+"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
+"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
+"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 649dd384f..52685f637 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -105,8 +105,8 @@ static void free_attr(std::map<std::string, AstNode*> *al)
bool boolean;
}
-%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
-%token <string> TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
+%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL
+%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
@@ -126,7 +126,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
-%type <string> opt_label tok_prim_wrapper hierarchical_id
+%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id
%type <boolean> opt_signed opt_property unique_case_attr
%type <al> attr case_attr
@@ -1329,6 +1329,14 @@ opt_label:
$$ = NULL;
};
+opt_sva_label:
+ TOK_SVA_LABEL ':' {
+ $$ = $1;
+ } |
+ /* empty */ {
+ $$ = NULL;
+ };
+
opt_property:
TOK_PROPERTY {
$$ = true;
@@ -1373,11 +1381,11 @@ modport_type_token:
TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
assert:
- TOK_ASSERT opt_property '(' expr ')' ';' {
+ opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' {
if (noassert_mode) {
- delete $4;
+ delete $5;
} else {
- AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4);
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1385,11 +1393,11 @@ assert:
if ($1 != nullptr)
delete $1;
} |
- TOK_ASSUME opt_property '(' expr ')' ';' {
+ opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' {
if (noassume_mode) {
- delete $4;
+ delete $5;
} else {
- AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4);
+ AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1397,11 +1405,11 @@ assert:
if ($1 != nullptr)
delete $1;
} |
- TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
+ opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (noassert_mode) {
- delete $5;
+ delete $6;
} else {
- AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5);
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1409,11 +1417,11 @@ assert:
if ($1 != nullptr)
delete $1;
} |
- TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
+ opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (noassume_mode) {
- delete $5;
+ delete $6;
} else {
- AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5);
+ AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1421,15 +1429,15 @@ assert:
if ($1 != nullptr)
delete $1;
} |
- TOK_COVER opt_property '(' expr ')' ';' {
- AstNode *node = new AstNode(AST_COVER, $4);
+ opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
+ AstNode *node = new AstNode(AST_COVER, $5);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
}
ast_stack.back()->children.push_back(node);
} |
- TOK_COVER opt_property '(' ')' ';' {
+ opt_sva_label TOK_COVER opt_property '(' ')' ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
if ($1 != nullptr) {
node->str = *$1;
@@ -1437,7 +1445,7 @@ assert:
}
ast_stack.back()->children.push_back(node);
} |
- TOK_COVER ';' {
+ opt_sva_label TOK_COVER ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
if ($1 != nullptr) {
node->str = *$1;
@@ -1445,87 +1453,87 @@ assert:
}
ast_stack.back()->children.push_back(node);
} |
- TOK_RESTRICT opt_property '(' expr ')' ';' {
+ opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' {
if (norestrict_mode) {
- delete $4;
+ delete $5;
} else {
- AstNode *node = new AstNode(AST_ASSUME, $4);
+ AstNode *node = new AstNode(AST_ASSUME, $5);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
}
- if (!$2)
+ if (!$3)
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
if ($1 != nullptr)
delete $1;
} |
- TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
+ opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode) {
- delete $5;
+ delete $6;
} else {
- AstNode *node = new AstNode(AST_FAIR, $5);
+ AstNode *node = new AstNode(AST_FAIR, $6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
}
- if (!$2)
+ if (!$3)
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
if ($1 != nullptr)
delete $1;
};
assert_property:
- TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
+ opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
- TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
+ opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
- TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
+ opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
- TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
+ opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
- TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
+ opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
- TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
+ opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
if (norestrict_mode) {
- delete $4;
+ delete $5;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
}
} |
- TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
+ opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode) {
- delete $5;
+ delete $6;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
+ ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -1748,6 +1756,11 @@ case_expr_list:
TOK_DEFAULT {
ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
} |
+ TOK_SVA_LABEL {
+ ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER));
+ ast_stack.back()->children.back()->str = *$1;
+ delete $1;
+ } |
expr {
ast_stack.back()->children.push_back($1);
} |