Added support for attribute matching in extract pass
authorClifford Wolf <clifford@clifford.at>
Thu, 7 Mar 2013 17:51:17 +0000 (18:51 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 7 Mar 2013 17:51:17 +0000 (18:51 +0100)
passes/extract/extract.cc

index 320f812ea864a8236b512ff4d76e00186109e9e8..4909126a777434b02efdc6c6d9670768e679065e 100644 (file)
@@ -31,6 +31,58 @@ using RTLIL::id2cstr;
 
 namespace
 {
+       class SubCircuitSolver : public SubCircuit::Solver
+       {
+       public:
+               std::set<RTLIL::IdString> attr_compare;
+
+               bool compareAttributes(const std::map<RTLIL::IdString, RTLIL::Const> &needleAttr, const std::map<RTLIL::IdString, RTLIL::Const> &haystackAttr)
+               {
+                       for (auto &it : attr_compare) {
+                               size_t nc = needleAttr.count(it), hc = haystackAttr.count(it);
+                               if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it)))
+                                       return false;
+                       }
+                       return true;
+               }
+
+               virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData,
+                               const std::string &, const std::string &, void *haystackUserData, const std::map<std::string, std::string> &portMapping)
+               {
+                       if (attr_compare.size() == 0)
+                               return true;
+
+                       RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData;
+                       RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData;
+
+                       if (!compareAttributes(needleCell->attributes, haystackCell->attributes))
+                               return false;
+
+                       RTLIL::Wire *lastNeedleWire = NULL;
+                       RTLIL::Wire *lastHaystackWire = NULL;
+                       std::map<RTLIL::IdString, RTLIL::Const> emptyAttr;
+
+                       for (auto &conn : needleCell->connections)
+                       {
+                               RTLIL::SigSpec needleSig = conn.second;
+                               RTLIL::SigSpec haystackSig = haystackCell->connections.at(portMapping.at(conn.first));
+
+                               needleSig.expand();
+                               haystackSig.expand();
+
+                               for (int i = 0; i < std::min(needleSig.width, haystackSig.width); i++) {
+                                       RTLIL::Wire *needleWire = needleSig.chunks.at(i).wire, *haystackWire = haystackSig.chunks.at(i).wire;
+                                       if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
+                                               if (!compareAttributes(needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr))
+                                                       return false;
+                                       lastNeedleWire = needleWire, lastHaystackWire = haystackWire;
+                               }
+                       }
+
+                       return true;
+               }
+       };
+
        struct bit_ref_t {
                std::string cell, port;
                int bit;
@@ -288,6 +340,9 @@ struct ExtractPass : public Pass {
                log("        Register a valid permutation of swapable ports for a needle\n");
                log("        cell type. This option can be used multiple times.\n");
                log("\n");
+               log("    -attr <attribute_name>\n");
+               log("        Attributes with the given name must match (cells and wires).\n");
+               log("\n");
                log("This pass does not operate on modules with uprocessed processes in it.\n");
                log("(I.e. the 'proc' pass should be used first to convert processes to netlists.)\n");
                log("\n");
@@ -324,7 +379,7 @@ struct ExtractPass : public Pass {
                log_header("Executing EXTRACT pass (map subcircuits to cells).\n");
                log_push();
 
-               SubCircuit::Solver solver;
+               SubCircuitSolver solver;
 
                std::string filename;
                bool constports = false;
@@ -422,6 +477,10 @@ struct ExtractPass : public Pass {
                                solver.addSwappablePortsPermutation(type, map);
                                continue;
                        }
+                       if (args[argidx] == "-attr" && argidx+1 < args.size()) {
+                               solver.attr_compare.insert(RTLIL::escape_id(args[++argidx]));
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);