diff options
Diffstat (limited to 'frontends/verilog')
-rw-r--r-- | frontends/verilog/const2ast.cc | 78 | ||||
-rw-r--r-- | frontends/verilog/preproc.cc | 3 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 23 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 4 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 8 |
5 files changed, 74 insertions, 42 deletions
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index ebecb92f2..4a58357bf 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -96,44 +96,54 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le if (base == 10 && GetSize(digits) == 1 && digits.front() >= 0xf0) base = 2; + data.clear(); + if (base == 10) { - data.clear(); - if (len_in_bits < 0) { - while (!digits.empty()) - data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); - while (data.size() < 32) - data.push_back(RTLIL::S0); - } else { - for (int i = 0; i < len_in_bits; i++) - data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); + while (!digits.empty()) + data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); + } else { + int bits_per_digit = my_ilog2(base-1); + for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) { + if (*it > (base-1) && *it < 0xf0) + log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n", + base-1, base, current_filename.c_str(), get_line_num()); + for (int i = 0; i < bits_per_digit; i++) { + int bitmask = 1 << i; + if (*it == 0xf0) + data.push_back(case_type == 'x' ? RTLIL::Sa : RTLIL::Sx); + else if (*it == 0xf1) + data.push_back(case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz); + else if (*it == 0xf2) + data.push_back(RTLIL::Sa); + else + data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0); + } } - return; } - int bits_per_digit = my_ilog2(base-1); - if (len_in_bits < 0) - len_in_bits = std::max<int>(digits.size() * bits_per_digit, 32); + int len = GetSize(data); + RTLIL::State msb = data.empty() ? RTLIL::S0 : data.back(); - data.clear(); - data.resize(len_in_bits); - - for (int i = 0; i < len_in_bits; i++) { - int bitmask = 1 << (i % bits_per_digit); - int digitidx = digits.size() - (i / bits_per_digit) - 1; - if (digitidx < 0) { - if (i > 0 && (data[i-1] == RTLIL::Sz || data[i-1] == RTLIL::Sx || data[i-1] == RTLIL::Sa)) - data[i] = data[i-1]; - else - data[i] = RTLIL::S0; - } else if (digits[digitidx] == 0xf0) - data[i] = case_type == 'x' ? RTLIL::Sa : RTLIL::Sx; - else if (digits[digitidx] == 0xf1) - data[i] = case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz; - else if (digits[digitidx] == 0xf2) - data[i] = RTLIL::Sa; - else - data[i] = (digits[digitidx] & bitmask) ? RTLIL::S1 : RTLIL::S0; + if (len_in_bits < 0) { + if (len < 32) + data.resize(32, msb == RTLIL::S0 || msb == RTLIL::S1 ? RTLIL::S0 : msb); + return; + } + + for (len = len - 1; len >= 0; len--) + if (data[len] == RTLIL::S1) + break; + if (msb == RTLIL::S0 || msb == RTLIL::S1) { + len += 1; + data.resize(len_in_bits, RTLIL::S0); + } else { + len += 2; + data.resize(len_in_bits, msb); } + + if (len > len_in_bits) + log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n", + len_in_bits, len, current_filename.c_str(), get_line_num()); } // convert the Verilog code for a constant to an AST node @@ -142,7 +152,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (warn_z) { AstNode *ret = const2ast(code, case_type); if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) - log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n", + log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", current_filename.c_str(), get_line_num()); return ret; } @@ -220,8 +230,6 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (len_in_bits < 0) { if (is_signed && data.back() == RTLIL::S1) data.push_back(RTLIL::S0); - while (data.size() < 32) - data.push_back(RTLIL::S0); } return AstNode::mkconst_bits(data, is_signed); } diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index fb8a7b95f..997920b89 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -39,6 +39,7 @@ #include <string.h> YOSYS_NAMESPACE_BEGIN +using namespace VERILOG_FRONTEND; static std::list<std::string> output_code; static std::list<std::string> input_buffer; @@ -222,7 +223,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons input_file(f, filename); defines_map["YOSYS"] = "1"; - defines_map["SYNTHESIS"] = "1"; + defines_map[formal_mode ? "FORMAL" : "SYNTHESIS"] = "1"; while (!input_buffer.empty()) { diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 727ee3d1c..cd8b586c4 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -39,6 +39,14 @@ using namespace VERILOG_FRONTEND; static std::vector<std::string> verilog_defaults; static std::list<std::vector<std::string>> verilog_defaults_stack; +static void error_on_dpi_function(AST::AstNode *node) +{ + if (node->type == AST::AST_DPI_FUNCTION) + log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum); + for (auto child : node->children) + error_on_dpi_function(child); +} + struct VerilogFrontend : public Frontend { VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } virtual void help() @@ -55,8 +63,8 @@ struct VerilogFrontend : public Frontend { log(" of SystemVerilog is supported)\n"); log("\n"); log(" -formal\n"); - log(" enable support for assert() and assume() statements\n"); - log(" (assert support is also enabled with -sv)\n"); + log(" enable support for assert() and assume() from SystemVerilog\n"); + log(" replace the implicit -D SYNTHESIS with -D FORMAL\n"); log("\n"); log(" -dump_ast1\n"); log(" dump abstract syntax tree (before simplification)\n"); @@ -107,6 +115,9 @@ struct VerilogFrontend : public Frontend { log(" -nopp\n"); log(" do not run the pre-processor\n"); log("\n"); + log(" -nodpi\n"); + log(" disable DPI-C support\n"); + log("\n"); log(" -lib\n"); log(" only create empty blackbox modules. This implies -DBLACKBOX.\n"); log("\n"); @@ -160,6 +171,7 @@ struct VerilogFrontend : public Frontend { bool flag_mem2reg = false; bool flag_ppdump = false; bool flag_nopp = false; + bool flag_nodpi = false; bool flag_lib = false; bool flag_noopt = false; bool flag_icells = false; @@ -229,6 +241,10 @@ struct VerilogFrontend : public Frontend { flag_nopp = true; continue; } + if (arg == "-nodpi") { + flag_nodpi = true; + continue; + } if (arg == "-lib") { flag_lib = true; defines_map["BLACKBOX"] = string(); @@ -320,6 +336,9 @@ struct VerilogFrontend : public Frontend { child->attributes[attr] = AST::AstNode::mkconst_int(1, false); } + if (flag_nodpi) + error_on_dpi_function(current_ast); + AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire); if (!flag_nopp) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index a72593583..69a8ddaad 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -170,7 +170,7 @@ YOSYS_NAMESPACE_END "always_latch" { SV_KEYWORD(TOK_ALWAYS); } "assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; return TOK_ID; } +"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "logic" { SV_KEYWORD(TOK_REG); } "bit" { SV_KEYWORD(TOK_REG); } @@ -248,7 +248,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { supply0 { return TOK_SUPPLY0; } supply1 { return TOK_SUPPLY1; } -"$"(display|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { +"$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 708ac7627..863fee599 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -153,6 +153,8 @@ design: module design | defattr design | task_func_decl design | + param_decl design | + localparam_decl design | /* empty */; attr: @@ -708,6 +710,8 @@ wire_name_and_opt_assign: wire_name: TOK_ID range_or_multirange { + if (astbuf1 == nullptr) + frontend_verilog_yyerror("Syntax error."); AstNode *node = astbuf1->clone(); node->str = *$1; append_attr_clone(node, albuf); @@ -755,7 +759,7 @@ assign_expr_list: assign_expr | assign_expr_list ',' assign_expr; assign_expr: - expr '=' expr { + lvalue '=' expr { ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); }; @@ -959,7 +963,7 @@ simple_behavioral_stmt: // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: - defattr | assert | wire_decl | + defattr | assert | wire_decl | param_decl | localparam_decl | non_opt_delay behavioral_stmt | simple_behavioral_stmt ';' | ';' | hierarchical_id attr { |