Also add support for labels on sva module items, fixes #699

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2019-03-08 22:53:58 -08:00
parent 5dfc7becca
commit e7a34d342e
2 changed files with 129 additions and 60 deletions

View File

@ -189,10 +189,57 @@ YOSYS_NAMESPACE_END
"always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_ff" { SV_KEYWORD(TOK_ALWAYS); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); }
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } to do it in the parser (because we force the parser too early to reduce when parsing cells..) */
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } ([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] {
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } 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();
}
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }

View File

@ -106,6 +106,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
} }
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
%token <string> TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
@ -119,14 +120,13 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %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 <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <string> opt_label opt_stmt_label tok_prim_wrapper hierarchical_id %type <string> opt_label tok_prim_wrapper hierarchical_id
%type <boolean> opt_signed opt_property unique_case_attr %type <boolean> opt_signed opt_property unique_case_attr
%type <al> attr case_attr %type <al> attr case_attr
@ -1337,14 +1337,6 @@ opt_property:
$$ = false; $$ = false;
}; };
opt_stmt_label:
TOK_ID ':' {
$$ = $1;
} |
/* empty */ {
$$ = NULL;
};
modport_stmt: modport_stmt:
TOK_MODPORT TOK_ID { TOK_MODPORT TOK_ID {
AstNode *modport = new AstNode(AST_MODPORT); AstNode *modport = new AstNode(AST_MODPORT);
@ -1381,11 +1373,35 @@ modport_type_token:
TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
assert: assert:
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { TOK_ASSERT opt_property '(' expr ')' ';' {
if (noassert_mode) {
delete $4;
} else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
}
if ($1 != nullptr)
delete $1;
} |
TOK_ASSUME opt_property '(' expr ')' ';' {
if (noassume_mode) {
delete $4;
} else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
}
if ($1 != nullptr)
delete $1;
} |
TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (noassert_mode) { if (noassert_mode) {
delete $5; delete $5;
} else { } else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5);
if ($1 != nullptr) if ($1 != nullptr)
node->str = *$1; node->str = *$1;
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
@ -1393,11 +1409,11 @@ assert:
if ($1 != nullptr) if ($1 != nullptr)
delete $1; delete $1;
} | } |
opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (noassume_mode) { if (noassume_mode) {
delete $5; delete $5;
} else { } else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5);
if ($1 != nullptr) if ($1 != nullptr)
node->str = *$1; node->str = *$1;
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
@ -1405,39 +1421,15 @@ assert:
if ($1 != nullptr) if ($1 != nullptr)
delete $1; delete $1;
} | } |
opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { TOK_COVER opt_property '(' expr ')' ';' {
if (noassert_mode) { AstNode *node = new AstNode(AST_COVER, $4);
delete $6;
} else {
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);
}
if ($1 != nullptr)
delete $1;
} |
opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (noassume_mode) {
delete $6;
} else {
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);
}
if ($1 != nullptr)
delete $1;
} |
opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' {
AstNode *node = new AstNode(AST_COVER, $5);
if ($1 != nullptr) { if ($1 != nullptr) {
node->str = *$1; node->str = *$1;
delete $1; delete $1;
} }
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
} | } |
opt_stmt_label TOK_COVER opt_property '(' ')' ';' { TOK_COVER opt_property '(' ')' ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
if ($1 != nullptr) { if ($1 != nullptr) {
node->str = *$1; node->str = *$1;
@ -1445,7 +1437,7 @@ assert:
} }
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
} | } |
opt_stmt_label TOK_COVER ';' { TOK_COVER ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
if ($1 != nullptr) { if ($1 != nullptr) {
node->str = *$1; node->str = *$1;
@ -1453,30 +1445,30 @@ assert:
} }
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
} | } |
opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { TOK_RESTRICT opt_property '(' expr ')' ';' {
if (norestrict_mode) { if (norestrict_mode) {
delete $5; delete $4;
} else { } else {
AstNode *node = new AstNode(AST_ASSUME, $5); AstNode *node = new AstNode(AST_ASSUME, $4);
if ($1 != nullptr) if ($1 != nullptr)
node->str = *$1; node->str = *$1;
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
} }
if (!$3) if (!$2)
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
if ($1 != nullptr) if ($1 != nullptr)
delete $1; delete $1;
} | } |
opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode) { if (norestrict_mode) {
delete $6; delete $5;
} else { } else {
AstNode *node = new AstNode(AST_FAIR, $6); AstNode *node = new AstNode(AST_FAIR, $5);
if ($1 != nullptr) if ($1 != nullptr)
node->str = *$1; node->str = *$1;
ast_stack.back()->children.push_back(node); ast_stack.back()->children.push_back(node);
} }
if (!$3) if (!$2)
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
if ($1 != nullptr) if ($1 != nullptr)
delete $1; delete $1;
@ -1485,30 +1477,60 @@ assert:
assert_property: assert_property:
TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} | } |
TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} | } |
TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} | } |
TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} | } |
TOK_COVER TOK_PROPERTY '(' expr ')' ';' { TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} | } |
TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
if (norestrict_mode) if (norestrict_mode) {
delete $4; delete $4;
else } else {
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
}
} | } |
TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
if (norestrict_mode) if (norestrict_mode) {
delete $5; delete $5;
else } else {
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
}
}; };
simple_behavioral_stmt: simple_behavioral_stmt: