cxxrtl: fix typo.
[yosys.git] / backends / edif / edif.cc
index 199560ad0d3438022f61b213744e6b73eaa754d8..e0013238c8321b320de162fc86df6a397f6b03f3 100644 (file)
@@ -90,7 +90,7 @@ struct EdifNames
 
 struct EdifBackend : public Backend {
        EdifBackend() : Backend("edif", "write design to EDIF netlist file") { }
-       void help() YS_OVERRIDE
+       void help() override
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -113,6 +113,9 @@ struct EdifBackend : public Backend {
                log("    -attrprop\n");
                log("        create EDIF properties for cell attributes\n");
                log("\n");
+               log("    -keep\n");
+               log("        create extra KEEP nets by allowing a cell to drive multiple nets.\n");
+               log("\n");
                log("    -pvector {par|bra|ang}\n");
                log("        sets the delimiting character for module port rename clauses to\n");
                log("        parentheses, square brackets, or angle brackets.\n");
@@ -123,14 +126,14 @@ struct EdifBackend : public Backend {
                log("is targeted.\n");
                log("\n");
        }
-       void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
        {
                log_header(design, "Executing EDIF backend.\n");
                std::string top_module_name;
                bool port_rename = false;
                bool attr_properties = false;
                std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
-               bool nogndvcc = false, gndvccy = false;
+               bool nogndvcc = false, gndvccy = false, keepmode = false;
                CellTypes ct(design);
                EdifNames edif_names;
 
@@ -153,6 +156,10 @@ struct EdifBackend : public Backend {
                                attr_properties = true;
                                continue;
                        }
+                       if (args[argidx] == "-keep") {
+                               keepmode = true;
+                               continue;
+                       }
                        if (args[argidx] == "-pvector" && argidx+1 < args.size()) {
                                std::string parray;
                                port_rename = true;
@@ -171,13 +178,12 @@ struct EdifBackend : public Backend {
                extra_args(f, filename, args, argidx);
 
                if (top_module_name.empty())
-                       for (auto & mod_it:design->modules_)
-                               if (mod_it.second->get_bool_attribute("\\top"))
-                                       top_module_name = mod_it.first.str();
+                       for (auto module : design->modules())
+                               if (module->get_bool_attribute(ID::top))
+                                       top_module_name = module->name.str();
 
-               for (auto module_it : design->modules_)
+               for (auto module : design->modules())
                {
-                       RTLIL::Module *module = module_it.second;
                        if (module->get_blackbox_attribute())
                                continue;
 
@@ -185,14 +191,13 @@ struct EdifBackend : public Backend {
                                top_module_name = module->name.str();
 
                        if (module->processes.size() != 0)
-                               log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name));
+                               log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name));
                        if (module->memories.size() != 0)
-                               log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name));
+                               log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name));
 
-                       for (auto cell_it : module->cells_)
+                       for (auto cell : module->cells())
                        {
-                               RTLIL::Cell *cell = cell_it.second;
-                               if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) {
+                               if (design->module(cell->type) == nullptr || design->module(cell->type)->get_blackbox_attribute()) {
                                        lib_cell_ports[cell->type];
                                        for (auto p : cell->connections())
                                                lib_cell_ports[cell->type][p.first] = GetSize(p.second);
@@ -277,11 +282,11 @@ struct EdifBackend : public Backend {
 
                // extract module dependencies
                std::map<RTLIL::Module*, std::set<RTLIL::Module*>> module_deps;
-               for (auto &mod_it : design->modules_) {
-                       module_deps[mod_it.second] = std::set<RTLIL::Module*>();
-                       for (auto &cell_it : mod_it.second->cells_)
-                               if (design->modules_.count(cell_it.second->type) > 0)
-                                       module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type));
+               for (auto module : design->modules()) {
+                       module_deps[module] = std::set<RTLIL::Module*>();
+                       for (auto cell : module->cells())
+                               if (design->module(cell->type) != nullptr)
+                                       module_deps[module].insert(design->module(cell->type));
                }
 
                // simple good-enough topological sort
@@ -292,12 +297,12 @@ struct EdifBackend : public Backend {
                                for (auto &dep : it.second)
                                        if (module_deps.count(dep) > 0)
                                                goto not_ready_yet;
-                               // log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name));
+                               // log("Next in topological sort: %s\n", log_id(it.first->name));
                                sorted_modules.push_back(it.first);
                        not_ready_yet:;
                        }
                        if (sorted_modules_idx == sorted_modules.size())
-                               log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name));
+                               log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name));
                        while (sorted_modules_idx < sorted_modules.size())
                                module_deps.erase(sorted_modules.at(sorted_modules_idx++));
                }
@@ -325,7 +330,7 @@ struct EdifBackend : public Backend {
                                }
                                *f << stringf("\n            (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
                        }
-               };              
+               };
                for (auto module : sorted_modules)
                {
                        if (module->get_blackbox_attribute())
@@ -339,8 +344,72 @@ struct EdifBackend : public Backend {
                        *f << stringf("      (view VIEW_NETLIST\n");
                        *f << stringf("        (viewType NETLIST)\n");
                        *f << stringf("        (interface\n");
-                       for (auto &wire_it : module->wires_) {
-                               RTLIL::Wire *wire = wire_it.second;
+
+                       for (auto cell : module->cells()) {
+                               for (auto &conn : cell->connections())
+                                       if (cell->output(conn.first))
+                                               sigmap.add(conn.second);
+                       }
+
+                       for (auto wire : module->wires())
+                               for (auto b1 : SigSpec(wire))
+                               {
+                                       auto b2 = sigmap(b1);
+
+                                       if (b1 == b2 || !b2.wire)
+                                               continue;
+
+                                       log_assert(b1.wire != nullptr);
+
+                                       Wire *w1 = b1.wire;
+                                       Wire *w2 = b2.wire;
+
+                                       {
+                                               int c1 = w1->get_bool_attribute(ID::keep);
+                                               int c2 = w2->get_bool_attribute(ID::keep);
+
+                                               if (c1 > c2) goto promote;
+                                               if (c1 < c2) goto nopromote;
+                                       }
+
+                                       {
+                                               int c1 = w1->name.isPublic();
+                                               int c2 = w2->name.isPublic();
+
+                                               if (c1 > c2) goto promote;
+                                               if (c1 < c2) goto nopromote;
+                                       }
+
+                                       {
+                                               auto count_nontrivial_attr = [](Wire *w) {
+                                                       int count = w->attributes.size();
+                                                       count -= w->attributes.count(ID::src);
+                                                       count -= w->attributes.count(ID::unused_bits);
+                                                       return count;
+                                               };
+
+                                               int c1 = count_nontrivial_attr(w1);
+                                               int c2 = count_nontrivial_attr(w2);
+
+                                               if (c1 > c2) goto promote;
+                                               if (c1 < c2) goto nopromote;
+                                       }
+
+                                       {
+                                               int c1 = w1->port_id ? INT_MAX - w1->port_id : 0;
+                                               int c2 = w2->port_id ? INT_MAX - w2->port_id : 0;
+
+                                               if (c1 > c2) goto promote;
+                                               if (c1 < c2) goto nopromote;
+                                       }
+
+                               nopromote:
+                                       if (0)
+                               promote:
+                                               sigmap.add(b1);
+                               }
+
+                       for (auto wire : module->wires()) {
                                if (wire->port_id == 0)
                                        continue;
                                const char *dir = "INOUT";
@@ -372,14 +441,16 @@ struct EdifBackend : public Backend {
                                        }
                                }
                        }
+
                        *f << stringf("        )\n");
                        *f << stringf("        (contents\n");
+
                        if (!nogndvcc) {
                                *f << stringf("          (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n");
                                *f << stringf("          (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n");
                        }
-                       for (auto &cell_it : module->cells_) {
-                               RTLIL::Cell *cell = cell_it.second;
+
+                       for (auto cell : module->cells()) {
                                *f << stringf("          (instance %s\n", EDIF_DEF(cell->name));
                                *f << stringf("            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type),
                                                lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : "");
@@ -416,6 +487,7 @@ struct EdifBackend : public Backend {
                                                }
                                }
                        }
+
                        for (auto &it : net_join_db) {
                                RTLIL::SigBit sig = it.first;
                                if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) {
@@ -444,7 +516,7 @@ struct EdifBackend : public Backend {
                                }
                                *f << stringf("          (net %s (joined\n", EDIF_DEF(netname));
                                for (auto &ref : it.second)
-                                       *f << stringf("            %s\n", ref.first.c_str());
+                                       *f << stringf("              %s\n", ref.first.c_str());
                                if (sig.wire == NULL) {
                                        if (nogndvcc)
                                                log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
@@ -452,38 +524,55 @@ struct EdifBackend : public Backend {
                                                *f << stringf("            (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
                                        if (sig == RTLIL::State::S1)
                                                *f << stringf("            (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
-                               }                               
+                               }
                                *f << stringf("            )");
                                if (attr_properties && sig.wire != NULL)
                                        for (auto &p : sig.wire->attributes)
                                                add_prop(p.first, p.second);
                                *f << stringf("\n          )\n");
                        }
-                       for (auto &wire_it : module->wires_) {
-                               RTLIL::Wire *wire = wire_it.second;
+
+                       for (auto wire : module->wires())
+                       {
                                if (!wire->get_bool_attribute(ID::keep))
                                        continue;
-                               for(int i = 0; i < wire->width; i++) {
+
+                               for(int i = 0; i < wire->width; i++)
+                               {
                                        SigBit raw_sig = RTLIL::SigSpec(wire, i);
                                        SigBit mapped_sig = sigmap(raw_sig);
+
                                        if (raw_sig == mapped_sig || net_join_db.count(mapped_sig) == 0)
                                                continue;
+
                                        std::string netname = log_signal(raw_sig);
                                        for (size_t i = 0; i < netname.size(); i++)
                                                if (netname[i] == ' ' || netname[i] == '\\')
                                                        netname.erase(netname.begin() + i--);
-                                       *f << stringf("          (net %s (joined\n", EDIF_DEF(netname));
-                                       auto &refs = net_join_db.at(mapped_sig);
-                                       for (auto &ref : refs)
-                                               if (ref.second)
-                                                       *f << stringf("            %s\n", ref.first.c_str());
-                                       *f << stringf("            )");
-                                       if (attr_properties && raw_sig.wire != NULL)
-                                               for (auto &p : raw_sig.wire->attributes)
-                                                       add_prop(p.first, p.second);
-                                       *f << stringf("\n          )\n");
+
+                                       if (keepmode)
+                                       {
+                                               *f << stringf("          (net %s (joined\n", EDIF_DEF(netname));
+
+                                               auto &refs = net_join_db.at(mapped_sig);
+                                               for (auto &ref : refs)
+                                                       if (ref.second)
+                                                               *f << stringf("              %s\n", ref.first.c_str());
+                                               *f << stringf("            )");
+
+                                               if (attr_properties && raw_sig.wire != NULL)
+                                                       for (auto &p : raw_sig.wire->attributes)
+                                                               add_prop(p.first, p.second);
+
+                                               *f << stringf("\n          )\n");
+                                       }
+                                       else
+                                       {
+                                               log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname));
+                                       }
                                }
                        }
+
                        *f << stringf("        )\n");
                        *f << stringf("      )\n");
                        *f << stringf("    )\n");