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(-) (limited to 'frontends') 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(-) (limited to 'frontends') 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(-) (limited to 'frontends') 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 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(-) (limited to 'frontends') 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 34417ce55f1b1d71ac11dfdfecfffc7a3340b6cb Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 27 May 2019 11:42:10 +0200 Subject: Added support for unsized constants, fixes #1022 Includes work from @sumit0190 and @AaronKel --- frontends/ast/ast.cc | 17 ++++++++++++++++- frontends/ast/ast.h | 4 +++- frontends/ast/genrtlil.cc | 9 +++++++-- frontends/verilog/const2ast.cc | 26 ++++++++++++++++++-------- frontends/verilog/verilog_lexer.l | 2 +- 5 files changed, 45 insertions(+), 13 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 5623541b2..29e175c15 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -194,6 +194,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch is_logic = false; is_signed = false; is_string = false; + is_unsized = false; was_checked = false; range_valid = false; range_swapped = false; @@ -722,7 +723,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width) } // create an AST node for a constant (using a bit vector as value) -AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signed) +AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized) { AstNode *node = new AstNode(AST_CONSTANT); node->is_signed = is_signed; @@ -736,9 +737,15 @@ AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signe node->range_valid = true; node->range_left = node->bits.size()-1; node->range_right = 0; + node->is_unsized = is_unsized; return node; } +AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signed) +{ + return mkconst_bits(v, is_signed, false); +} + // create an AST node for a constant (using a string in bit vector form as value) AstNode *AstNode::mkconst_str(const std::vector &v) { @@ -775,6 +782,14 @@ bool AstNode::bits_only_01() const return true; } +RTLIL::Const AstNode::bitsAsUnsizedConst(int width) +{ + RTLIL::State extbit = bits.back(); + while (width > int(bits.size())) + bits.push_back(extbit); + return RTLIL::Const(bits); +} + RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed) { std::vector bits = this->bits; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 281cbe086..f90e683ad 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, range_valid, range_swapped, was_checked, is_unsized; int port_id, range_left, range_right; uint32_t integer; double realvalue; @@ -262,6 +262,7 @@ namespace AST // helper functions for creating AST nodes for constants static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32); + static AstNode *mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized); static AstNode *mkconst_bits(const std::vector &v, bool is_signed); static AstNode *mkconst_str(const std::vector &v); static AstNode *mkconst_str(const std::string &str); @@ -269,6 +270,7 @@ namespace AST // helper function for creating sign-extended const objects RTLIL::Const bitsAsConst(int width, bool is_signed); RTLIL::Const bitsAsConst(int width = -1); + RTLIL::Const bitsAsUnsizedConst(int width); RTLIL::Const asAttrConst(); RTLIL::Const asParaConst(); uint64_t asInt(bool is_signed); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 379fed641..d9dfc17cc 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -963,8 +963,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) detectSignWidth(width_hint, sign_hint); is_signed = sign_hint; - if (type == AST_CONSTANT) - return RTLIL::SigSpec(bitsAsConst()); + if (type == AST_CONSTANT) { + if (is_unsized) { + return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint)); + } else { + return RTLIL::SigSpec(bitsAsConst()); + } + } RTLIL::SigSpec sig = realAsConst(width_hint); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 7848c626d..57d366dbf 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -71,7 +71,7 @@ static int my_ilog2(int x) } // parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?') -static void my_strtobin(std::vector &data, const char *str, int len_in_bits, int base, char case_type) +static void my_strtobin(std::vector &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized) { // all digits in string (MSB at index 0) std::vector digits; @@ -129,6 +129,9 @@ static void my_strtobin(std::vector &data, const char *str, int le return; } + if (is_unsized && (len > len_in_bits)) + log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len); + for (len = len - 1; len >= 0; len--) if (data[len] == RTLIL::S1) break; @@ -186,7 +189,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn // Simple base-10 integer if (*endptr == 0) { std::vector data; - my_strtobin(data, str, -1, 10, case_type); + my_strtobin(data, str, -1, 10, case_type, false); if (data.back() == RTLIL::S1) data.push_back(RTLIL::S0); return AstNode::mkconst_bits(data, true); @@ -201,6 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn { std::vector data; bool is_signed = false; + bool is_unsized = false; if (*(endptr+1) == 's') { is_signed = true; endptr++; @@ -209,28 +213,34 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn { case 'b': case 'B': - my_strtobin(data, endptr+2, len_in_bits, 2, case_type); + my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false); break; case 'o': case 'O': - my_strtobin(data, endptr+2, len_in_bits, 8, case_type); + my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false); break; case 'd': case 'D': - my_strtobin(data, endptr+2, len_in_bits, 10, case_type); + my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false); break; case 'h': case 'H': - my_strtobin(data, endptr+2, len_in_bits, 16, case_type); + my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false); break; default: - return NULL; + char next_char = char(tolower(*(endptr+1))); + if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') { + my_strtobin(data, endptr+1, 1, 2, case_type, true); + is_unsized = true; + } else { + return NULL; + } } if (len_in_bits < 0) { if (is_signed && data.back() == RTLIL::S1) data.push_back(RTLIL::S0); } - return AstNode::mkconst_bits(data, is_signed); + return AstNode::mkconst_bits(data, is_signed, is_unsized); } return NULL; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 142d05d45..d89e144a9 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -232,7 +232,7 @@ YOSYS_NAMESPACE_END return TOK_CONSTVAL; } -[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ { +[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONSTVAL; } -- cgit v1.2.3 From 84ffb217081fed7ddf1f683f65f2a2fdf813cd6b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 27 May 2019 12:25:18 +0200 Subject: Give error instead of asserting for invalid range, fixes #947 --- 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 379fed641..1b19ba4e5 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -904,7 +904,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (!range_valid) 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)); + if (!(range_left >= range_right || (range_left == -1 && range_right == 0))) + log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1); RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1); wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); -- 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 ++++++---------------------------------------- 1 file changed, 14 insertions(+), 97 deletions(-) (limited to 'frontends') 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; } -- 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(-) (limited to 'frontends') 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