From 9df04d7e7520884bfc40004bb131cfdb474061c7 Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Wed, 22 May 2019 14:22:42 +0200 Subject: make lexer/parser aware of wand/wor net types --- frontends/ast/ast.h | 2 +- frontends/verilog/verilog_lexer.l | 2 ++ frontends/verilog/verilog_parser.y | 8 +++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 281cbe086..6c19dc7e6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -173,7 +173,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector bits; - bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked; int port_id, range_left, range_right; uint32_t integer; double realvalue; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 142d05d45..c763841c2 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -218,6 +218,8 @@ YOSYS_NAMESPACE_END "output" { return TOK_OUTPUT; } "inout" { return TOK_INOUT; } "wire" { return TOK_WIRE; } +"wor" { return TOK_WOR; } +"wand" { return TOK_WAND; } "reg" { return TOK_REG; } "integer" { return TOK_INTEGER; } "signed" { return TOK_SIGNED; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 132468f0c..8800705ac 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -139,7 +139,7 @@ struct specify_rise_fall { %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 TOK_VAR -%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC +%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR 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 %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC @@ -485,6 +485,12 @@ wire_type_token_io: wire_type_token: TOK_WIRE { } | + TOK_WOR { + astbuf3->is_wor = true; + } | + TOK_WAND { + astbuf3->is_wand = true; + } | TOK_REG { astbuf3->is_reg = true; } | -- cgit v1.2.3 From 075a48d3fa69324d5b2700779a686fa46a69adb2 Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Thu, 23 May 2019 10:16:41 +0200 Subject: implementation for assignments working --- frontends/ast/ast.cc | 3 ++ frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 93 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 5623541b2..9c360efb6 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -51,6 +51,7 @@ namespace AST_INTERNAL { std::map current_scope; const dict *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; + std::map wire_logic_map; AstNode *current_always, *current_top_block, *current_block, *current_block_child; AstModule *current_module; bool current_always_clocked; @@ -940,6 +941,8 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } + wire_logic_map = std::map(); + if (!defer) { bool blackbox_module = flag_lib; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 6c19dc7e6..7b1744b2e 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -327,6 +327,7 @@ namespace AST_INTERNAL extern std::map current_scope; extern const dict *genRTLIL_subst_ptr; extern RTLIL::SigSpec ignoreThisSignalsInInitial; + extern std::map wire_logic_map; extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; extern bool current_always_clocked; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 379fed641..c60f8f5cc 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -163,6 +163,42 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const return wire; } +// helper function for creating RTLIL code for wand/wor declarations +static void wandwor2rtlil(AstNode *that, RTLIL::Wire *output_wire, bool gen_attributes = true) +{ + std::string type; + + if (that->is_wand) { + type = "$reduce_and"; + } else if (that->is_wor) { + type = "$reduce_or"; + } else { + log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n"); + } + + std::stringstream sstr; + sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); + + RTLIL::Cell *cell = current_module->addCell(sstr.str(), type); + cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); + + 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()); + cell->attributes[attr.first] = attr.second->asAttrConst(); + } + + cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); + cell->parameters["\\A_WIDTH"] = RTLIL::Const(0); + cell->setPort("\\A", RTLIL::SigSpec()); + + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + cell->setPort("\\Y", output_wire); + + wire_logic_map[output_wire] = cell; +} + // helper class for converting AST always nodes to RTLIL processes struct AST_INTERNAL::ProcessGenerator { @@ -919,6 +955,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } + + if (is_wand || is_wor) { + if (wire->width > 1) + log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n"); + wandwor2rtlil(this, wire); + } + } break; @@ -1450,23 +1493,45 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // add entries to current_module->connections for assignments (outside of always blocks) case AST_ASSIGN: { + bool left_had_const = false; RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size()); - if (left.has_const()) { - RTLIL::SigSpec new_left, new_right; - for (int i = 0; i < GetSize(left); i++) - if (left[i].wire) { - new_left.append(left[i]); - 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)); - left = new_left; - right = new_right; - } + + RTLIL::SigSpec new_left, new_right; + for (int i = 0; i < GetSize(left); i++) + if (left[i].wire) { + std::map::iterator iter = wire_logic_map.find(left[i].wire); + if (iter == wire_logic_map.end()) + { + new_left.append(left[i]); + } else { + RTLIL::Cell *reduce_cell = iter->second; + RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); + int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); + log_warning("%d\n", reduce_cell_in.size()); + + RTLIL::Wire *new_reduce_input = current_module->addWire( + stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); + new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + reduce_cell_in.append(new_reduce_input); + reduce_cell->setPort("\\A", reduce_cell_in); + reduce_cell->fixup_parameters(); + new_left.append(new_reduce_input); + } + new_right.append(right[i]); + } else { + left_had_const = true; + } + + left = new_left; + right = new_right; current_module->connect(RTLIL::SigSig(left, right)); + + if (left_had_const) + 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)); } break; -- cgit v1.2.3 From fd003e0e975be3c7f357fb151fd1c83a8ea9b0ae Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Thu, 23 May 2019 13:42:30 +0200 Subject: fix indentation across files --- frontends/ast/ast.cc | 6 +- frontends/ast/ast.h | 2 +- frontends/ast/genrtlil.cc | 134 +++++++++++++++++++++---------------- frontends/verilog/verilog_parser.y | 4 +- 4 files changed, 83 insertions(+), 63 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 9c360efb6..963152588 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -51,7 +51,7 @@ namespace AST_INTERNAL { std::map current_scope; const dict *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; - std::map wire_logic_map; + std::map wire_logic_map; AstNode *current_always, *current_top_block, *current_block, *current_block_child; AstModule *current_module; bool current_always_clocked; @@ -195,6 +195,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch is_logic = false; is_signed = false; is_string = false; + is_wand = false; + is_wor = false; was_checked = false; range_valid = false; range_swapped = false; @@ -941,7 +943,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } - wire_logic_map = std::map(); + wire_logic_map = std::map(); if (!defer) { diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 7b1744b2e..c2a7744c4 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -327,7 +327,7 @@ namespace AST_INTERNAL extern std::map current_scope; extern const dict *genRTLIL_subst_ptr; extern RTLIL::SigSpec ignoreThisSignalsInInitial; - extern std::map wire_logic_map; + extern std::map wire_logic_map; extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; extern bool current_always_clocked; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index c60f8f5cc..7a6a2be6b 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -166,37 +166,37 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const // helper function for creating RTLIL code for wand/wor declarations static void wandwor2rtlil(AstNode *that, RTLIL::Wire *output_wire, bool gen_attributes = true) { - std::string type; - - if (that->is_wand) { - type = "$reduce_and"; - } else if (that->is_wor) { - type = "$reduce_or"; - } else { - log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n"); - } + std::string type; + + if (that->is_wand) { + type = "$reduce_and"; + } else if (that->is_wor) { + type = "$reduce_or"; + } else { + log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n"); + } std::stringstream sstr; sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); RTLIL::Cell *cell = current_module->addCell(sstr.str(), type); cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); - + 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()); cell->attributes[attr.first] = attr.second->asAttrConst(); } - + cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); cell->parameters["\\A_WIDTH"] = RTLIL::Const(0); cell->setPort("\\A", RTLIL::SigSpec()); - + cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); cell->setPort("\\Y", output_wire); - - wire_logic_map[output_wire] = cell; + + wire_logic_map[output_wire] = cell; } // helper class for converting AST always nodes to RTLIL processes @@ -956,12 +956,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->attributes[attr.first] = attr.second->asAttrConst(); } - if (is_wand || is_wor) { - if (wire->width > 1) - log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n"); - wandwor2rtlil(this, wire); - } - + if (is_wand || is_wor) { + if (wire->width > 1) + log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n"); + wandwor2rtlil(this, wire); + } } break; @@ -1493,45 +1492,44 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // add entries to current_module->connections for assignments (outside of always blocks) case AST_ASSIGN: { - bool left_had_const = false; + bool left_had_const = false; RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size()); - RTLIL::SigSpec new_left, new_right; - for (int i = 0; i < GetSize(left); i++) - if (left[i].wire) { - std::map::iterator iter = wire_logic_map.find(left[i].wire); - if (iter == wire_logic_map.end()) - { - new_left.append(left[i]); - } else { - RTLIL::Cell *reduce_cell = iter->second; - RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); - int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); - log_warning("%d\n", reduce_cell_in.size()); - - RTLIL::Wire *new_reduce_input = current_module->addWire( - stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); - new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); - reduce_cell_in.append(new_reduce_input); - reduce_cell->setPort("\\A", reduce_cell_in); - reduce_cell->fixup_parameters(); - new_left.append(new_reduce_input); - } - new_right.append(right[i]); - } else { - left_had_const = true; - } - - left = new_left; - right = new_right; + RTLIL::SigSpec new_left, new_right; + for (int i = 0; i < GetSize(left); i++) + if (left[i].wire) { + std::map::iterator iter = wire_logic_map.find(left[i].wire); + if (iter == wire_logic_map.end()) + { + new_left.append(left[i]); + } else { + RTLIL::Cell *reduce_cell = iter->second; + RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); + int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); + + RTLIL::Wire *new_reduce_input = current_module->addWire( + stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); + new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + reduce_cell_in.append(new_reduce_input); + reduce_cell->setPort("\\A", reduce_cell_in); + reduce_cell->fixup_parameters(); + new_left.append(new_reduce_input); + } + new_right.append(right[i]); + } else { + left_had_const = true; + } + + left = new_left; + right = new_right; current_module->connect(RTLIL::SigSig(left, right)); - - if (left_had_const) - 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)); + + if (left_had_const) + 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)); } break; @@ -1576,14 +1574,34 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (child->type == AST_ARGUMENT) { RTLIL::SigSpec sig; - if (child->children.size() > 0) + RTLIL::SigSpec new_sig; + if (child->children.size() > 0) { sig = child->children[0]->genRTLIL(); + for (int i = 0; i < GetSize(sig); i++) { + std::map::iterator iter = wire_logic_map.find(sig[i].wire); + if (iter == wire_logic_map.end()) { + new_sig.append(sig[i]); + } else { + RTLIL::Cell *reduce_cell = iter->second; + RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); + int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); + + RTLIL::Wire *new_reduce_input = current_module->addWire( + stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); + new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + reduce_cell_in.append(new_reduce_input); + reduce_cell->setPort("\\A", reduce_cell_in); + reduce_cell->fixup_parameters(); + new_sig.append(new_reduce_input); + } + } + } if (child->str.size() == 0) { char buf[100]; snprintf(buf, 100, "$%d", ++port_counter); - cell->setPort(buf, sig); + cell->setPort(buf, new_sig); } else { - cell->setPort(child->str, sig); + cell->setPort(child->str, new_sig); } continue; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8800705ac..8244a8f44 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -486,10 +486,10 @@ wire_type_token: TOK_WIRE { } | TOK_WOR { - astbuf3->is_wor = true; + astbuf3->is_wor = true; } | TOK_WAND { - astbuf3->is_wand = true; + astbuf3->is_wand = true; } | TOK_REG { astbuf3->is_reg = true; -- cgit v1.2.3 From c2caf85f7cbcbea4240b56a134e4c3e74189c62d Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Thu, 23 May 2019 13:42:42 +0200 Subject: add simple test case for wand/wor --- tests/various/wandwor.v | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/various/wandwor.v diff --git a/tests/various/wandwor.v b/tests/various/wandwor.v new file mode 100644 index 000000000..824f89683 --- /dev/null +++ b/tests/various/wandwor.v @@ -0,0 +1,35 @@ +module a(Q); + output wire Q; + + assign Q = 0; +endmodule + +module b(D); + input wire D; +endmodule + +module c; + wor D; + assign D = 1; + assign D = 0; + assign D = 1; + assign D = 0; + + + wand E; + wire E_wire = E; + + genvar i; + for (i = 0; i < 3; i = i + 1) + begin :genloop + a a_inst ( + .Q(E) + ); + + b b_inst ( + .D(E_wire) + ); + end + +endmodule + -- cgit v1.2.3 From 85de9d26c1118a83b01f62c450acecf3fd9077d6 Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Thu, 23 May 2019 17:55:56 +0200 Subject: fix assignment of non-wires --- frontends/ast/genrtlil.cc | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 7a6a2be6b..047b0a81b 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1500,8 +1500,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (int i = 0; i < GetSize(left); i++) if (left[i].wire) { std::map::iterator iter = wire_logic_map.find(left[i].wire); - if (iter == wire_logic_map.end()) - { + if (iter == wire_logic_map.end()) { new_left.append(left[i]); } else { RTLIL::Cell *reduce_cell = iter->second; @@ -1578,21 +1577,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (child->children.size() > 0) { sig = child->children[0]->genRTLIL(); for (int i = 0; i < GetSize(sig); i++) { - std::map::iterator iter = wire_logic_map.find(sig[i].wire); - if (iter == wire_logic_map.end()) { - new_sig.append(sig[i]); + if (sig[i].wire) { + std::map::iterator iter = wire_logic_map.find(sig[i].wire); + if (iter == wire_logic_map.end()) { + new_sig.append(sig[i]); + } else { + RTLIL::Cell *reduce_cell = iter->second; + RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); + int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); + + RTLIL::Wire *new_reduce_input = current_module->addWire( + stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); + new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + reduce_cell_in.append(new_reduce_input); + reduce_cell->setPort("\\A", reduce_cell_in); + reduce_cell->fixup_parameters(); + new_sig.append(new_reduce_input); + } } else { - RTLIL::Cell *reduce_cell = iter->second; - RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); - int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); - - RTLIL::Wire *new_reduce_input = current_module->addWire( - stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); - new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); - reduce_cell_in.append(new_reduce_input); - reduce_cell->setPort("\\A", reduce_cell_in); - reduce_cell->fixup_parameters(); - new_sig.append(new_reduce_input); + new_sig.append(sig[i]); } } } -- cgit v1.2.3 From ed625a3102233bf9c9af17e56575dc4a0ed8946c Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:00:22 +0200 Subject: move wand/wor resolution into hierarchy pass --- frontends/ast/genrtlil.cc | 111 ++++++------------------------------------ passes/hierarchy/hierarchy.cc | 78 ++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 98 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 047b0a81b..8094304e5 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -163,42 +163,6 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const return wire; } -// helper function for creating RTLIL code for wand/wor declarations -static void wandwor2rtlil(AstNode *that, RTLIL::Wire *output_wire, bool gen_attributes = true) -{ - std::string type; - - if (that->is_wand) { - type = "$reduce_and"; - } else if (that->is_wor) { - type = "$reduce_or"; - } else { - log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n"); - } - - std::stringstream sstr; - sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++); - - RTLIL::Cell *cell = current_module->addCell(sstr.str(), type); - cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum); - - 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()); - cell->attributes[attr.first] = attr.second->asAttrConst(); - } - - cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); - cell->parameters["\\A_WIDTH"] = RTLIL::Const(0); - cell->setPort("\\A", RTLIL::SigSpec()); - - cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); - cell->setPort("\\Y", output_wire); - - wire_logic_map[output_wire] = cell; -} - // helper class for converting AST always nodes to RTLIL processes struct AST_INTERNAL::ProcessGenerator { @@ -956,11 +920,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->attributes[attr.first] = attr.second->asAttrConst(); } - if (is_wand || is_wor) { - if (wire->width > 1) - log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n"); - wandwor2rtlil(this, wire); - } + if (is_wand) wire->set_bool_attribute("\\wand"); + if (is_wor) wire->set_bool_attribute("\\wor"); } break; @@ -1492,43 +1453,23 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // add entries to current_module->connections for assignments (outside of always blocks) case AST_ASSIGN: { - bool left_had_const = false; RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size()); - - RTLIL::SigSpec new_left, new_right; - for (int i = 0; i < GetSize(left); i++) - if (left[i].wire) { - std::map::iterator iter = wire_logic_map.find(left[i].wire); - if (iter == wire_logic_map.end()) { + if (left.has_const()) { + RTLIL::SigSpec new_left, new_right; + for (int i = 0; i < GetSize(left); i++) + if (left[i].wire) { new_left.append(left[i]); - } else { - RTLIL::Cell *reduce_cell = iter->second; - RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); - int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); - - RTLIL::Wire *new_reduce_input = current_module->addWire( - stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); - new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); - reduce_cell_in.append(new_reduce_input); - reduce_cell->setPort("\\A", reduce_cell_in); - reduce_cell->fixup_parameters(); - new_left.append(new_reduce_input); + new_right.append(right[i]); } - new_right.append(right[i]); - } else { - left_had_const = true; - } - - left = new_left; - right = new_right; - current_module->connect(RTLIL::SigSig(left, right)); - - if (left_had_const) 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)); + left = new_left; + right = new_right; + } + current_module->connect(RTLIL::SigSig(left, right)); } break; @@ -1573,38 +1514,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (child->type == AST_ARGUMENT) { RTLIL::SigSpec sig; - RTLIL::SigSpec new_sig; - if (child->children.size() > 0) { + if (child->children.size() > 0) sig = child->children[0]->genRTLIL(); - for (int i = 0; i < GetSize(sig); i++) { - if (sig[i].wire) { - std::map::iterator iter = wire_logic_map.find(sig[i].wire); - if (iter == wire_logic_map.end()) { - new_sig.append(sig[i]); - } else { - RTLIL::Cell *reduce_cell = iter->second; - RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A"); - int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int(); - - RTLIL::Wire *new_reduce_input = current_module->addWire( - stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width)); - new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); - reduce_cell_in.append(new_reduce_input); - reduce_cell->setPort("\\A", reduce_cell_in); - reduce_cell->fixup_parameters(); - new_sig.append(new_reduce_input); - } - } else { - new_sig.append(sig[i]); - } - } - } if (child->str.size() == 0) { char buf[100]; snprintf(buf, 100, "$%d", ++port_counter); - cell->setPort(buf, new_sig); + cell->setPort(buf, sig); } else { - cell->setPort(child->str, new_sig); + cell->setPort(child->str, sig); } continue; } diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 72bc2e133..013923816 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -562,7 +562,7 @@ struct HierarchyPass : public Pass { log("In parametric designs, a module might exists in several variations with\n"); log("different parameter values. This pass looks at all modules in the current\n"); log("design an re-runs the language frontends for the parametric modules as\n"); - log("needed.\n"); + log("needed. It also resolves assignments to wired logic data types (wand/wor).\n"); log("\n"); log(" -check\n"); log(" also check the design hierarchy. this generates an error when\n"); @@ -941,6 +941,61 @@ struct HierarchyPass : public Pass { std::set blackbox_derivatives; std::vector design_modules = design->modules(); + std::map wlogic_map; + + for (auto module : design_modules) + for (auto wire : module->wires()) + { + Cell *reduce = nullptr; + if (wire->get_bool_attribute("\\wand")) { + reduce = module->addCell( + stringf("$%s_reduce", wire->name.c_str()), "$reduce_and"); + } + if (wire->get_bool_attribute("\\wor")) { + reduce = module->addCell( + stringf("$%s_reduce", wire->name.c_str()), "$reduce_or"); + } + if (reduce) { + if (wire->width > 1) + log_error("Multi-bit wand/wor unsupported (%s)\n", + log_id(wire)); + + reduce->parameters["\\A_SIGNED"] = Const(0); + reduce->parameters["\\A_WIDTH"] = Const(0); + reduce->setPort("\\A", SigSpec()); + + reduce->parameters["\\Y_WIDTH"] = Const(1); + reduce->setPort("\\Y", wire); + wlogic_map[wire] = reduce; + } + } + + for (auto module : design_modules) { + std::vector new_connections; + for (auto &conn : module->connections()) + { + SigSpec sig = conn.first; + for (int i = 0; i < GetSize(sig); i++) { + Wire *sigwire = sig[i].wire; + if (sigwire == nullptr) + continue; + + if (sigwire->get_bool_attribute("\\wor") || sigwire->get_bool_attribute("\\wand")) { + Cell *reduce = wlogic_map[sigwire]; + SigSpec reduce_in = reduce->getPort("\\A"); + int reduce_width = reduce->getParam("\\A_WIDTH").as_int(); + Wire *new_reduce_input = module->addWire( + stringf("%s_in%d", reduce->name.c_str(), reduce_width)); + reduce_in.append(new_reduce_input); + reduce->setPort("\\A", reduce_in); + reduce->fixup_parameters(); + sig[i] = new_reduce_input; + } + } + new_connections.push_back(SigSig(sig, conn.second)); + } + module->new_connections(new_connections); + } for (auto module : design_modules) for (auto cell : module->cells()) @@ -996,6 +1051,27 @@ struct HierarchyPass : public Pass { cell->setPort(conn.first, sig); } + for (int i = 0; i < GetSize(sig); i++) { + Wire *sigwire = sig[i].wire; + if (sigwire == nullptr) + continue; + + if (sigwire->get_bool_attribute("\\wor") || sigwire->get_bool_attribute("\\wand")) { + if (w->port_output && !w->port_input) { + Cell *reduce = wlogic_map[sigwire]; + SigSpec reduce_in = reduce->getPort("\\A"); + int reduce_width = reduce->getParam("\\A_WIDTH").as_int(); + Wire *new_reduce_input = module->addWire( + stringf("$%s_in%d", reduce->name.c_str(), reduce_width)); + reduce_in.append(new_reduce_input); + reduce->setPort("\\A", reduce_in); + reduce->fixup_parameters(); + sig[i] = new_reduce_input; + } + } + } + cell->setPort(conn.first, sig); + if (w->port_output && !w->port_input && sig.has_const()) log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n", log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig)); -- cgit v1.2.3 From cd12f2ddcfbdbfbf147afc2c90ddc54ec1f74485 Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:01:44 +0200 Subject: remove leftovers from ast data structures --- frontends/ast/ast.cc | 3 --- frontends/ast/ast.h | 1 - 2 files changed, 4 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 963152588..44b8863f9 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -51,7 +51,6 @@ namespace AST_INTERNAL { std::map current_scope; const dict *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; - std::map wire_logic_map; AstNode *current_always, *current_top_block, *current_block, *current_block_child; AstModule *current_module; bool current_always_clocked; @@ -943,8 +942,6 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } - wire_logic_map = std::map(); - if (!defer) { bool blackbox_module = flag_lib; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index c2a7744c4..6c19dc7e6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -327,7 +327,6 @@ namespace AST_INTERNAL extern std::map current_scope; extern const dict *genRTLIL_subst_ptr; extern RTLIL::SigSpec ignoreThisSignalsInInitial; - extern std::map wire_logic_map; extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; extern bool current_always_clocked; -- cgit v1.2.3 From 7f11a732102c9e5c32871de9aad2de95b20d988f Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:07:12 +0200 Subject: update README.md with wand/wor information --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index efb74ef4e..73124898d 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ writing the design to the console in Yosys's internal format: yosys> write_ilang -elaborate design hierarchy: +elaborate design hierarchy and convert wand/wor nets to logic: yosys> hierarchy @@ -257,7 +257,7 @@ for them: - Non-synthesizable language features as defined in IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002 -- The ``tri``, ``triand``, ``trior``, ``wand`` and ``wor`` net types +- The ``tri``, ``triand`` and ``trior`` net types - The ``config`` and ``disable`` keywords and library map files -- cgit v1.2.3 From c5fe04acfde6e0f8c4c8f3d77a917a5918e8b839 Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:10:39 +0200 Subject: remove port direction workaround from test case --- tests/various/wandwor.v | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/various/wandwor.v b/tests/various/wandwor.v index 824f89683..d1dca6269 100644 --- a/tests/various/wandwor.v +++ b/tests/various/wandwor.v @@ -17,7 +17,6 @@ module c; wand E; - wire E_wire = E; genvar i; for (i = 0; i < 3; i = i + 1) @@ -27,7 +26,7 @@ module c; ); b b_inst ( - .D(E_wire) + .D(E) ); end -- cgit v1.2.3 From f68b658b4b88b9a71377d19d7d693f07eccf433e Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:45:54 +0200 Subject: reformat wand/wor test --- tests/various/wandwor.v | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/tests/various/wandwor.v b/tests/various/wandwor.v index d1dca6269..fc072daa3 100644 --- a/tests/various/wandwor.v +++ b/tests/various/wandwor.v @@ -1,34 +1,33 @@ module a(Q); - output wire Q; - - assign Q = 0; + output wire Q = 0; endmodule module b(D); - input wire D; + input wire D; endmodule module c; - wor D; - assign D = 1; - assign D = 0; - assign D = 1; - assign D = 0; + // net definitions + wor D; + wand E; + + // assignments to wired logic nets + assign D = 1; + assign D = 0; + assign D = 1; + assign D = 0; + // assignments of wired logic nets to wires + wire F = E; - wand E; - - genvar i; - for (i = 0; i < 3; i = i + 1) - begin :genloop - a a_inst ( - .Q(E) - ); - - b b_inst ( - .D(E) - ); - end + genvar i; + for (i = 0; i < 3; i = i + 1) + begin : genloop + // connection of module outputs + a a_inst (.Q(E)); + // connection of module inputs + b b_inst (.D(E)); + end endmodule -- cgit v1.2.3