From ed625a3102233bf9c9af17e56575dc4a0ed8946c Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Mon, 27 May 2019 18:00:22 +0200 Subject: [PATCH] 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)); -- 2.30.2