move wand/wor resolution into hierarchy pass
authorStefan Biereigel <stefan@biereigel.de>
Mon, 27 May 2019 16:00:22 +0000 (18:00 +0200)
committerStefan Biereigel <stefan@biereigel.de>
Mon, 27 May 2019 16:00:22 +0000 (18:00 +0200)
frontends/ast/genrtlil.cc
passes/hierarchy/hierarchy.cc

index 047b0a81b4e6879d5097ffffe1891578f9476a48..8094304e52ede74ceb6d9c2d1c59455472fbe857 100644 (file)
@@ -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<RTLIL::SigSpec, RTLIL::Cell*>::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<RTLIL::SigSpec, RTLIL::Cell*>::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;
                                }
index 72bc2e133983ac022a5dc49e21b029b0f7f707bb..0139238163567601a9fa226787675847de0ef305 100644 (file)
@@ -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<Module*> blackbox_derivatives;
                std::vector<Module*> design_modules = design->modules();
+               std::map<Wire*, Cell*> 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<SigSig> 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));