From 7cfdf4ffa7698fa40aae401c2b8b159a6e37011a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Feb 2020 12:16:01 -0800 Subject: [PATCH 1/7] verilog: fix $specify3 check --- frontends/ast/genrtlil.cc | 18 +++++++++++------- tests/various/specify.v | 7 +++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 94f5c0a04..05a5b45b8 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1559,21 +1559,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Attribute `%s' with non-constant value.\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - if (cell->type.in("$specify2", "$specify3")) { + if (cell->type == "$specify2") { int src_width = GetSize(cell->getPort("\\SRC")); int dst_width = GetSize(cell->getPort("\\DST")); bool full = cell->getParam("\\FULL").as_bool(); if (!full && src_width != dst_width) log_file_error(filename, linenum, "Parallel specify SRC width does not match DST width.\n"); - if (cell->type == "$specify3") { - int dat_width = GetSize(cell->getPort("\\DAT")); - if (dat_width != dst_width) - log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n"); - } cell->setParam("\\SRC_WIDTH", Const(src_width)); cell->setParam("\\DST_WIDTH", Const(dst_width)); } - if (cell->type == "$specrule") { + else if (cell->type == "$specify3") { + int dat_width = GetSize(cell->getPort("\\DAT")); + int dst_width = GetSize(cell->getPort("\\DST")); + if (dat_width != dst_width) + log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n"); + int src_width = GetSize(cell->getPort("\\SRC")); + cell->setParam("\\SRC_WIDTH", Const(src_width)); + cell->setParam("\\DST_WIDTH", Const(dst_width)); + } + else if (cell->type == "$specrule") { int src_width = GetSize(cell->getPort("\\SRC")); int dst_width = GetSize(cell->getPort("\\DST")); cell->setParam("\\SRC_WIDTH", Const(src_width)); diff --git a/tests/various/specify.v b/tests/various/specify.v index 5d44d78f7..e4dd132f1 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -37,3 +37,10 @@ specify (posedge clk *> (q +: d)) = (3,1); endspecify endmodule + +module test3(input clk, input [1:0] d, output [1:0] q); +specify + (posedge clk => (q +: d)) = (3,1); + (posedge clk *> (q +: d)) = (3,1); +endspecify +endmodule From b523ecf2f45f80488412781ba9a3455a71d64d62 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 08:59:08 -0800 Subject: [PATCH 2/7] specify: system timing checks to accept min:typ:max triple --- backends/verilog/verilog_backend.cc | 12 +++++++-- frontends/verilog/verilog_parser.y | 41 ++++++++++++++++++++--------- kernel/rtlil.cc | 8 ++++-- tests/various/specify.v | 7 +++++ 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 682c47a1f..19541f1c4 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1417,11 +1417,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) decimal = 1; f << ", "; - dump_const(f, cell->getParam("\\T_LIMIT")); + dump_const(f, cell->getParam("\\T_LIMIT_MIN")); + f << ": "; + dump_const(f, cell->getParam("\\T_LIMIT_TYP")); + f << ": "; + dump_const(f, cell->getParam("\\T_LIMIT_MAX")); if (spec_type == "$setuphold" || spec_type == "$recrem" || spec_type == "$fullskew") { f << ", "; - dump_const(f, cell->getParam("\\T_LIMIT2")); + dump_const(f, cell->getParam("\\T_LIMIT2_MIN")); + f << ": "; + dump_const(f, cell->getParam("\\T_LIMIT2_TYP")); + f << ": "; + dump_const(f, cell->getParam("\\T_LIMIT2_MAX")); } f << ");\n"; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8840cf4e8..9b1b07f86 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -161,9 +161,9 @@ struct specify_rise_fall { %type attr case_attr %type specify_target -%type specify_triple +%type specify_triple specify_opt_triple %type specify_rise_fall -%type specify_if specify_condition specify_opt_arg +%type specify_if specify_condition %type specify_edge // operator precedence from low to high @@ -855,7 +855,7 @@ specify_item: delete target; delete timing; } | - TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' expr specify_opt_arg ')' ';' { + TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' specify_triple specify_opt_triple ')' ';' { if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" && *$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange") frontend_verilog_yyerror("Unsupported specify rule type: %s\n", $1->c_str()); @@ -868,8 +868,8 @@ specify_item: AstNode *dst_pol = AstNode::mkconst_int($7 == 'p', false, 1); AstNode *dst_expr = $8, *dst_en = $9 ? $9 : AstNode::mkconst_int(1, false, 1); - AstNode *limit = $11; - AstNode *limit2 = $12; + specify_triple *limit = $11; + specify_triple *limit2 = $12; AstNode *cell = new AstNode(AST_CELL); ast_stack.back()->children.push_back(cell); @@ -880,11 +880,23 @@ specify_item: cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1))); cell->children.back()->str = "\\TYPE"; - cell->children.push_back(new AstNode(AST_PARASET, limit)); - cell->children.back()->str = "\\T_LIMIT"; + cell->children.push_back(new AstNode(AST_PARASET, limit->t_min)); + cell->children.back()->str = "\\T_LIMIT_MIN"; - cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2 : AstNode::mkconst_int(0, true))); - cell->children.back()->str = "\\T_LIMIT2"; + cell->children.push_back(new AstNode(AST_PARASET, limit->t_avg)); + cell->children.back()->str = "\\T_LIMIT_TYP"; + + cell->children.push_back(new AstNode(AST_PARASET, limit->t_max)); + cell->children.back()->str = "\\T_LIMIT_MAX"; + + cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_min : AstNode::mkconst_int(0, true))); + cell->children.back()->str = "\\T_LIMIT2_MIN"; + + cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_avg : AstNode::mkconst_int(0, true))); + cell->children.back()->str = "\\T_LIMIT2_TYP"; + + cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2->t_max : AstNode::mkconst_int(0, true))); + cell->children.back()->str = "\\T_LIMIT2_MAX"; cell->children.push_back(new AstNode(AST_PARASET, src_pen)); cell->children.back()->str = "\\SRC_PEN"; @@ -913,8 +925,8 @@ specify_item: delete $1; }; -specify_opt_arg: - ',' expr { +specify_opt_triple: + ',' specify_triple { $$ = $2; } | /* empty */ { @@ -1123,7 +1135,12 @@ ignspec_constant_expression: expr { delete $1; }; ignspec_expr: - expr { delete $1; }; + expr { delete $1; } | + expr ':' expr ':' expr { + delete $1; + delete $3; + delete $5; + }; ignspec_id: TOK_ID { delete $1; }; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f286d139f..5d7e61901 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1258,8 +1258,12 @@ namespace { param_bool(ID(SRC_POL)); param_bool(ID(DST_PEN)); param_bool(ID(DST_POL)); - param(ID(T_LIMIT)); - param(ID(T_LIMIT2)); + param(ID(T_LIMIT_MIN)); + param(ID(T_LIMIT_TYP)); + param(ID(T_LIMIT_MAX)); + param(ID(T_LIMIT2_MIN)); + param(ID(T_LIMIT2_TYP)); + param(ID(T_LIMIT2_MAX)); port(ID(SRC_EN), 1); port(ID(DST_EN), 1); port(ID(SRC), param(ID(SRC_WIDTH))); diff --git a/tests/various/specify.v b/tests/various/specify.v index e4dd132f1..5006e4c38 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -44,3 +44,10 @@ specify (posedge clk *> (q +: d)) = (3,1); endspecify endmodule + +module test4(input clk, d, output q); +specify + $setup(d, posedge clk, 1:2:3); + $setuphold(d, posedge clk, 1:2:3, 4:5:6); +endspecify +endmodule From 2e51dc1856aae456e15cafd484997bfbd102175e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 13:06:13 -0800 Subject: [PATCH 3/7] verilog: ignore '&&&' when not in -specify mode --- frontends/verilog/verilog_lexer.l | 2 +- frontends/verilog/verilog_parser.y | 9 +++++---- tests/various/specify.v | 6 ++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 9b43c250e..18fa2966b 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -440,7 +440,7 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { } "&&&" { - if (!specify_mode) REJECT; + if (!specify_mode) return TOK_IGNORED_SPECIFY_AND; return TOK_SPECIFY_AND; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9b1b07f86..f37c6d99b 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -146,7 +146,7 @@ struct specify_rise_fall { %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY -%token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND +%token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND TOK_IGNORED_SPECIFY_AND %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED @@ -1117,6 +1117,7 @@ system_timing_arg : system_timing_args : system_timing_arg | + system_timing_args TOK_IGNORED_SPECIFY_AND system_timing_arg | system_timing_args ',' system_timing_arg ; path_delay_expression : @@ -1137,9 +1138,9 @@ ignspec_constant_expression: ignspec_expr: expr { delete $1; } | expr ':' expr ':' expr { - delete $1; - delete $3; - delete $5; + delete $1; + delete $3; + delete $5; }; ignspec_id: diff --git a/tests/various/specify.v b/tests/various/specify.v index 5006e4c38..aa8aca4bc 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -51,3 +51,9 @@ specify $setuphold(d, posedge clk, 1:2:3, 4:5:6); endspecify endmodule + +module test5(input clk, d, e, output q); +specify + $setup(d, posedge clk &&& e, 1:2:3); +endspecify +endmodule From 6b58c1820c7bbacb4730af40e10592823b0eb15c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 13:27:15 -0800 Subject: [PATCH 4/7] verilog: improve specify support when not in -specify mode --- frontends/verilog/verilog_parser.y | 20 +++++++------------- tests/various/specify.v | 2 -- tests/various/specify.ys | 2 +- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index f37c6d99b..155de8f90 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1043,7 +1043,7 @@ list_of_specparam_assignments: specparam_assignment | list_of_specparam_assignments ',' specparam_assignment; specparam_assignment: - ignspec_id '=' constant_mintypmax_expression ; + ignspec_id '=' ignspec_expr ; ignspec_opt_cond: TOK_IF '(' ignspec_expr ')' | /* empty */; @@ -1060,13 +1060,15 @@ simple_path_declaration : ; path_delay_value : - '(' path_delay_expression list_of_path_delay_extra_expressions ')' - | path_delay_expression - | path_delay_expression list_of_path_delay_extra_expressions + '(' ignspec_expr list_of_path_delay_extra_expressions ')' + | ignspec_expr + | ignspec_expr list_of_path_delay_extra_expressions ; list_of_path_delay_extra_expressions : - ',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions; + ',' ignspec_expr + | ',' ignspec_expr list_of_path_delay_extra_expressions + ; specify_edge_identifier : TOK_POSEDGE | TOK_NEGEDGE ; @@ -1120,14 +1122,6 @@ system_timing_args : system_timing_args TOK_IGNORED_SPECIFY_AND system_timing_arg | system_timing_args ',' system_timing_arg ; -path_delay_expression : - ignspec_constant_expression; - -constant_mintypmax_expression : - ignspec_constant_expression - | ignspec_constant_expression ':' ignspec_constant_expression ':' ignspec_constant_expression - ; - // for the time being this is OK, but we may write our own expr here. // as I'm not sure it is legal to use a full expr here (probably not) // On the other hand, other rules requiring constant expressions also use 'expr' diff --git a/tests/various/specify.v b/tests/various/specify.v index aa8aca4bc..5655ded21 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -7,11 +7,9 @@ module test ( if (EN) Q <= D; specify -`ifndef SKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS if (EN) (posedge CLK *> (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); -`endif endspecify endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index 00597e1e2..a2b6038e4 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -55,4 +55,4 @@ equiv_induct -seq 5 equiv_status -assert design -reset -read_verilog -DSKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS specify.v +read_verilog specify.v From d20c1dac73e344dda73ec2b526ffb764efc9fdd8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 17:58:43 -0800 Subject: [PATCH 5/7] verilog: ignore ranges too without -specify --- frontends/verilog/verilog_parser.y | 3 ++- tests/various/specify.v | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 155de8f90..dc8f39e8d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1138,7 +1138,8 @@ ignspec_expr: }; ignspec_id: - TOK_ID { delete $1; }; + TOK_ID { delete $1; } + range_or_multirange { delete $3; }; /**********************************************************************/ diff --git a/tests/various/specify.v b/tests/various/specify.v index 5655ded21..c160d2ec4 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -55,3 +55,10 @@ specify $setup(d, posedge clk &&& e, 1:2:3); endspecify endmodule + +module test6(input clk, d, e, output q); +specify + (d[0] *> q[0]) = (3,1); + (posedge clk[0] => (q[0] +: d[0])) = (3,1); +endspecify +endmodule From 1d401a7991f4c0f133b7355acc400132da1aa4a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 19 Feb 2020 10:45:10 -0800 Subject: [PATCH 6/7] clean: ignore specify-s inside cells when determining whether to keep --- passes/opt/opt_clean.cc | 24 +++++++++++++++--------- tests/various/specify.ys | 21 ++++++++++++++++++++- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 2f69b3d4c..f5bb40050 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -51,20 +51,26 @@ struct keep_cache_t if (cache.count(module)) return cache.at(module); - cache[module] = true; - if (!module->get_bool_attribute(ID::keep)) { - bool found_keep = false; + bool found_keep = false; + if (module->get_bool_attribute(ID::keep)) + found_keep = true; + else for (auto cell : module->cells()) - if (query(cell)) found_keep = true; - cache[module] = found_keep; - } + if (query(cell, true /* ignore_specify */)) { + found_keep = true; + break; + } + cache[module] = found_keep; - return cache[module]; + return found_keep; } - bool query(Cell *cell) + bool query(Cell *cell, bool ignore_specify = false) { - if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule))) + if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) + return true; + + if (!ignore_specify && cell->type.in(ID($specify2), ID($specify3), ID($specrule))) return true; if (cell->has_keep_attr()) diff --git a/tests/various/specify.ys b/tests/various/specify.ys index a2b6038e4..9d55b8eb5 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -55,4 +55,23 @@ equiv_induct -seq 5 equiv_status -assert design -reset -read_verilog specify.v +read_verilog -specify < o) = 1; +endspecify +assign o = ~i; +endmodule + +module test7(input i, output o); + wire w; + test7_sub unused(i, w); + test7_sub used(i, o); +endmodule +EOT +hierarchy +cd test7 +clean +select -assert-count 1 c:used +select -assert-none c:* c:used %d From ea4bd161b68cda30b5300b9275ebc0723896be02 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 19 Feb 2020 11:09:37 -0800 Subject: [PATCH 7/7] verilog: add support for more delays than just rise/fall --- frontends/verilog/verilog_parser.y | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index dc8f39e8d..dc58acdb0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -995,7 +995,46 @@ specify_rise_fall: $$->fall = *$4; delete $2; delete $4; - }; + } | + '(' specify_triple ',' specify_triple ',' specify_triple ')' { + $$ = new specify_rise_fall; + $$->rise = *$2; + $$->fall = *$4; + delete $2; + delete $4; + delete $6; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + } | + '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { + $$ = new specify_rise_fall; + $$->rise = *$2; + $$->fall = *$4; + delete $2; + delete $4; + delete $6; + delete $8; + delete $10; + delete $12; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + } | + '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { + $$ = new specify_rise_fall; + $$->rise = *$2; + $$->fall = *$4; + delete $2; + delete $4; + delete $6; + delete $8; + delete $10; + delete $12; + delete $14; + delete $16; + delete $18; + delete $20; + delete $22; + delete $24; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + } specify_triple: expr {