From f6fe73b31f6e6d8966ad4ddae860b4d79133cce2 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 18 Sep 2018 01:23:40 +0300 Subject: Fixed remaining cases where we check fo wire reg/wire incorrect assignments on Yosys-generated assignments. In this case, offending code was: module top(input in, output out); function func; input arg; func = arg; endfunction assign out = func(in); endmodule --- frontends/ast/simplify.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a9608369c..ae46e4bc9 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1337,6 +1337,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list.at(0)); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1373,6 +1374,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list[0]); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1531,6 +1533,7 @@ skip_dynamic_range_lvalue_expansion:; wire_tmp_id->str = wire_tmp->str; newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone())); + newNode->children.back()->was_checked = true; int cursor = 0; for (auto child : children[0]->children) @@ -1816,6 +1819,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *regid = new AstNode(AST_IDENTIFIER); regid->str = reg->str; regid->id2ast = reg; + regid->was_checked = true; AstNode *rhs = nullptr; @@ -2202,6 +2206,8 @@ skip_dynamic_range_lvalue_expansion:; AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_EQ, lvalue, clone()))); + always->children[0]->children[0]->was_checked = true; + current_ast_mod->children.push_back(always); goto replace_fcall_with_id; @@ -2251,6 +2257,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone()); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2321,6 +2328,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id, arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2760,6 +2768,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value)); block->children.back()->children[0]->str = memory->str; block->children.back()->children[0]->id2ast = memory; + block->children.back()->children[0]->was_checked = true; } cursor += increment; @@ -3021,6 +3030,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *newNode = clone(); newNode->type = AST_ASSIGN_EQ; async_block->children[0]->children.push_back(newNode); + async_block->children[0]->children.back()->children[0]->was_checked = true; newNode = new AstNode(AST_NONE); newNode->cloneInto(this); @@ -3065,6 +3075,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->str = was_checked; block->children.insert(block->children.begin()+assign_idx+1, assign_addr); AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); @@ -3088,6 +3099,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, children[0]->id2ast = NULL; children[0]->str = id_data; type = AST_ASSIGN_EQ; + children[0]->was_checked = true; did_something = true; } -- cgit v1.2.3 From eb452ffb2861ceac572a4bef6dddb8db3b79deb7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 23 Sep 2018 10:32:54 +0200 Subject: Added support for ommited "parameter" in Verilog-2001 style parameter decl in SV mode Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2389d7d31..63cf646e9 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -881,9 +881,15 @@ param_decl_list: single_param_decl: TOK_ID '=' expr { - if (astbuf1 == nullptr) - frontend_verilog_yyerror("syntax error"); - AstNode *node = astbuf1->clone(); + AstNode *node; + if (astbuf1 == nullptr) { + if (!sv_mode) + frontend_verilog_yyerror("syntax error"); + node = new AstNode(AST_PARAMETER); + node->children.push_back(AstNode::mkconst_int(0, true)); + } else { + node = astbuf1->clone(); + } node->str = *$1; delete node->children[0]; node->children[0] = $3; -- cgit v1.2.3 From 8fde05dfa58d87ff2e71495c77f698af19a0d80b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 24 Sep 2018 20:51:16 +0200 Subject: Add "read_verilog -noassert -noassume -assert-assumes" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_frontend.cc | 23 ++++++++++++++++++++++- frontends/verilog/verilog_frontend.h | 9 +++++++++ frontends/verilog/verilog_parser.y | 23 ++++++++++++++++++----- 3 files changed, 49 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 8dcc7c5aa..aeea36a2b 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -66,12 +66,21 @@ struct VerilogFrontend : public Frontend { log(" enable support for SystemVerilog assertions and some Yosys extensions\n"); log(" replace the implicit -D SYNTHESIS with -D FORMAL\n"); log("\n"); + log(" -noassert\n"); + log(" ignore assert() statements\n"); + log("\n"); + log(" -noassume\n"); + log(" ignore assume() statements\n"); + log("\n"); log(" -norestrict\n"); - log(" ignore restrict() assertions\n"); + log(" ignore restrict() statements\n"); log("\n"); log(" -assume-asserts\n"); log(" treat all assert() statements like assume() statements\n"); log("\n"); + log(" -assert-assumes\n"); + log(" treat all assume() statements like assert() statements\n"); + log("\n"); log(" -dump_ast1\n"); log(" dump abstract syntax tree (before simplification)\n"); log("\n"); @@ -229,6 +238,14 @@ struct VerilogFrontend : public Frontend { formal_mode = true; continue; } + if (arg == "-noassert") { + noassert_mode = true; + continue; + } + if (arg == "-noassume") { + noassume_mode = true; + continue; + } if (arg == "-norestrict") { norestrict_mode = true; continue; @@ -237,6 +254,10 @@ struct VerilogFrontend : public Frontend { assume_asserts_mode = true; continue; } + if (arg == "-assert-assumes") { + assert_assumes_mode = true; + continue; + } if (arg == "-dump_ast1") { flag_dump_ast1 = true; continue; diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 16edc7985..523bbc897 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -54,12 +54,21 @@ namespace VERILOG_FRONTEND // running in -formal mode extern bool formal_mode; + // running in -noassert mode + extern bool noassert_mode; + + // running in -noassume mode + extern bool noassume_mode; + // running in -norestrict mode extern bool norestrict_mode; // running in -assume-asserts mode extern bool assume_asserts_mode; + // running in -assert-assumes mode + extern bool assert_assumes_mode; + // running in -lib mode extern bool lib_mode; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 63cf646e9..16cac1460 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -58,7 +58,8 @@ namespace VERILOG_FRONTEND { bool do_not_require_port_stubs; bool default_nettype_wire; bool sv_mode, formal_mode, lib_mode; - bool norestrict_mode, assume_asserts_mode; + bool noassert_mode, noassume_mode, norestrict_mode; + bool assume_asserts_mode, assert_assumes_mode; bool current_wire_rand, current_wire_const; std::istream *lexin; } @@ -1281,16 +1282,28 @@ opt_stmt_label: assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); + if (noassert_mode) + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); } | opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + if (noassume_mode) + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5)); } | opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); + if (noassert_mode) + delete $6; + else + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); } | opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + if (noassume_mode) + delete $6; + else + ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6)); } | opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); -- cgit v1.2.3 From 80a07652f2eb5e13190f46dcc116207a0427dc65 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 25 Sep 2018 00:32:57 +0300 Subject: Fixed issue #630 by fixing a minor typo in the previous commit (as well as a non critical minor code optimization) --- frontends/ast/simplify.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e741bd92a..e1c2cb26a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3028,8 +3028,8 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *newNode = clone(); newNode->type = AST_ASSIGN_EQ; + newNode->children[0]->was_checked = true; async_block->children[0]->children.push_back(newNode); - async_block->children[0]->children.back()->children[0]->was_checked = true; newNode = new AstNode(AST_NONE); newNode->cloneInto(this); @@ -3074,7 +3074,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->str = was_checked; + assign_addr->children[0]->was_checked = true; block->children.insert(block->children.begin()+assign_idx+1, assign_addr); AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); -- cgit v1.2.3 From 9f9fe94b3522d465d98fa491c5992b14d268f09d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 30 Sep 2018 18:43:35 +0200 Subject: Fix handling of $past 2nd argument in read_verilog Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 04c429f7f..aa3b982d8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1781,7 +1781,7 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) == 2) { AstNode *buf = children[1]->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + while (buf->simplify(true, false, false, stage, -1, false, false)) { } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); -- cgit v1.2.3 From 62424ef3de67dc8077a0ca03b302966f0284730f Mon Sep 17 00:00:00 2001 From: Dan Gisselquist Date: Mon, 1 Oct 2018 19:41:35 +0200 Subject: Add read_verilog $changed support Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index aa3b982d8..71eba547c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1836,7 +1836,7 @@ skip_dynamic_range_lvalue_expansion:; goto apply_newNode; } - if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell") + if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed") { if (GetSize(children) != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", @@ -1853,6 +1853,9 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$stable") newNode = new AstNode(AST_EQ, past, present); + else if (str == "\\$changed") + newNode = new AstNode(AST_NE, past, present); + else if (str == "\\$rose") newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); -- cgit v1.2.3 From cb214fc01d95ed9df7de10ccffa3471a1dc91659 Mon Sep 17 00:00:00 2001 From: Tom Verbeure Date: Tue, 2 Oct 2018 07:44:23 +0000 Subject: Fix for issue 594. --- frontends/ast/genrtlil.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 0f7e910f3..c9345ff08 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -985,7 +985,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) use_const_chunk: if (children.size() != 0) { - log_assert(children[0]->type == AST_RANGE); + if (children[0]->type != AST_RANGE) + log_file_error(filename, linenum, "Single range expected.\n"); int source_width = id2ast->range_left - id2ast->range_right + 1; int source_offset = id2ast->range_right; if (!children[0]->range_valid) { -- cgit v1.2.3 From 4b0448fc2cc707f312813b4e0826371fa384e3d9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 5 Oct 2018 09:26:10 +0200 Subject: Fix compiler warning in verific.cc Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index c5fa58313..06d98611a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1676,6 +1676,7 @@ YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN +#ifdef YOSYS_ENABLE_VERIFIC bool check_noverific_env() { const char *e = getenv("YOSYS_NOVERIFIC"); @@ -1685,6 +1686,7 @@ bool check_noverific_env() return false; return true; } +#endif struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } -- cgit v1.2.3 From 9850de405a11fe93e4562c86be0a0830b83c2785 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 7 Oct 2018 19:48:42 +0200 Subject: Improve Verific importer blackbox handling Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 06d98611a..dba3b0f0c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -118,6 +118,18 @@ RTLIL::SigBit VerificImporter::net_map_at(Net *net) return net_map.at(net); } +bool is_blackbox(Netlist *nl) +{ + if (nl->IsBlackBox()) + return true; + + const char *attr = nl->GetAttValue("blackbox"); + if (attr != nullptr && strcmp(attr, "0")) + return true; + + return false; +} + void VerificImporter::import_attributes(dict &attributes, DesignObj *obj) { MapIter mi; @@ -709,7 +721,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se netlist = nl; if (design->has(module_name)) { - if (!nl->IsOperator()) + if (!nl->IsOperator() && !is_blackbox(nl)) log_cmd_error("Re-definition of module `%s'.\n", nl->Owner()->Name()); return; } @@ -718,7 +730,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se module->name = module_name; design->add(module); - if (nl->IsBlackBox()) { + if (is_blackbox(nl)) { log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name)); module->set_bool_attribute("\\blackbox"); } else { -- cgit v1.2.3 From 75009ada3c2a4bcd38c52c8fb871c9e8c1f2e6b1 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Thu, 11 Oct 2018 23:33:31 +0200 Subject: Synthesis support for SystemVerilog interfaces This time doing the changes mostly in AST before RTLIL generation --- frontends/ast/ast.cc | 133 ++++++++++++++++++++++++++++++++++--- frontends/ast/ast.h | 6 ++ frontends/ast/genrtlil.cc | 48 ++++++++++++- frontends/ast/simplify.cc | 2 +- frontends/verilog/verilog_lexer.l | 8 +++ frontends/verilog/verilog_parser.y | 60 +++++++++++++++++ 6 files changed, 243 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e79be953a..256c08776 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -905,7 +905,7 @@ RTLIL::Const AstNode::realAsConst(int width) // create a new AstModule from an AST_MODULE AST node static AstModule* process_module(AstNode *ast, bool defer) { - log_assert(ast->type == AST_MODULE); + log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); if (defer) log("Storing AST representation for module `%s'.\n", ast->str.c_str()); @@ -916,6 +916,7 @@ static AstModule* process_module(AstNode *ast, bool defer) current_module->ast = NULL; current_module->name = ast->str; current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); + current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; AstNode *ast_before_simplify = ast->clone(); @@ -989,6 +990,8 @@ static AstModule* process_module(AstNode *ast, bool defer) ignoreThisSignalsInInitial = RTLIL::SigSpec(); } + if (ast->type == AST_INTERFACE) + current_module->set_bool_attribute("\\is_interface"); current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomeminit = flag_nomeminit; @@ -1031,7 +1034,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump log_assert(current_ast->type == AST_DESIGN); for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { - if ((*it)->type == AST_MODULE) + if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE) { for (auto n : design->verilog_globals) (*it)->children.push_back(n->clone()); @@ -1083,8 +1086,123 @@ AstModule::~AstModule() delete ast; } +void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) +{ + bool is_top = false; + AstNode *new_ast = ast->clone(); + for (auto &intf : local_interfaces) { + std::string intfname = intf.first.str(); + RTLIL::Module *intfmodule = intf.second; + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string newname = log_id(wire_it.first); + newname = intfname + "." + newname; + wire->str = newname; + new_ast->children.push_back(wire); + } + } + std::string original_name = this->name.str(); + std::string changed_name = original_name + "_before_replacing_local_interfaces"; + design->rename(this, changed_name); + this->set_bool_attribute("\\to_delete"); + if (this->get_bool_attribute("\\initial_top")) { + this->attributes.erase("\\initial_top"); + is_top = true; + } + AstModule *newmod = process_module(new_ast, false); + design->add(newmod); + RTLIL::Module* mod = design->module(original_name); + if (is_top) + mod->set_bool_attribute("\\top"); + mod->set_bool_attribute("\\interfaces_replaced_in_module"); +} + +// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + // Since interfaces themselves may be instantiated with different parameters, + // "modname" must also take those into account, so that unique modules + // are derived for any variant of interface connections: + std::string interf_info = ""; + + bool has_interfaces = false; + for(auto &intf : interfaces) { + interf_info += log_id(intf.second->name); + has_interfaces = true; + } + + if (has_interfaces) + modname += "$interfaces$" + interf_info; + + + if (!design->has(modname)) { + new_ast->str = modname; + for(auto &intf : interfaces) { + RTLIL::Module * intfmodule = intf.second; + std::string intfname = intf.first.str(); + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } + } + + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + + RTLIL::Module* mod = design->module(modname); + + for(auto &intf : interfaces) { + if(mod->wires_.count(intf.first)) { + mod->wires_.erase(intf.first); + mod->fixup_ports(); + RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); + new_subcell->set_bool_attribute("\\is_interface"); + } + else { + log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + } + } + + if (interfaces.size() > 0) { + mod->set_bool_attribute("\\interfaces_replaced_in_module"); + } + + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + +// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + if (!design->has(modname)) { + new_ast->str = modname; + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool) +std::string AstModule::derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool) { std::string stripped_name = name.str(); @@ -1156,15 +1274,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dicthas(modname)) { - new_ast->str = modname; - design->add(process_module(new_ast, false)); - design->module(modname)->check(); - } else { - log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); - } - delete new_ast; + (*new_ast_out) = new_ast; return modname; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 7e97bdb3b..6b93832b4 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -142,6 +142,9 @@ namespace AST AST_NEGEDGE, AST_EDGE, + AST_INTERFACE, + AST_INTERFACEPORT, + AST_INTERFACEPORTTYPE, AST_PACKAGE }; @@ -284,6 +287,9 @@ namespace AST bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) YS_OVERRIDE; + std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); + void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index c9345ff08..1dd1a9130 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -854,6 +854,22 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENCASE: case AST_PACKAGE: break; + case AST_INTERFACEPORT: { + // If a port in a module with unknown type is found, mark it as "is_interface=true" + // This is used by the hierarchy pass to know when it can replace interface connection with the individual + // signals. + RTLIL::Wire *wire = current_module->addWire(str, 1); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->start_offset = 0; + wire->port_id = port_id; + wire->port_input = true; + wire->port_output = true; + wire->set_bool_attribute("\\is_interface"); + wire->upto = 0; + } + break; + case AST_INTERFACEPORTTYPE: + break; // remember the parameter, needed for example in techmap case AST_PARAMETER: @@ -949,6 +965,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { RTLIL::Wire *wire = NULL; RTLIL::SigChunk chunk; + bool is_interface = false; int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; @@ -969,15 +986,41 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } - else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE && - id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0) + else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { + RTLIL::Wire *current_wire = current_module->wire(str); + if (current_wire->get_bool_attribute("\\is_interface")) + is_interface = true; + // Ignore + } + // If an identifier is found that is not already known, assume that it is an interface: + else if (1) { // FIXME: Check if sv_mode first? + is_interface = true; + } + else { log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); + } if (id2ast->type == AST_MEMORY) log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); + // If identifier is an interface, create a RTLIL::SigSpec object and set is_interface to true. + // This makes it possible for the hierarchy pass to see what are interface connections and then replace them + // with the individual signals: + if (is_interface) { + RTLIL::Wire *dummy_wire; + std::string dummy_wire_name = "$dummywireforinterface" + str; + if (current_module->wires_.count(dummy_wire_name)) + dummy_wire = current_module->wires_[dummy_wire_name]; + else { + dummy_wire = current_module->addWire(dummy_wire_name); + dummy_wire->set_bool_attribute("\\is_interface"); + } + RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire); + return tmp; + } + wire = current_module->wires_[str]; chunk.wire = wire; chunk.width = wire->width; @@ -1423,6 +1466,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { AstNode *child = *it; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 71eba547c..2a561ea5f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { - log_assert(type == AST_MODULE); + log_assert(type == AST_MODULE || type == AST_INTERFACE); last_blocking_assignment_warn = pair(); deep_recursion_warning = true; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..8808c2675 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -150,6 +150,9 @@ YOSYS_NAMESPACE_END "specparam" { return TOK_SPECPARAM; } "package" { SV_KEYWORD(TOK_PACKAGE); } "endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); } +"interface" { SV_KEYWORD(TOK_INTERFACE); } +"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } +"modport" { SV_KEYWORD(TOK_MODPORT); } "parameter" { return TOK_PARAMETER; } "localparam" { return TOK_LOCALPARAM; } "defparam" { return TOK_DEFPARAM; } @@ -295,6 +298,11 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } +[a-zA-Z_$][a-zA-Z0-9_$\.]* { + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_ID; +} + "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { static bool printed_warning = false; if (!printed_warning) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 16cac1460..0ff5d576e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -106,6 +106,7 @@ static void free_attr(std::map *al) %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 +%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT @@ -168,6 +169,7 @@ design: param_decl design | localparam_decl design | package design | + interface design | /* empty */; attr: @@ -320,6 +322,21 @@ module_arg: } delete $1; } module_arg_opt_assignment | + TOK_ID { + astbuf1 = new AstNode(AST_INTERFACEPORT); + astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); + astbuf1->children[0]->str = *$1; + delete $1; + } TOK_ID { /* SV interfaces */ + if (!sv_mode) + frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); + astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type. + astbuf2->str = *$3; + delete $3; + astbuf2->port_id = ++port_counter; + ast_stack.back()->children.push_back(astbuf2); + delete astbuf1; // really only needed if multiple instances of same type. + } module_arg_opt_assignment | attr wire_type range TOK_ID { AstNode *node = $2; node->str = *$4; @@ -357,6 +374,33 @@ package_body: package_body_stmt: localparam_decl; +interface: + TOK_INTERFACE TOK_ID { + do_not_require_port_stubs = false; + AstNode *intf = new AstNode(AST_INTERFACE); + ast_stack.back()->children.push_back(intf); + ast_stack.push_back(intf); + current_ast_mod = intf; + port_stubs.clear(); + port_counter = 0; + intf->str = *$2; + delete $2; + } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { + if (port_stubs.size() != 0) + frontend_verilog_yyerror("Missing details for module port `%s'.", + port_stubs.begin()->first.c_str()); + ast_stack.pop_back(); + log_assert(ast_stack.size() == 1); + current_ast_mod = NULL; + }; + +interface_body: + interface_body interface_body_stmt |; + +interface_body_stmt: + param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | + modport_stmt; + non_opt_delay: '#' TOK_ID { delete $2; } | '#' TOK_CONSTVAL { delete $2; } | @@ -1280,6 +1324,22 @@ opt_property: opt_stmt_label: TOK_ID ':' | /* empty */; +modport_stmt: + TOK_MODPORT TOK_ID modport_args_opt ';' + +modport_args_opt: + '(' ')' | '(' modport_args optional_comma ')'; + +modport_args: + modport_arg | modport_args ',' modport_arg; + +modport_arg: + modport_type_token TOK_ID | + TOK_ID + +modport_type_token: + TOK_INPUT | TOK_OUTPUT + assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) -- cgit v1.2.3 From 458a94059e6738d93a87ddb9af282d0e1d28791d Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Fri, 12 Oct 2018 20:58:37 +0200 Subject: Support for 'modports' for System Verilog interfaces --- frontends/ast/ast.cc | 40 ++++++++++++++++++++++++++++++++++---- frontends/ast/ast.h | 4 +++- frontends/ast/genrtlil.cc | 29 +++++++++++++++++++++++++++ frontends/verilog/verilog_parser.y | 24 ++++++++++++++++++++--- 4 files changed, 89 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 256c08776..10fd5277a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1118,7 +1118,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) { AstNode *new_ast = NULL; std::string modname = derive_common(design, parameters, &new_ast, mayfail); @@ -1143,14 +1143,46 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict 0) { + std::string interface_modport = modports.at(intfname).str(); + AstModule *ast_module_of_interface = (AstModule*)intfmodule; + AstNode *ast_node_of_interface = ast_module_of_interface->ast; + for (auto &ch : ast_node_of_interface->children) { + if (ch->type == AST_MODPORT) { + if (ch->str == interface_modport) { + modport = ch; + } + } + } + } for (auto &wire_it : intfmodule->wires_){ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); std::string origname = log_id(wire_it.first); std::string newname = intfname + "." + origname; wire->str = newname; - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); + if (modport != NULL) { + bool found_in_modport = false; + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { // If not found in modport, do not create port + new_ast->children.push_back(wire); + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } } } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 6b93832b4..8187b1ac6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -145,6 +145,8 @@ namespace AST AST_INTERFACE, AST_INTERFACEPORT, AST_INTERFACEPORTTYPE, + AST_MODPORT, + AST_MODPORTMEMBER, AST_PACKAGE }; @@ -287,7 +289,7 @@ namespace AST bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; - RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) YS_OVERRIDE; std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 1dd1a9130..d87163dc2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,6 +853,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: + case AST_MODPORT: + case AST_MODPORTMEMBER: break; case AST_INTERFACEPORT: { // If a port in a module with unknown type is found, mark it as "is_interface=true" @@ -865,6 +867,33 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->port_input = true; wire->port_output = true; wire->set_bool_attribute("\\is_interface"); + if (children.size() > 0) { + for(size_t i=0; itype == AST_INTERFACEPORTTYPE) { + std::string name_type = children[i]->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + if (ndots == 0) { + wire->attributes["\\interface_type"] = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { + wire->attributes["\\interface_type"] = seglist[0]; + wire->attributes["\\interface_modport"] = seglist[1]; + } + else { + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + break; + } + } + } wire->upto = 0; } break; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 0ff5d576e..a6f37008a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -61,6 +61,7 @@ namespace VERILOG_FRONTEND { bool noassert_mode, noassume_mode, norestrict_mode; bool assume_asserts_mode, assert_assumes_mode; bool current_wire_rand, current_wire_const; + bool current_modport_input, current_modport_output; std::istream *lexin; } YOSYS_NAMESPACE_END @@ -1325,7 +1326,16 @@ opt_stmt_label: TOK_ID ':' | /* empty */; modport_stmt: - TOK_MODPORT TOK_ID modport_args_opt ';' + TOK_MODPORT TOK_ID { + AstNode *modport = new AstNode(AST_MODPORT); + ast_stack.back()->children.push_back(modport); + ast_stack.push_back(modport); + modport->str = *$2; + delete $2; + } modport_args_opt { + ast_stack.pop_back(); + log_assert(ast_stack.size() == 2); + } ';' modport_args_opt: '(' ')' | '(' modport_args optional_comma ')'; @@ -1334,11 +1344,19 @@ modport_args: modport_arg | modport_args ',' modport_arg; modport_arg: - modport_type_token TOK_ID | + modport_type_token TOK_ID { + AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); + ast_stack.back()->children.push_back(modport_member); + modport_member->str = *$2; + modport_member->is_input = current_modport_input; + modport_member->is_output = current_modport_output; + delete $2; + } | TOK_ID + /* FIXME for TOK_ID without modport_type_token */ modport_type_token: - TOK_INPUT | TOK_OUTPUT + TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { -- cgit v1.2.3 From a36d1701dd99736b82f64ed870e7464f2deae220 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Fri, 12 Oct 2018 22:02:29 +0200 Subject: Fix build error with clang --- frontends/ast/ast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 10fd5277a..b3f78c922 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1199,7 +1199,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictset_bool_attribute("\\is_interface"); } else { - log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str()); } } -- cgit v1.2.3 From 455638e00dff4951e666fb91fbd80de6b9e95f9f Mon Sep 17 00:00:00 2001 From: argama Date: Sun, 14 Oct 2018 01:42:48 +0800 Subject: detect ff/latch before processing other nodes --- frontends/liberty/liberty.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0a5bd84de..0018d6dac 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -634,6 +634,8 @@ struct LibertyFrontend : public Frontend { } } + // some liberty files do not put ff/latch at the beginning of a cell + // try to find "ff" or "latch" and create FF/latch before processing all other nodes for (auto node : cell->children) { if (!flag_lib) { @@ -645,6 +647,21 @@ struct LibertyFrontend : public Frontend { goto skip_cell; } } + } + + for (auto node : cell->children) + { + /* + if (!flag_lib) { + if (node->id == "ff" && node->args.size() == 2) + create_ff(module, node); + if (node->id == "latch" && node->args.size() == 2) + if (!create_latch(module, node, flag_ignore_miss_data_latch)) { + delete module; + goto skip_cell; + } + } + */ if (node->id == "pin" && node->args.size() == 1) { -- cgit v1.2.3 From c50afc4246d552db079aec303b0d79ae92107a67 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 13 Oct 2018 20:34:44 +0200 Subject: Documentation improvements etc. - Mention new feature in the SystemVerilog section in the README file - Commented changes much better - Rename a few signals to make it clearer - Prevent warning for unused signals in an easier way - Add myself as copyright holder to 2 files - Fix one potential memory leak (delete 'wire' if not in modport) --- frontends/ast/ast.cc | 31 ++++++++++++++++++++++++++++--- frontends/ast/genrtlil.cc | 12 +++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index b3f78c922..7600e2912 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2018 Ruben Undheim * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1086,6 +1087,8 @@ AstModule::~AstModule() delete ast; } +// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again +// from AST. The interface members are copied into the AST module with the prefix of the interface. void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) { bool is_top = false; @@ -1101,23 +1104,33 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictchildren.push_back(wire); } } + + // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; design->rename(this, changed_name); this->set_bool_attribute("\\to_delete"); + + // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the + // new module. if (this->get_bool_attribute("\\initial_top")) { this->attributes.erase("\\initial_top"); is_top = true; } + + // Generate RTLIL from AST for the new module and add to the design: AstModule *newmod = process_module(new_ast, false); design->add(newmod); RTLIL::Module* mod = design->module(original_name); if (is_top) mod->set_bool_attribute("\\top"); + + // Set the attribute "interfaces_replaced_in_module" so that it does not happen again. mod->set_bool_attribute("\\interfaces_replaced_in_module"); } // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) { AstNode *new_ast = NULL; @@ -1140,9 +1153,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dicthas(modname)) { new_ast->str = modname; + + // Iterate over all interfaces which are ports in this module: for(auto &intf : interfaces) { RTLIL::Module * intfmodule = intf.second; std::string intfname = intf.first.str(); + // Check if a modport applies for the interface port: AstNode *modport = NULL; if (modports.count(intfname) > 0) { std::string interface_modport = modports.at(intfname).str(); @@ -1150,12 +1166,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictast; for (auto &ch : ast_node_of_interface->children) { if (ch->type == AST_MODPORT) { - if (ch->str == interface_modport) { + if (ch->str == interface_modport) { // Modport found modport = ch; } } } } + // Iterate over all wires in the interface and add them to the module: for (auto &wire_it : intfmodule->wires_){ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); std::string origname = log_id(wire_it.first); @@ -1163,10 +1180,11 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictstr = newname; if (modport != NULL) { bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport for (auto &ch : modport->children) { if (ch->type == AST_MODPORTMEMBER) { std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output found_in_modport = true; wire->is_input = ch->is_input; wire->is_output = ch->is_output; @@ -1174,9 +1192,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictchildren.push_back(wire); } + else { // If not found in modport, do not create port + delete wire; + } } else { // If no modport, set inout wire->is_input = true; @@ -1191,10 +1212,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictmodule(modname); + // Now that the interfaces have been exploded, we can delete the dummy port related to every interface. for(auto &intf : interfaces) { if(mod->wires_.count(intf.first)) { mod->wires_.erase(intf.first); mod->fixup_ports(); + // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated + // down to sub-sub-modules etc. RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); new_subcell->set_bool_attribute("\\is_interface"); } @@ -1203,6 +1227,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict 0) { mod->set_bool_attribute("\\interfaces_replaced_in_module"); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d87163dc2..32b9af6e9 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -857,7 +857,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MODPORTMEMBER: break; case AST_INTERFACEPORT: { - // If a port in a module with unknown type is found, mark it as "is_interface=true" + // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' // This is used by the hierarchy pass to know when it can replace interface connection with the individual // signals. RTLIL::Wire *wire = current_module->addWire(str, 1); @@ -872,7 +872,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if(children[i]->type == AST_INTERFACEPORTTYPE) { std::string name_type = children[i]->str; size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - if (ndots == 0) { + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport wire->attributes["\\interface_type"] = name_type; } else { @@ -882,11 +883,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while(std::getline(name_type_stream, segment, '.')) { seglist.push_back(segment); } - if (ndots == 1) { + if (ndots == 1) { // Has modport wire->attributes["\\interface_type"] = seglist[0]; wire->attributes["\\interface_modport"] = seglist[1]; } - else { + else { // Erroneous port type log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); } } @@ -1034,7 +1035,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); - // If identifier is an interface, create a RTLIL::SigSpec object and set is_interface to true. + // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them // with the individual signals: if (is_interface) { @@ -1495,6 +1496,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { -- cgit v1.2.3 From 736105b0468f9468f00915cad60949535ce5a496 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 13 Oct 2018 20:48:55 +0200 Subject: Handle FIXME for modport members without type directly in front --- frontends/verilog/verilog_parser.y | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a6f37008a..4dbe028a0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1344,16 +1344,18 @@ modport_args: modport_arg | modport_args ',' modport_arg; modport_arg: - modport_type_token TOK_ID { + modport_type_token modport_member | + modport_member + +modport_member: + TOK_ID { AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); ast_stack.back()->children.push_back(modport_member); - modport_member->str = *$2; + modport_member->str = *$1; modport_member->is_input = current_modport_input; modport_member->is_output = current_modport_output; - delete $2; - } | - TOK_ID - /* FIXME for TOK_ID without modport_type_token */ + delete $1; + } modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} -- cgit v1.2.3 From 097da32e1a8cfe29d64666c1b2c9b47129b07c7e Mon Sep 17 00:00:00 2001 From: argama Date: Tue, 16 Oct 2018 21:33:37 +0800 Subject: ignore protect endprotect --- frontends/verilog/verilog_lexer.l | 3 +++ 1 file changed, 3 insertions(+) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..2c4880b84 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END frontend_verilog_yyerror("Unsupported default nettype: %s", p); } +"`protect"[^\n]* /* ignore `protect*/ +"`endprotect"[^\n]* /* ignore `endprotect*/ + "`"[a-zA-Z_$][a-zA-Z0-9_$]* { frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext); } -- cgit v1.2.3 From 6ca493b88ca101f357e9de4dfdad4f3c913512c8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 Oct 2018 12:23:36 +0200 Subject: Minor code cleanups in liberty front-end Signed-off-by: Clifford Wolf --- frontends/liberty/liberty.cc | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0018d6dac..66db43baf 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -634,11 +634,12 @@ struct LibertyFrontend : public Frontend { } } - // some liberty files do not put ff/latch at the beginning of a cell - // try to find "ff" or "latch" and create FF/latch before processing all other nodes - for (auto node : cell->children) + if (!flag_lib) { - if (!flag_lib) { + // some liberty files do not put ff/latch at the beginning of a cell + // try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes + for (auto node : cell->children) + { if (node->id == "ff" && node->args.size() == 2) create_ff(module, node); if (node->id == "latch" && node->args.size() == 2) @@ -651,18 +652,6 @@ struct LibertyFrontend : public Frontend { for (auto node : cell->children) { - /* - if (!flag_lib) { - if (node->id == "ff" && node->args.size() == 2) - create_ff(module, node); - if (node->id == "latch" && node->args.size() == 2) - if (!create_latch(module, node, flag_ignore_miss_data_latch)) { - delete module; - goto skip_cell; - } - } - */ - if (node->id == "pin" && node->args.size() == 1) { LibertyAst *dir = node->find("direction"); -- cgit v1.2.3 From d9a438101298710b9dadd4e7a1cb0041e8ba4199 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 11:57:39 +0200 Subject: Fixed memory leak --- frontends/ast/ast.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7600e2912..1f2ecffde 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1120,6 +1120,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictadd(newmod); RTLIL::Module* mod = design->module(original_name); if (is_top) -- cgit v1.2.3 From 397dfccb304a12a40d34c4454a5cb4acee8be75f Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 11:58:25 +0200 Subject: Support for SystemVerilog interfaces as a port in the top level module + test case --- frontends/ast/ast.cc | 108 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 1f2ecffde..412e04f6e 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -904,7 +904,7 @@ RTLIL::Const AstNode::realAsConst(int width) } // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast, bool defer) +static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL) { log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); @@ -920,7 +920,11 @@ static AstModule* process_module(AstNode *ast, bool defer) current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; - AstNode *ast_before_simplify = ast->clone(); + AstNode *ast_before_simplify; + if (original_ast != NULL) + ast_before_simplify = original_ast; + else + ast_before_simplify = ast->clone(); if (flag_dump_ast1) { log("Dumping Verilog AST before simplification:\n"); @@ -1105,6 +1109,104 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictclone(); + + // Explode all interface ports. Note this will only have any effect on top + // level modules. Other sub-modules will have their interface ports + // exploded in derive(..) + for (size_t i =0; ichildren.size(); i++) + { + AstNode *ch2 = new_ast->children[i]; + std::string interface_type = ""; + std::string interface_modport = ""; + if (ch2->type == AST_INTERFACEPORT) { + std::string name_port = ch2->str; + if (ch2->children.size() > 0) { + for(size_t j=0; jchildren.size();j++) { + AstNode *ch = ch2->children[j]; + if(ch->type == AST_INTERFACEPORTTYPE) { + std::string name_type = ch->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport + interface_type = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { // Has modport + interface_type = seglist[0]; + interface_modport = seglist[1]; + } + else { // Erroneous port type + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + if (design->modules_.count(interface_type) > 0) { + AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); + celltype_for_intf->str = interface_type; + AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); + cell_for_intf->str = name_port + "_inst_from_top_dummy"; + new_ast->children.push_back(cell_for_intf); + + RTLIL::Module *intfmodule = design->modules_[interface_type]; + AstModule *ast_module_of_interface = (AstModule*)intfmodule; + AstNode *ast_node_of_interface = ast_module_of_interface->ast; + AstNode *modport = NULL; + std::string interface_modport_compare_str = "\\" + interface_modport; + for (auto &chm : ast_node_of_interface->children) { + if (chm->type == AST_MODPORT) { + if (chm->str == interface_modport_compare_str) { // Modport found + modport = chm; + } + } + } + + std::string intfname = name_port; + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + if (modport != NULL) { + bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { + new_ast->children.push_back(wire); + } + else { // If not found in modport, do not create port + delete wire; + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } + } + } + } + } + } + } + } + + // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; @@ -1119,7 +1221,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictadd(newmod); RTLIL::Module* mod = design->module(original_name); -- cgit v1.2.3 From 436e3c0a7cbe5a482e14857e4e5a1d02b3464ae8 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 12:45:51 +0200 Subject: Refactor code to avoid code duplication + added comments --- frontends/ast/ast.cc | 212 ++++++++++++++++++++++------------------------ frontends/ast/ast.h | 5 ++ frontends/ast/genrtlil.cc | 25 +----- 3 files changed, 108 insertions(+), 134 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 412e04f6e..cc275959a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1091,6 +1091,84 @@ AstModule::~AstModule() delete ast; } + +// An interface port with modport is specified like this: +// . +// This function splits the interface_name from the modport_name, and fails if it is not a valid combination +std::pair AST::split_modport_from_type(std::string name_type) +{ + std::string interface_type = ""; + std::string interface_modport = ""; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport + interface_type = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { // Has modport + interface_type = seglist[0]; + interface_modport = seglist[1]; + } + else { // Erroneous port type + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + return std::pair(interface_type, interface_modport); + +} + +AstNode * AST::find_modport(AstNode *intf, std::string name) +{ + for (auto &ch : intf->children) + if (ch->type == AST_MODPORT) + if (ch->str == name) // Modport found + return ch; + return NULL; +} + +// Iterate over all wires in an interface and add them as wires in the AST module: +void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) +{ + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + if (modport != NULL) { + bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { + module_ast->children.push_back(wire); + } + else { // If not found in modport, do not create port + delete wire; + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + module_ast->children.push_back(wire); + } + } +} + // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again // from AST. The interface members are copied into the AST module with the prefix of the interface. void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) @@ -1111,102 +1189,47 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictclone(); - // Explode all interface ports. Note this will only have any effect on top - // level modules. Other sub-modules will have their interface ports - // exploded in derive(..) + // Explode all interface ports. Note this will only have an effect on 'top + // level' modules. Other sub-modules will have their interface ports + // exploded via the derive(..) function for (size_t i =0; ichildren.size(); i++) { AstNode *ch2 = new_ast->children[i]; - std::string interface_type = ""; - std::string interface_modport = ""; - if (ch2->type == AST_INTERFACEPORT) { - std::string name_port = ch2->str; + if (ch2->type == AST_INTERFACEPORT) { // Is an interface port + std::string name_port = ch2->str; // Name of the interface port if (ch2->children.size() > 0) { for(size_t j=0; jchildren.size();j++) { AstNode *ch = ch2->children[j]; - if(ch->type == AST_INTERFACEPORTTYPE) { - std::string name_type = ch->str; - size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - // Separate the interface instance name from any modports: - if (ndots == 0) { // Does not have modport - interface_type = name_type; - } - else { - std::stringstream name_type_stream(name_type); - std::string segment; - std::vector seglist; - while(std::getline(name_type_stream, segment, '.')) { - seglist.push_back(segment); - } - if (ndots == 1) { // Has modport - interface_type = seglist[0]; - interface_modport = seglist[1]; - } - else { // Erroneous port type - log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); - } - } + if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface + std::pair res = split_modport_from_type(ch->str); + std::string interface_type = res.first; + std::string interface_modport = res.second; // Is "", if no modport if (design->modules_.count(interface_type) > 0) { + // Add a cell to the module corresponding to the interface port such that + // it can further propagated down if needed: AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); celltype_for_intf->str = interface_type; AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); cell_for_intf->str = name_port + "_inst_from_top_dummy"; new_ast->children.push_back(cell_for_intf); - RTLIL::Module *intfmodule = design->modules_[interface_type]; + // Get all members of this non-overridden dummy interface instance: + RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming + // reprocess_module is called from the hierarchy pass) be + // present in design->modules_ AstModule *ast_module_of_interface = (AstModule*)intfmodule; - AstNode *ast_node_of_interface = ast_module_of_interface->ast; - AstNode *modport = NULL; std::string interface_modport_compare_str = "\\" + interface_modport; - for (auto &chm : ast_node_of_interface->children) { - if (chm->type == AST_MODPORT) { - if (chm->str == interface_modport_compare_str) { // Modport found - modport = chm; - } - } - } - - std::string intfname = name_port; - for (auto &wire_it : intfmodule->wires_){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); - std::string origname = log_id(wire_it.first); - std::string newname = intfname + "." + origname; - wire->str = newname; - if (modport != NULL) { - bool found_in_modport = false; - // Search for the current wire in the wire list for the current modport - for (auto &ch : modport->children) { - if (ch->type == AST_MODPORTMEMBER) { - std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output - found_in_modport = true; - wire->is_input = ch->is_input; - wire->is_output = ch->is_output; - break; - } - } - } - if (found_in_modport) { - new_ast->children.push_back(wire); - } - else { // If not found in modport, do not create port - delete wire; - } - } - else { // If no modport, set inout - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); - } - } + AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport + // Iterate over all wires in the interface and add them to the module: + explode_interface_port(new_ast, intfmodule, name_port, modport); } + break; } } } } } - // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; @@ -1267,47 +1290,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictast; - for (auto &ch : ast_node_of_interface->children) { - if (ch->type == AST_MODPORT) { - if (ch->str == interface_modport) { // Modport found - modport = ch; - } - } - } + modport = find_modport(ast_node_of_interface, interface_modport); } // Iterate over all wires in the interface and add them to the module: - for (auto &wire_it : intfmodule->wires_){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); - std::string origname = log_id(wire_it.first); - std::string newname = intfname + "." + origname; - wire->str = newname; - if (modport != NULL) { - bool found_in_modport = false; - // Search for the current wire in the wire list for the current modport - for (auto &ch : modport->children) { - if (ch->type == AST_MODPORTMEMBER) { - std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output - found_in_modport = true; - wire->is_input = ch->is_input; - wire->is_output = ch->is_output; - break; - } - } - } - if (found_in_modport) { - new_ast->children.push_back(wire); - } - else { // If not found in modport, do not create port - delete wire; - } - } - else { // If no modport, set inout - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); - } - } + explode_interface_port(new_ast, intfmodule, intfname, modport); } design->add(process_module(new_ast, false)); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 8187b1ac6..08f91c9c3 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -308,6 +308,11 @@ namespace AST // call a DPI function AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector &args); + + // Helper functions related to handling SystemVerilog interfaces + std::pair split_modport_from_type(std::string name_type); + AstNode * find_modport(AstNode *intf, std::string name); + void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport); } namespace AST_INTERNAL diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 32b9af6e9..8a6849faa 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -870,27 +870,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (children.size() > 0) { for(size_t i=0; itype == AST_INTERFACEPORTTYPE) { - std::string name_type = children[i]->str; - size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - // Separate the interface instance name from any modports: - if (ndots == 0) { // Does not have modport - wire->attributes["\\interface_type"] = name_type; - } - else { - std::stringstream name_type_stream(name_type); - std::string segment; - std::vector seglist; - while(std::getline(name_type_stream, segment, '.')) { - seglist.push_back(segment); - } - if (ndots == 1) { // Has modport - wire->attributes["\\interface_type"] = seglist[0]; - wire->attributes["\\interface_modport"] = seglist[1]; - } - else { // Erroneous port type - log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); - } - } + std::pair res = AST::split_modport_from_type(children[i]->str); + wire->attributes["\\interface_type"] = res.first; + if (res.second != "") + wire->attributes["\\interface_modport"] = res.second; break; } } -- cgit v1.2.3 From 23b69ca32b2ef93fc4b3f724099bfecdee0af869 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Oct 2018 23:48:53 +0200 Subject: Improve read_verilog range out of bounds warning Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 8a6849faa..59c309665 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1083,8 +1083,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", str.c_str()); else - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n", - str.c_str(), chunk.width); + log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { if (chunk.width + chunk.offset > source_width) { @@ -1097,11 +1097,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", - str.c_str(), add_undef_bits_lsb); + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", - str.c_str(), add_undef_bits_msb); + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } } -- cgit v1.2.3 From 536ae16c3abcf3fef1dd14df8733bf51fa1bce1a Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 25 Oct 2018 02:37:56 +0300 Subject: Rename the generic "Syntax error" message from the Verilog/SystemVerilog parser into unique, meaningful info on the error. Also add 13 compilation examples that triggers each of these messages. --- frontends/verilog/verilog_parser.y | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4dbe028a0..f8eee5d22 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -305,7 +305,7 @@ module_arg_opt_assignment: else ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); } else - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value."); } | /* empty */; @@ -672,7 +672,7 @@ task_func_port: astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { if (astbuf2) { - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)"); } else { astbuf2 = new AstNode(AST_RANGE); astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); @@ -680,7 +680,7 @@ task_func_port: } } if (astbuf2 && astbuf2->children.size() != 2) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("task/function argument range must be of the form: [:], [+:], or [-:]"); } wire_name | wire_name; task_func_body: @@ -883,7 +883,7 @@ param_signed: param_integer: TOK_INTEGER { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Internal error in param_integer - should not happen?"); astbuf1->children.push_back(new AstNode(AST_RANGE)); astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true)); astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); @@ -893,7 +893,7 @@ param_integer: param_real: TOK_REAL { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real."); astbuf1->children.push_back(new AstNode(AST_REALVALUE)); } | /* empty */; @@ -901,7 +901,7 @@ param_range: range { if ($1 != NULL) { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/real parameters should not have a range."); astbuf1->children.push_back($1); } }; @@ -930,7 +930,7 @@ single_param_decl: AstNode *node; if (astbuf1 == nullptr) { if (!sv_mode) - frontend_verilog_yyerror("syntax error"); + frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword"); node = new AstNode(AST_PARAMETER); node->children.push_back(AstNode::mkconst_int(0, true)); } else { @@ -966,7 +966,7 @@ wire_decl: astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { if (astbuf2) { - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); } else { astbuf2 = new AstNode(AST_RANGE); astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); @@ -974,7 +974,7 @@ wire_decl: } } if (astbuf2 && astbuf2->children.size() != 2) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); } wire_name_list { delete astbuf1; if (astbuf2 != NULL) @@ -1068,7 +1068,7 @@ wire_name_and_opt_assign: wire_name: TOK_ID range_or_multirange { if (astbuf1 == nullptr) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node."); AstNode *node = astbuf1->clone(); node->str = *$1; append_attr_clone(node, albuf); @@ -1076,7 +1076,7 @@ wire_name: node->children.push_back(astbuf2->clone()); if ($2 != NULL) { if (node->is_input || node->is_output) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); if (!astbuf2) { AstNode *rng = new AstNode(AST_RANGE); rng->children.push_back(AstNode::mkconst_int(0, true)); @@ -1478,7 +1478,7 @@ behavioral_stmt: node->str = *$3; } behavioral_stmt_list TOK_END opt_label { if ($3 != NULL && $7 != NULL && *$3 != *$7) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Begin label (%s) and end label (%s) doesn't match.", $3->c_str()+1, $7->c_str()+1); if ($3 != NULL) delete $3; if ($7 != NULL) @@ -1794,7 +1794,7 @@ basic_expr: } | '(' expr ')' TOK_CONSTVAL { if ($4->substr(0, 1) != "'") - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); AstNode *bits = $2; AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if (val == NULL) @@ -1804,7 +1804,7 @@ basic_expr: } | hierarchical_id TOK_CONSTVAL { if ($2->substr(0, 1) != "'") - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); AstNode *bits = new AstNode(AST_IDENTIFIER); bits->str = *$1; AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); -- cgit v1.2.3 From 5ab58d49308a670178a404e6e11bd8758f33c16d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Oct 2018 13:20:00 +0200 Subject: Fix minor typo in error message Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index f8eee5d22..1fe08903c 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1478,7 +1478,7 @@ behavioral_stmt: node->str = *$3; } behavioral_stmt_list TOK_END opt_label { if ($3 != NULL && $7 != NULL && *$3 != *$7) - frontend_verilog_yyerror("Begin label (%s) and end label (%s) doesn't match.", $3->c_str()+1, $7->c_str()+1); + frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1); if ($3 != NULL) delete $3; if ($7 != NULL) -- cgit v1.2.3 From d86ea6badd1911064138c32fc8e65934f923f90e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Nov 2018 15:25:24 +0100 Subject: Do not generate "reg assigned in a continuous assignment" warnings for "rand reg" Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e56a62563..fcadd329a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); - if (type == AST_ASSIGN && children[0]->id2ast->is_reg) - log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { + bool is_rand_reg = false; + if (children[1]->type == AST_FCALL) { + if (children[1]->str == "\\$anyconst") + is_rand_reg = true; + if (children[1]->str == "\\$anyseq") + is_rand_reg = true; + if (children[1]->str == "\\$allconst") + is_rand_reg = true; + if (children[1]->str == "\\$allseq") + is_rand_reg = true; + } + if (!is_rand_reg) + log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + } children[0]->was_checked = true; } break; -- cgit v1.2.3 From 39f891aebce87b4a6124c2f7dc5b6b2d04ec2899 Mon Sep 17 00:00:00 2001 From: ZipCPU Date: Sat, 3 Nov 2018 13:39:32 -0400 Subject: Make and dependent upon LSB only --- frontends/ast/simplify.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index fcadd329a..9688b77bc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1874,10 +1874,16 @@ skip_dynamic_range_lvalue_expansion:; newNode = new AstNode(AST_NE, past, present); else if (str == "\\$rose") - newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_LOGIC_NOT, + new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), + new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); else if (str == "\\$fell") - newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present)); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), + new AstNode(AST_LOGIC_NOT, + new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); else log_abort(); -- cgit v1.2.3 From 64e0582c292ca1f3a64c01d9a1faa96ef2f74588 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Nov 2018 10:19:32 +0100 Subject: Various indenting fixes in AST front-end (mostly space vs tab issues) Signed-off-by: Clifford Wolf --- frontends/ast/ast.cc | 9 ++--- frontends/ast/genrtlil.cc | 88 ++++++++++++++++++----------------------------- frontends/ast/simplify.cc | 71 ++++++++++++++++++-------------------- 3 files changed, 69 insertions(+), 99 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index cc275959a..2c1561552 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -172,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) AstNode *attr = attributes.at(id); if (attr->type != AST_CONSTANT) - log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", - id.c_str()); + log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str()); return attr->integer != 0; } @@ -969,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { @@ -1061,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump if (design->has((*it)->str)) { RTLIL::Module *existing_mod = design->module((*it)->str); if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { - log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", - (*it)->str.c_str()); + log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str()); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s:%d.\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 59c309665..9531dd356 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi if (gen_attributes) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s if (that != NULL) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); sw->attributes[attr.first] = attr.second->asAttrConst(); } @@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; delete left_at_zero_ast; delete right_at_zero_ast; @@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width_hint = max(width_hint, int(children[0]->asInt(true))); } break; @@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun default: for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); - log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", - type2str(type).c_str()); + log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); } if (*found_real) @@ -892,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { if (current_module->wires_.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str()); if (!range_valid) - log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", - str.c_str()); + log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str()); log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); @@ -910,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -920,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { if (current_module->memories.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str()); log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); if (!children[0]->range_valid || !children[1]->range_valid) - log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", - str.c_str()); + log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str()); RTLIL::Memory *memory = new RTLIL::Memory; memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -946,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); memory->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -966,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - realvalue, log_signal(sig)); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; } @@ -994,8 +980,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) - log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", - str.c_str()); + log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str()); chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } @@ -1010,13 +995,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) is_interface = true; } else { - log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); } if (id2ast->type == AST_MEMORY) - log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them @@ -1051,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); @@ -1081,7 +1063,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", - str.c_str()); + str.c_str()); else log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); @@ -1098,10 +1080,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (add_undef_bits_lsb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } } @@ -1436,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -1459,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_right.append(right[i]); } log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" - " old assignment: %s = %s\n new assignment: %s = %s.\n", - log_signal(left), log_signal(right), - log_signal(new_left), log_signal(new_right)); + " old assignment: %s = %s\n new assignment: %s = %s.\n", + log_signal(left), log_signal(right), + log_signal(new_left), log_signal(new_right)); left = new_left; right = new_right; } @@ -1494,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", - log_id(cell), log_id(paraname), child->children[0]->realvalue); + log_id(cell), log_id(paraname), child->children[0]->realvalue); auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); strnode->cloneInto(child->children[0]); delete strnode; } if (child->children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", - log_id(cell), log_id(paraname)); + log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); continue; } @@ -1522,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1551,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(children) > 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", - RTLIL::unescape_id(str).c_str(), GetSize(children)); + RTLIL::unescape_id(str).c_str(), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width = children[0]->asInt(true); } if (width <= 0) - log_file_error(filename, linenum, "Failed to detect width of %s!\n", - RTLIL::unescape_id(str).c_str()); + log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str()); Cell *cell = current_module->addCell(myid, str.substr(1)); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1589,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); type_name = type2str(type); - log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", - type_name.c_str()); + log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); } return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9688b77bc..bb4c9735d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int nargs = GetSize(children); if (nargs < 1) log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", - str.c_str(), int(children.size())); + str.c_str(), int(children.size())); // First argument is the format string AstNode *node_string = children[0]; @@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case 'X': if (next_arg >= GetSize(children)) log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", - cformat, str.c_str()); + cformat, str.c_str()); node_arg = children[next_arg++]; while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -745,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (current_scope.at(modname)->type != AST_CELL) log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", - RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); + RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); paraset->str = paramname; @@ -893,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - children[0]->realvalue, log_signal(constvalue)); + children[0]->realvalue, log_signal(constvalue)); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); did_something = true; @@ -1312,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PRIMITIVE) { if (children.size() < 2) - log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str()); std::vector children_list; for (auto child : children) { @@ -1328,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) - log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str()); std::vector z_const(1, RTLIL::State::Sz); @@ -1416,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } did_something = true; @@ -1788,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) != 1 && GetSize(children) != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); if (GetSize(children) == 2) { @@ -1857,11 +1854,11 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); AstNode *present = children.at(0)->clone(); AstNode *past = clone(); @@ -1875,15 +1872,13 @@ skip_dynamic_range_lvalue_expansion:; else if (str == "\\$rose") newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_LOGIC_NOT, - new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); else if (str == "\\$fell") newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), - new AstNode(AST_LOGIC_NOT, - new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); + new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); else log_abort(); @@ -1901,7 +1896,7 @@ skip_dynamic_range_lvalue_expansion:; { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -1926,11 +1921,11 @@ skip_dynamic_range_lvalue_expansion:; { if (str == "\\$bits" && children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (str == "\\$size" && children.size() != 1 && children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); int dim = 1; if (str == "\\$size" && children.size() == 2) { @@ -2004,18 +1999,18 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } else { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[0]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2026,7 +2021,7 @@ skip_dynamic_range_lvalue_expansion:; while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[1]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2114,7 +2109,7 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) < 2 || GetSize(children) > 4) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -3278,12 +3273,12 @@ void AstNode::replace_variables(std::map &varia if (!children.empty()) { if (children.size() != 1 || children.at(0)->type != AST_RANGE) log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } if (!children.at(0)->range_valid) log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); offset = min(children.at(0)->range_left, children.at(0)->range_right); width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } @@ -3323,7 +3318,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (child->simplify(true, false, false, 1, -1, false, true)) { } if (!child->range_valid) log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", - child->str.c_str(), fcall->filename.c_str(), fcall->linenum); + child->str.c_str(), fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; @@ -3367,15 +3362,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (stmt->children.at(1)->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); @@ -3383,7 +3378,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) AstNode *range = stmt->children.at(0)->children.at(0); if (!range->range_valid) log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -3415,7 +3410,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -3436,7 +3431,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (num->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -3474,7 +3469,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); delete cond; @@ -3504,7 +3499,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); log_abort(); } -- cgit v1.2.3 From 36ea98385f30107369479d2e682c544863c4f1af Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Nov 2018 15:57:17 +0100 Subject: Add warning for SV "restrict" without "property" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 1fe08903c..5ab1b62df 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -125,7 +125,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label tok_prim_wrapper hierarchical_id -%type opt_signed unique_case_attr +%type opt_signed opt_property unique_case_attr %type attr case_attr // operator precedence from low to high @@ -1320,7 +1320,12 @@ opt_label: }; opt_property: - TOK_PROPERTY | /* empty */; + TOK_PROPERTY { + $$ = true; + } | + /* empty */ { + $$ = false; + }; opt_stmt_label: TOK_ID ':' | /* empty */; @@ -1399,12 +1404,16 @@ assert: delete $5; else ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); } | opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) delete $6; else ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); }; assert_property: -- cgit v1.2.3 From 719e29404a74db8f994c9c3dc0d6b6e8d7f114a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 5 Nov 2018 12:33:21 +0100 Subject: Allow square brackets in liberty identifiers Signed-off-by: Clifford Wolf --- frontends/liberty/liberty.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 66db43baf..4acfbf1cb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& int id_len = 0; while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') || - ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++; + ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || + expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++; if (id_len == 0) log_error("Expected identifier at `%s'.\n", expr); -- cgit v1.2.3 From 5387ccb041f4acafc96c7b3fcf8db04dddfb8ab5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Nov 2018 21:03:13 +0100 Subject: Set Verific flag vhdl_support_variable_slice=1 Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index dba3b0f0c..971f0b24a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1835,6 +1835,7 @@ struct VerificPass : public Pass { Message::RegisterCallBackMsg(msg_func); RuntimeFlags::SetVar("db_preserve_user_nets", 1); RuntimeFlags::SetVar("db_allow_external_nets", 1); + RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); -- cgit v1.2.3 From 86ce43999eaed10c3b9d141bb2f66bf98ad45eb6 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 24 Nov 2018 18:49:23 +0100 Subject: Make return value of $clog2 signed As per Verilog 2005 - 17.11.1. Fixes #708 Signed-off-by: Sylvain Munaut --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index bb4c9735d..55abe165f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1913,7 +1913,7 @@ skip_dynamic_range_lvalue_expansion:; if (arg_value.bits.at(i) == RTLIL::State::S1) result = i + 1; - newNode = mkconst_int(result, false); + newNode = mkconst_int(result, true); goto apply_newNode; } -- cgit v1.2.3 From 910d94b21214b78d841cfb32a724c4f0ea8b365d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Dec 2018 07:21:50 +0100 Subject: Verific updates Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 53 -------------------------------------------- 1 file changed, 53 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 971f0b24a..bc035c31a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2094,42 +2094,6 @@ struct VerificPass : public Pass { if (mode_all) { -#if 0 - log("Running veri_file::ElaborateAll().\n"); - if (!veri_file::ElaborateAll()) - log_cmd_error("Elaboration of Verilog modules failed.\n"); - - log("Running vhdl_file::ElaborateAll().\n"); - if (!vhdl_file::ElaborateAll()) - log_cmd_error("Elaboration of VHDL modules failed.\n"); - - Library *lib = Netlist::PresentDesign()->Owner()->Owner(); - - if (argidx == GetSize(args)) - { - MapIter iter; - char *iter_name; - Verific::Cell *iter_cell; - - FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) { - if (*iter_name != '$') - nl_todo.insert(iter_cell->GetFirstNetlist()); - } - } - else - { - for (; argidx < GetSize(args); argidx++) - { - Verific::Cell *cell = lib->GetCell(args[argidx].c_str()); - - if (cell == nullptr) - log_cmd_error("Module not found: %s\n", args[argidx].c_str()); - - nl_todo.insert(cell->GetFirstNetlist()); - cell->GetFirstNetlist()->SetPresentDesign(); - } - } -#else log("Running hier_tree::ElaborateAll().\n"); VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1); @@ -2146,28 +2110,12 @@ struct VerificPass : public Pass { FOREACH_ARRAY_ITEM(netlists, i, nl) nl_todo.insert(nl); delete netlists; -#endif } else { if (argidx == GetSize(args)) log_cmd_error("No top module specified.\n"); -#if 0 - for (; argidx < GetSize(args); argidx++) { - if (veri_file::GetModule(args[argidx].c_str())) { - log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str()); - if (!veri_file::Elaborate(args[argidx].c_str())) - log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); - nl_todo.insert(Netlist::PresentDesign()); - } else { - log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str()); - if (!vhdl_file::Elaborate(args[argidx].c_str())) - log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); - nl_todo.insert(Netlist::PresentDesign()); - } - } -#else Array veri_modules, vhdl_units; for (; argidx < GetSize(args); argidx++) { @@ -2199,7 +2147,6 @@ struct VerificPass : public Pass { FOREACH_ARRAY_ITEM(netlists, i, nl) nl_todo.insert(nl); delete netlists; -#endif } if (!verific_error_msg.empty()) -- cgit v1.2.3 From 58fb2ac818d07021b6929cb9ff14e13e993a231f Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 13 Dec 2018 18:47:05 +0100 Subject: verilog_parser: Properly handle recursion when processing attributes Fixes #737 Signed-off-by: Sylvain Munaut --- frontends/verilog/verilog_parser.y | 48 +++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5ab1b62df..51e112ed3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -35,6 +35,7 @@ %{ #include +#include #include #include "frontends/verilog/verilog_frontend.h" #include "kernel/log.h" @@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; std::map port_stubs; - std::map attr_list, default_attr_list; + std::map *attr_list, default_attr_list; + std::stack *> attr_list_stack; std::map *albuf; std::vector ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; @@ -175,15 +177,18 @@ design: attr: { - for (auto &it : attr_list) - delete it.second; - attr_list.clear(); + if (attr_list != nullptr) + attr_list_stack.push(attr_list); + attr_list = new std::map; for (auto &it : default_attr_list) - attr_list[it.first] = it.second->clone(); + (*attr_list)[it.first] = it.second->clone(); } attr_opt { - std::map *al = new std::map; - al->swap(attr_list); - $$ = al; + $$ = attr_list; + if (!attr_list_stack.empty()) { + attr_list = attr_list_stack.top(); + attr_list_stack.pop(); + } else + attr_list = nullptr; }; attr_opt: @@ -192,15 +197,20 @@ attr_opt: defattr: DEFATTR_BEGIN { + if (attr_list != nullptr) + attr_list_stack.push(attr_list); + attr_list = new std::map; for (auto &it : default_attr_list) delete it.second; default_attr_list.clear(); - for (auto &it : attr_list) - delete it.second; - attr_list.clear(); } opt_attr_list { - default_attr_list = attr_list; - attr_list.clear(); + attr_list->swap(default_attr_list); + delete attr_list; + if (!attr_list_stack.empty()) { + attr_list = attr_list_stack.top(); + attr_list_stack.pop(); + } else + attr_list = nullptr; } DEFATTR_END; opt_attr_list: @@ -212,15 +222,15 @@ attr_list: attr_assign: hierarchical_id { - if (attr_list.count(*$1) != 0) - delete attr_list[*$1]; - attr_list[*$1] = AstNode::mkconst_int(1, false); + if (attr_list->count(*$1) != 0) + delete (*attr_list)[*$1]; + (*attr_list)[*$1] = AstNode::mkconst_int(1, false); delete $1; } | hierarchical_id '=' expr { - if (attr_list.count(*$1) != 0) - delete attr_list[*$1]; - attr_list[*$1] = $3; + if (attr_list->count(*$1) != 0) + delete (*attr_list)[*$1]; + (*attr_list)[*$1] = $3; delete $1; }; -- cgit v1.2.3 From 4effb38e6d318e2e233bdfa9f2e0bb67e4998bf0 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 16 Dec 2018 17:50:36 +0000 Subject: read_ilang: allow slicing sigspecs. --- frontends/ilang/ilang_parser.y | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'frontends') diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index bfc062fec..b957ecd96 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -387,17 +387,13 @@ sigspec: $$ = new RTLIL::SigSpec(current_module->wires_[$1]); free($1); } | - TOK_ID '[' TOK_INT ']' { - if (current_module->wires_.count($1) == 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wires_[$1], $3); - free($1); + sigspec '[' TOK_INT ']' { + $$ = new RTLIL::SigSpec($1->extract($3)); + delete $1; } | - TOK_ID '[' TOK_INT ':' TOK_INT ']' { - if (current_module->wires_.count($1) == 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wires_[$1], $5, $3 - $5 + 1); - free($1); + sigspec '[' TOK_INT ':' TOK_INT ']' { + $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1)); + delete $1; } | '{' sigspec_list '}' { $$ = $2; -- cgit v1.2.3 From 3d671630e2bf78cd53ef1b678a1bbb63338cbcd2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 18 Dec 2018 16:01:22 +0100 Subject: Improve src tagging (using names and attrs) of cells and wires in verific front-end Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 258 ++++++++++++++++++++++++++----------------- frontends/verific/verific.h | 1 + 2 files changed, 160 insertions(+), 99 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index bc035c31a..61d9d593c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -130,6 +130,15 @@ bool is_blackbox(Netlist *nl) return false; } +RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) +{ + std::string s = stringf("$verific$%s", obj->Name()); + if (obj->Linefile()) + s += stringf("$%s:%d", Verific::LineFile::GetFileName(obj->Linefile()), Verific::LineFile::GetLineNo(obj->Linefile())); + s += stringf("$%d", autoidx++); + return s; +} + void VerificImporter::import_attributes(dict &attributes, DesignObj *obj) { MapIter mi; @@ -215,7 +224,7 @@ RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pooladdWire(NEW_ID); + dummy_wire = module->addWire(new_verific_id(inst)); else dummy_wire->width++; sig.append(RTLIL::SigSpec(dummy_wire, dummy_wire->width - 1)); @@ -231,8 +240,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr } if (inst->Type() == PRIM_NAND) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addAndGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + module->addAndGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput())); return true; } @@ -243,8 +252,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr } if (inst->Type() == PRIM_NOR) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addOrGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + module->addOrGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput())); return true; } @@ -284,16 +293,16 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr if (inst->Type() == PRIM_FADD) { RTLIL::SigSpec a = net_map_at(inst->GetInput1()), b = net_map_at(inst->GetInput2()), c = net_map_at(inst->GetCin()); - RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(NEW_ID); - RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); - RTLIL::SigSpec tmp1 = module->addWire(NEW_ID); - RTLIL::SigSpec tmp2 = module->addWire(NEW_ID); - RTLIL::SigSpec tmp3 = module->addWire(NEW_ID); - module->addXorGate(NEW_ID, a, b, tmp1); + RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(new_verific_id(inst)); + RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp1 = module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp2 = module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp3 = module->addWire(new_verific_id(inst)); + module->addXorGate(new_verific_id(inst), a, b, tmp1); module->addXorGate(inst_name, tmp1, c, y); - module->addAndGate(NEW_ID, tmp1, c, tmp2); - module->addAndGate(NEW_ID, a, b, tmp3); - module->addOrGate(NEW_ID, tmp2, tmp3, x); + module->addAndGate(new_verific_id(inst), tmp1, c, tmp2); + module->addAndGate(new_verific_id(inst), a, b, tmp3); + module->addOrGate(new_verific_id(inst), tmp2, tmp3, x); return true; } @@ -320,63 +329,78 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdString inst_name) { + RTLIL::Cell *cell = nullptr; + if (inst->Type() == PRIM_AND) { - module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_NAND) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addAnd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); - module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + cell = module->addAnd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + import_attributes(cell->attributes, inst); + cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_OR) { - module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_NOR) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addOr(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); - module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + cell = module->addOr(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + import_attributes(cell->attributes, inst); + cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_XOR) { - module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_XNOR) { - module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_INV) { - module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_MUX) { - module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + cell = module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_TRI) { - module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_FADD) { - RTLIL::SigSpec a_plus_b = module->addWire(NEW_ID, 2); - RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); + RTLIL::SigSpec a_plus_b = module->addWire(new_verific_id(inst), 2); + RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst)); if (inst->GetCout()) y.append(net_map_at(inst->GetCout())); - module->addAdd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); - module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); + cell = module->addAdd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); + import_attributes(cell->attributes, inst); + cell = module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); + import_attributes(cell->attributes, inst); return true; } @@ -387,24 +411,26 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr log_assert(clocking.body_net == nullptr); if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) - clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); else if (inst->GetSet()->IsGnd()) - clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0); + cell = clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0); else if (inst->GetReset()->IsGnd()) - clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1); + cell = clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1); else - clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), + cell = clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_DLATCHRS) { if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) - module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); else - module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), + cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } @@ -420,37 +446,45 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr if (inst->GetCout() != NULL) out.append(net_map_at(inst->GetCout())); if (inst->GetCin()->IsGnd()) { - module->addAdd(inst_name, IN1, IN2, out, SIGNED); + cell = module->addAdd(inst_name, IN1, IN2, out, SIGNED); + import_attributes(cell->attributes, inst); } else { - RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out)); - module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED); - module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst), GetSize(out)); + cell = module->addAdd(new_verific_id(inst), IN1, IN2, tmp, SIGNED); + import_attributes(cell->attributes, inst); + cell = module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); + import_attributes(cell->attributes, inst); } return true; } if (inst->Type() == OPER_MULTIPLIER) { - module->addMul(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMul(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_DIVIDER) { - module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_MODULO) { - module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REMAINDER) { - module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_SHIFT_LEFT) { - module->addShl(inst_name, IN1, IN2, OUT, false); + cell = module->addShl(inst_name, IN1, IN2, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -460,7 +494,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr for (unsigned i = 1; i < inst->OutputSize(); i++) { vec.append(RTLIL::State::S0); } - module->addShl(inst_name, vec, IN, OUT, false); + cell = module->addShl(inst_name, vec, IN, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -470,7 +505,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr for (unsigned i = 1; i < inst->OutputSize(); i++) { vec.append(RTLIL::State::S0); } - module->addShl(inst_name, vec, IN, OUT, false); + cell = module->addShl(inst_name, vec, IN, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -478,108 +514,127 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr Net *net_cin = inst->GetCin(); Net *net_a_msb = inst->GetInput1Bit(0); if (net_cin->IsGnd()) - module->addShr(inst_name, IN1, IN2, OUT, false); + cell = module->addShr(inst_name, IN1, IN2, OUT, false); else if (net_cin == net_a_msb) - module->addSshr(inst_name, IN1, IN2, OUT, true); + cell = module->addSshr(inst_name, IN1, IN2, OUT, true); else log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name()); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_AND) { - module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_OR) { - module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_XOR) { - module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_XNOR) { - module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_NOR) { - SigSpec t = module->ReduceOr(NEW_ID, IN, SIGNED); - module->addNot(inst_name, t, net_map_at(inst->GetOutput())); + SigSpec t = module->ReduceOr(new_verific_id(inst), IN, SIGNED); + cell = module->addNot(inst_name, t, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_LESSTHAN) { Net *net_cin = inst->GetCin(); if (net_cin->IsGnd()) - module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); else if (net_cin->IsPwr()) - module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); else log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name()); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_AND) { - module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_OR) { - module->addOr(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addOr(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_XOR) { - module->addXor(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addXor(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_XNOR) { - module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_BUF) { - module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); + cell = module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_INV) { - module->addNot(inst_name, IN, OUT, SIGNED); + cell = module->addNot(inst_name, IN, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_MINUS) { - module->addSub(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addSub(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_UMINUS) { - module->addNeg(inst_name, IN, OUT, SIGNED); + cell = module->addNeg(inst_name, IN, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_EQUAL) { - module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_NEQUAL) { - module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_MUX) { - module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); + cell = module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_NTO1MUX) { - module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); + cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } @@ -599,25 +654,29 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr padded_data.append(d); } - module->addShr(inst_name, padded_data, sel, out); + cell = module->addShr(inst_name, padded_data, sel, out); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_SELECTOR) { - module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); + cell = module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_SELECTOR) { SigSpec out = OUT; - module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); + cell = module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_TRI) { - module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); + cell = module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); + import_attributes(cell->attributes, inst); return true; } @@ -631,9 +690,10 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr RTLIL::SigSpec sig_reset = operatorInport(inst, "reset"); if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool()) - clocking.addDff(inst_name, IN, OUT); + cell = clocking.addDff(inst_name, IN, OUT); else - clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); + cell = clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); + import_attributes(cell->attributes, inst); return true; } @@ -862,7 +922,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se ascii_initdata++; } if (initval_valid) { - RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); + RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit"); cell->parameters["\\WORDS"] = 1; if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound()) cell->setPort("\\ADDR", word_idx); @@ -925,7 +985,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (net->Bus()) continue; - RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : NEW_ID); + RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net)); if (verific_verbose) log(" importing net %s as %s.\n", net->Name(), log_id(wire_name)); @@ -949,7 +1009,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (found_new_net) { - RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : NEW_ID); + RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus)); if (verific_verbose) log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name)); @@ -1025,16 +1085,16 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } if (GetSize(anyconst_sig)) - module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig))); + module->connect(anyconst_sig, module->Anyconst(new_verific_id(netbus), GetSize(anyconst_sig))); if (GetSize(anyseq_sig)) - module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig))); + module->connect(anyseq_sig, module->Anyseq(new_verific_id(netbus), GetSize(anyseq_sig))); if (GetSize(allconst_sig)) - module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig))); + module->connect(allconst_sig, module->Allconst(new_verific_id(netbus), GetSize(allconst_sig))); if (GetSize(allseq_sig)) - module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig))); + module->connect(allseq_sig, module->Allseq(new_verific_id(netbus), GetSize(allseq_sig))); } for (auto it : init_nets) @@ -1058,10 +1118,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } for (auto net : anyconst_nets) - module->connect(net_map_at(net), module->Anyconst(NEW_ID)); + module->connect(net_map_at(net), module->Anyconst(new_verific_id(net))); for (auto net : anyseq_nets) - module->connect(net_map_at(net), module->Anyseq(NEW_ID)); + module->connect(net_map_at(net), module->Anyseq(new_verific_id(net))); pool sva_asserts; pool sva_assumes; @@ -1072,7 +1132,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst) { - RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : NEW_ID); + RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst)); if (verific_verbose) log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name)); @@ -1196,7 +1256,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_assert(inst->Input1Size() == inst->OutputSize()); SigSpec sig_d, sig_q, sig_o; - sig_q = module->addWire(NEW_ID, inst->Input1Size()); + sig_q = module->addWire(new_verific_id(inst), inst->Input1Size()); for (int i = int(inst->Input1Size())-1; i >= 0; i--){ sig_d.append(net_map_at(inst->GetInput1Bit(i))); @@ -1210,8 +1270,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_signal(sig_d), log_signal(sig_q), log_signal(sig_o)); } - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addXnor(NEW_ID, sig_d, sig_q, sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o); if (!mode_keep) continue; @@ -1225,7 +1285,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se SigSpec sig_d = net_map_at(inst->GetInput1()); SigSpec sig_o = net_map_at(inst->GetOutput()); - SigSpec sig_q = module->addWire(NEW_ID); + SigSpec sig_q = module->addWire(new_verific_id(inst)); if (verific_verbose) { log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", @@ -1234,8 +1294,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_signal(sig_d), log_signal(sig_q), log_signal(sig_o)); } - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addXnor(NEW_ID, sig_d, sig_q, sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o); if (!mode_keep) continue; @@ -1254,7 +1314,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); - past_ffs.insert(clocking.addDff(NEW_ID, sig_d, sig_q)); + past_ffs.insert(clocking.addDff(new_verific_id(inst), sig_d, sig_q)); if (!mode_keep) continue; @@ -1268,14 +1328,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se SigBit sig_d = net_map_at(inst->GetInput1()); SigBit sig_o = net_map_at(inst->GetOutput()); - SigBit sig_q = module->addWire(NEW_ID); + SigBit sig_q = module->addWire(new_verific_id(inst)); if (verific_verbose) log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addEq(NEW_ID, {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addEq(new_verific_id(inst), {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o); if (!mode_keep) continue; @@ -1298,9 +1358,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se Cell *cell = nullptr; if (assume_attr != nullptr && !strcmp(assume_attr, "1")) - cell = module->addAssume(NEW_ID, cond, State::S1); + cell = module->addAssume(new_verific_id(inst), cond, State::S1); else - cell = module->addAssert(NEW_ID, cond, State::S1); + cell = module->addAssert(new_verific_id(inst), cond, State::S1); import_attributes(cell->attributes, inst); continue; @@ -1342,7 +1402,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se IdString port_name_id = RTLIL::escape_id(port_name); auto &sigvec = cell_port_conns[port_name_id]; if (GetSize(sigvec) <= port_offset) { - SigSpec zwires = module->addWire(NEW_ID, port_offset+1-GetSize(sigvec)); + SigSpec zwires = module->addWire(new_verific_id(inst), port_offset+1-GetSize(sigvec)); for (auto bit : zwires) sigvec.push_back(bit); } diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h index 334a436af..b331dd4b9 100644 --- a/frontends/verific/verific.h +++ b/frontends/verific/verific.h @@ -78,6 +78,7 @@ struct VerificImporter RTLIL::SigBit net_map_at(Verific::Net *net); + RTLIL::IdString new_verific_id(Verific::DesignObj *obj); void import_attributes(dict &attributes, Verific::DesignObj *obj); RTLIL::SigSpec operatorInput(Verific::Instance *inst); -- cgit v1.2.3 From fdf7c421810e8718f7ee312ddd3cfdbfb65aa2ce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 18 Dec 2018 17:49:38 +0100 Subject: Fix segfault in AST simplify (as proposed by Dan Gisselquist) Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55abe165f..83714f897 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1810,6 +1810,11 @@ skip_dynamic_range_lvalue_expansion:; log_assert(block != nullptr); + if (num_steps == 0) { + newNode = children[0]->clone(); + goto apply_newNode; + } + int myidx = autoidx++; AstNode *outreg = nullptr; -- cgit v1.2.3