abc9_ops: still emit delay table even box has no timing
[yosys.git] / passes / techmap / extract.cc
index a960f2bae050178ea837455e5b2c037015abe767..f8798eea50857e7a4c9012380cbc17cc24168774 100644 (file)
@@ -2,11 +2,11 @@
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  
+ *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
  *  copyright notice and this permission notice appear in all copies.
- *  
+ *
  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 #include "libs/subcircuit/subcircuit.h"
 #include <algorithm>
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
 using RTLIL::id2cstr;
 
-namespace
+class SubCircuitSolver : public SubCircuit::Solver
 {
-       class SubCircuitSolver : public SubCircuit::Solver
-       {
-       public:
-               bool ignore_parameters;
-               std::set<std::pair<std::string, std::string>> ignored_parameters;
-               std::set<RTLIL::IdString> cell_attr, wire_attr;
+public:
+       bool ignore_parameters;
+       std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> ignored_parameters;
+       std::set<RTLIL::IdString> cell_attr, wire_attr;
 
-               SubCircuitSolver() : ignore_parameters(false)
-               {
-               }
+       SubCircuitSolver() : ignore_parameters(false)
+       {
+       }
 
-               bool compareAttributes(const std::set<RTLIL::IdString> &attr, const std::map<RTLIL::IdString, RTLIL::Const> &needleAttr, const std::map<RTLIL::IdString, RTLIL::Const> &haystackAttr)
-               {
-                       for (auto &it : attr) {
-                               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;
+       bool compareAttributes(const std::set<RTLIL::IdString> &attr, const dict<RTLIL::IdString, RTLIL::Const> &needleAttr, const dict<RTLIL::IdString, RTLIL::Const> &haystackAttr)
+       {
+               for (auto &it : attr) {
+                       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;
+       }
 
-               RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value)
-               {
-                       if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_")
-                               return value;
-
-               #define param_bool(_n) if (param == _n) return value.as_bool();
-                       param_bool("\\ARST_POLARITY");
-                       param_bool("\\A_SIGNED");
-                       param_bool("\\B_SIGNED");
-                       param_bool("\\CLK_ENABLE");
-                       param_bool("\\CLK_POLARITY");
-                       param_bool("\\CLR_POLARITY");
-                       param_bool("\\EN_POLARITY");
-                       param_bool("\\SET_POLARITY");
-                       param_bool("\\TRANSPARENT");
-               #undef param_bool
-
-               #define param_int(_n) if (param == _n) return value.as_int();
-                       param_int("\\ABITS")
-                       param_int("\\A_WIDTH")
-                       param_int("\\B_WIDTH")
-                       param_int("\\CTRL_IN_WIDTH")
-                       param_int("\\CTRL_OUT_WIDTH")
-                       param_int("\\OFFSET")
-                       param_int("\\PRIORITY")
-                       param_int("\\RD_PORTS")
-                       param_int("\\SIZE")
-                       param_int("\\STATE_BITS")
-                       param_int("\\STATE_NUM")
-                       param_int("\\STATE_NUM_LOG2")
-                       param_int("\\STATE_RST")
-                       param_int("\\S_WIDTH")
-                       param_int("\\TRANS_NUM")
-                       param_int("\\WIDTH")
-                       param_int("\\WR_PORTS")
-                       param_int("\\Y_WIDTH")
-               #undef param_int
-
+       RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value)
+       {
+               if (!cell_type.begins_with("$") || cell_type.begins_with("$_"))
                        return value;
-               }
 
-               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)
-               {
-                       RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData;
-                       RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData;
+       #define param_bool(_n) if (param == _n) return value.as_bool();
+               param_bool(ID(ARST_POLARITY));
+               param_bool(ID(A_SIGNED));
+               param_bool(ID(B_SIGNED));
+               param_bool(ID(CLK_ENABLE));
+               param_bool(ID(CLK_POLARITY));
+               param_bool(ID(CLR_POLARITY));
+               param_bool(ID(EN_POLARITY));
+               param_bool(ID(SET_POLARITY));
+               param_bool(ID(TRANSPARENT));
+       #undef param_bool
+
+       #define param_int(_n) if (param == _n) return value.as_int();
+               param_int(ID(ABITS))
+               param_int(ID(A_WIDTH))
+               param_int(ID(B_WIDTH))
+               param_int(ID(CTRL_IN_WIDTH))
+               param_int(ID(CTRL_OUT_WIDTH))
+               param_int(ID(OFFSET))
+               param_int(ID(PRIORITY))
+               param_int(ID(RD_PORTS))
+               param_int(ID(SIZE))
+               param_int(ID(STATE_BITS))
+               param_int(ID(STATE_NUM))
+               param_int(ID(STATE_NUM_LOG2))
+               param_int(ID(STATE_RST))
+               param_int(ID(S_WIDTH))
+               param_int(ID(TRANS_NUM))
+               param_int(ID(WIDTH))
+               param_int(ID(WR_PORTS))
+               param_int(ID(Y_WIDTH))
+       #undef param_int
+
+               return value;
+       }
 
-                       if (!needleCell || !haystackCell) {
-                               assert(!needleCell && !haystackCell);
-                               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)
+       {
+               RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData;
+               RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData;
 
-                       if (!ignore_parameters) {
-                               std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param;
-                               for (auto &it : needleCell->parameters)
-                                       if (!ignored_parameters.count(std::pair<std::string, std::string>(needleCell->type, it.first)))
-                                               needle_param[it.first] = unified_param(needleCell->type, it.first, it.second);
-                               for (auto &it : haystackCell->parameters)
-                                       if (!ignored_parameters.count(std::pair<std::string, std::string>(haystackCell->type, it.first)))
-                                               haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second);
-                               if (needle_param != haystack_param)
-                                       return false;
-                       }
+               if (!needleCell || !haystackCell) {
+                       log_assert(!needleCell && !haystackCell);
+                       return true;
+               }
 
-                       if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes))
+               if (!ignore_parameters) {
+                       std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param;
+                       for (auto &it : needleCell->parameters)
+                               if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(needleCell->type, it.first)))
+                                       needle_param[it.first] = unified_param(needleCell->type, it.first, it.second);
+                       for (auto &it : haystackCell->parameters)
+                               if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(haystackCell->type, it.first)))
+                                       haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second);
+                       if (needle_param != haystack_param)
                                return false;
+               }
 
-                       if (wire_attr.size() > 0)
-                       {
-                               RTLIL::Wire *lastNeedleWire = NULL;
-                               RTLIL::Wire *lastHaystackWire = NULL;
-                               std::map<RTLIL::IdString, RTLIL::Const> emptyAttr;
+               if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes))
+                       return false;
 
-                               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.size(), haystackSig.size()); i++) {
-                                               RTLIL::Wire *needleWire = needleSig.chunks().at(i).wire, *haystackWire = haystackSig.chunks().at(i).wire;
-                                               if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
-                                                       if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr))
-                                                               return false;
-                                               lastNeedleWire = needleWire, lastHaystackWire = haystackWire;
-                                       }
+               if (wire_attr.size() > 0)
+               {
+                       RTLIL::Wire *lastNeedleWire = NULL;
+                       RTLIL::Wire *lastHaystackWire = NULL;
+                       dict<RTLIL::IdString, RTLIL::Const> emptyAttr;
+
+                       for (auto &conn : needleCell->connections())
+                       {
+                               RTLIL::SigSpec needleSig = conn.second;
+                               RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str()));
+
+                               for (int i = 0; i < min(needleSig.size(), haystackSig.size()); i++) {
+                                       RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire;
+                                       if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
+                                               if (!compareAttributes(wire_attr, 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;
-       };
+               return true;
+       }
+};
 
-       bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL,
-                       int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL)
-       {
-               SigMap sigmap(mod);
-               std::map<RTLIL::SigChunk, bit_ref_t> sig_bit_ref;
+struct bit_ref_t {
+       std::string cell, port;
+       int bit;
+};
 
-               if (sel && !sel->selected(mod)) {
-                       log("  Skipping module %s as it is not selected.\n", id2cstr(mod->name));
-                       return false;
-               }
+bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL,
+               int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL)
+{
+       SigMap sigmap(mod);
+       std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref;
 
-               if (mod->processes.size() > 0) {
-                       log("  Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
-                       return false;
-               }
+       if (sel && !sel->selected(mod)) {
+               log("  Skipping module %s as it is not selected.\n", id2cstr(mod->name));
+               return false;
+       }
 
-               if (constports) {
-                       graph.createNode("$const$0", "$const$0", NULL, true);
-                       graph.createNode("$const$1", "$const$1", NULL, true);
-                       graph.createNode("$const$x", "$const$x", NULL, true);
-                       graph.createNode("$const$z", "$const$z", NULL, true);
-                       graph.createPort("$const$0", "\\Y", 1);
-                       graph.createPort("$const$1", "\\Y", 1);
-                       graph.createPort("$const$x", "\\Y", 1);
-                       graph.createPort("$const$z", "\\Y", 1);
-                       graph.markExtern("$const$0", "\\Y", 0);
-                       graph.markExtern("$const$1", "\\Y", 0);
-                       graph.markExtern("$const$x", "\\Y", 0);
-                       graph.markExtern("$const$z", "\\Y", 0);
-               }
+       if (mod->processes.size() > 0) {
+               log("  Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
+               return false;
+       }
 
-               std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count;
-               if (max_fanout > 0)
-                       for (auto &cell_it : mod->cells)
-                       {
-                               RTLIL::Cell *cell = cell_it.second;
-                               if (!sel || sel->selected(mod, cell))
-                                       for (auto &conn : cell->connections) {
-                                               RTLIL::SigSpec conn_sig = conn.second;
-                                               sigmap.apply(conn_sig);
-                                               conn_sig.expand();
-                                               for (auto &chunk : conn_sig.chunks())
-                                                       if (chunk.wire != NULL)
-                                                               sig_use_count[std::pair<RTLIL::Wire*, int>(chunk.wire, chunk.offset)]++;
-                                       }
-                       }
+       if (constports) {
+               graph.createNode("$const$0", "$const$0", NULL, true);
+               graph.createNode("$const$1", "$const$1", NULL, true);
+               graph.createNode("$const$x", "$const$x", NULL, true);
+               graph.createNode("$const$z", "$const$z", NULL, true);
+               graph.createPort("$const$0", "\\Y", 1);
+               graph.createPort("$const$1", "\\Y", 1);
+               graph.createPort("$const$x", "\\Y", 1);
+               graph.createPort("$const$z", "\\Y", 1);
+               graph.markExtern("$const$0", "\\Y", 0);
+               graph.markExtern("$const$1", "\\Y", 0);
+               graph.markExtern("$const$x", "\\Y", 0);
+               graph.markExtern("$const$z", "\\Y", 0);
+       }
 
-               // create graph nodes from cells
-               for (auto &cell_it : mod->cells)
+       std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count;
+       if (max_fanout > 0)
+               for (auto &cell_it : mod->cells_)
                {
                        RTLIL::Cell *cell = cell_it.second;
-                       if (sel && !sel->selected(mod, cell))
-                               continue;
+                       if (!sel || sel->selected(mod, cell))
+                               for (auto &conn : cell->connections()) {
+                                       RTLIL::SigSpec conn_sig = conn.second;
+                                       sigmap.apply(conn_sig);
+                                       for (auto &bit : conn_sig)
+                                               if (bit.wire != NULL)
+                                                       sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++;
+                               }
+               }
 
-                       std::string type = cell->type;
-                       if (sel == NULL && type.substr(0, 2) == "\\$")
-                               type = type.substr(1);
-                       graph.createNode(cell->name, type, (void*)cell);
+       // create graph nodes from cells
+       for (auto &cell_it : mod->cells_)
+       {
+               RTLIL::Cell *cell = cell_it.second;
+               if (sel && !sel->selected(mod, cell))
+                       continue;
 
-                       for (auto &conn : cell->connections)
-                       {
-                               graph.createPort(cell->name, conn.first, conn.second.size());
+               std::string type = cell->type.str();
+               if (sel == NULL && type.compare(0, 2, "\\$") == 0)
+                       type = type.substr(1);
+               graph.createNode(cell->name.str(), type, (void*)cell);
 
-                               if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0)
-                                       continue;
+               for (auto &conn : cell->connections())
+               {
+                       graph.createPort(cell->name.str(), conn.first.str(), conn.second.size());
 
-                               RTLIL::SigSpec conn_sig = conn.second;
-                               sigmap.apply(conn_sig);
-                               conn_sig.expand();
+                       if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0)
+                               continue;
 
-                               for (size_t i = 0; i < conn_sig.chunks().size(); i++)
-                               {
-                                       auto &chunk = conn_sig.chunks()[i];
-                                       assert(chunk.width == 1);
-
-                                       if (chunk.wire == NULL) {
-                                               if (constports) {
-                                                       std::string node = "$const$x";
-                                                       if (chunk.data.bits[0] == RTLIL::State::S0) node = "$const$0";
-                                                       if (chunk.data.bits[0] == RTLIL::State::S1) node = "$const$1";
-                                                       if (chunk.data.bits[0] == RTLIL::State::Sz) node = "$const$z";
-                                                       graph.createConnection(cell->name, conn.first, i, node, "\\Y", 0);
-                                               } else
-                                                       graph.createConstant(cell->name, conn.first, i, int(chunk.data.bits[0]));
-                                               continue;
-                                       }
+                       RTLIL::SigSpec conn_sig = conn.second;
+                       sigmap.apply(conn_sig);
 
-                                       if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(chunk.wire, chunk.offset)] > max_fanout)
-                                               continue;
+                       for (int i = 0; i < conn_sig.size(); i++)
+                       {
+                               auto &bit = conn_sig[i];
+
+                               if (bit.wire == NULL) {
+                                       if (constports) {
+                                               std::string node = "$const$x";
+                                               if (bit == RTLIL::State::S0) node = "$const$0";
+                                               if (bit == RTLIL::State::S1) node = "$const$1";
+                                               if (bit == RTLIL::State::Sz) node = "$const$z";
+                                               graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0);
+                                       } else
+                                               graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data));
+                                       continue;
+                               }
 
-                                       if (sel && !sel->selected(mod, chunk.wire))
-                                               continue;
+                               if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)] > max_fanout)
+                                       continue;
 
-                                       if (sig_bit_ref.count(chunk) == 0) {
-                                               bit_ref_t &bit_ref = sig_bit_ref[chunk];
-                                               bit_ref.cell = cell->name;
-                                               bit_ref.port = conn.first;
-                                               bit_ref.bit = i;
-                                       }
+                               if (sel && !sel->selected(mod, bit.wire))
+                                       continue;
 
-                                       bit_ref_t &bit_ref = sig_bit_ref[chunk];
-                                       graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name, conn.first, i);
+                               if (sig_bit_ref.count(bit) == 0) {
+                                       bit_ref_t &bit_ref = sig_bit_ref[bit];
+                                       bit_ref.cell = cell->name.str();
+                                       bit_ref.port = conn.first.str();
+                                       bit_ref.bit = i;
                                }
-                       }
-               }
-
-               // mark external signals (used in non-selected cells)
-               for (auto &cell_it : mod->cells)
-               {
-                       RTLIL::Cell *cell = cell_it.second;
-                       if (sel && !sel->selected(mod, cell))
-                               for (auto &conn : cell->connections)
-                               {
-                                       RTLIL::SigSpec conn_sig = conn.second;
-                                       sigmap.apply(conn_sig);
-                                       conn_sig.expand();
 
-                                       for (auto &chunk : conn_sig.chunks())
-                                               if (sig_bit_ref.count(chunk) != 0) {
-                                                       bit_ref_t &bit_ref = sig_bit_ref[chunk];
-                                                       graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
-                                               }
-                               }
+                               bit_ref_t &bit_ref = sig_bit_ref[bit];
+                               graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i);
+                       }
                }
+       }
 
-               // mark external signals (used in module ports)
-               for (auto &wire_it : mod->wires)
-               {
-                       RTLIL::Wire *wire = wire_it.second;
-                       if (wire->port_id > 0)
+       // mark external signals (used in non-selected cells)
+       for (auto &cell_it : mod->cells_)
+       {
+               RTLIL::Cell *cell = cell_it.second;
+               if (sel && !sel->selected(mod, cell))
+                       for (auto &conn : cell->connections())
                        {
-                               RTLIL::SigSpec conn_sig(wire);
+                               RTLIL::SigSpec conn_sig = conn.second;
                                sigmap.apply(conn_sig);
-                               conn_sig.expand();
 
-                               for (auto &chunk : conn_sig.chunks())
-                                       if (sig_bit_ref.count(chunk) != 0) {
-                                               bit_ref_t &bit_ref = sig_bit_ref[chunk];
+                               for (auto &bit : conn_sig)
+                                       if (sig_bit_ref.count(bit) != 0) {
+                                               bit_ref_t &bit_ref = sig_bit_ref[bit];
                                                graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
                                        }
                        }
-               }
-
-               // graph.print();
-               return true;
        }
 
-       RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
+       // mark external signals (used in module ports)
+       for (auto &wire_it : mod->wires_)
        {
-               SigMap sigmap(needle);
-               SigSet<std::pair<std::string, int>> sig2port;
-
-               // create new cell
-               RTLIL::Cell *cell = new RTLIL::Cell;
-               cell->name = stringf("$extract$%s$%d", needle->name.c_str(), RTLIL::autoidx++);
-               cell->type = needle->name;
-               haystack->add(cell);
-
-               // create cell ports
-               for (auto &it : needle->wires) {
-                       RTLIL::Wire *wire = it.second;
-                       if (wire->port_id > 0) {
-                               for (int i = 0; i < wire->width; i++)
-                                       sig2port.insert(sigmap(RTLIL::SigSpec(wire, 1, i)), std::pair<std::string, int>(wire->name, i));
-                               cell->connections[wire->name] = RTLIL::SigSpec(RTLIL::State::Sz, wire->width);
-                       }
+               RTLIL::Wire *wire = wire_it.second;
+               if (wire->port_id > 0)
+               {
+                       RTLIL::SigSpec conn_sig(wire);
+                       sigmap.apply(conn_sig);
+
+                       for (auto &bit : conn_sig)
+                               if (sig_bit_ref.count(bit) != 0) {
+                                       bit_ref_t &bit_ref = sig_bit_ref[bit];
+                                       graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
+                               }
                }
+       }
 
-               // delete replaced cells and connect new ports
-               for (auto &it : match.mappings)
-               {
-                       auto &mapping = it.second;
-                       RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
-                       RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;
+       // graph.print();
+       return true;
+}
 
-                       if (needle_cell == NULL)
-                               continue;
+RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
+{
+       SigMap sigmap(needle);
+       SigSet<std::pair<RTLIL::IdString, int>> sig2port;
+
+       // create new cell
+       RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name);
+
+       // create cell ports
+       for (auto &it : needle->wires_) {
+               RTLIL::Wire *wire = it.second;
+               if (wire->port_id > 0) {
+                       for (int i = 0; i < wire->width; i++)
+                               sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i));
+                       cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width));
+               }
+       }
 
-                       for (auto &conn : needle_cell->connections) {
-                               RTLIL::SigSpec sig = sigmap(conn.second);
-                               if (mapping.portMapping.count(conn.first) > 0 && sig2port.has(sigmap(sig))) {
-                                       sig.expand();
-                                       for (int i = 0; i < sig.size(); i++)
-                                       for (auto &port : sig2port.find(sig.chunks()[i])) {
-                                               RTLIL::SigSpec bitsig = haystack_cell->connections.at(mapping.portMapping[conn.first]).extract(i, 1);
-                                               cell->connections.at(port.first).replace(port.second, bitsig);
-                                       }
+       // delete replaced cells and connect new ports
+       for (auto &it : match.mappings)
+       {
+               auto &mapping = it.second;
+               RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
+               RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;
+
+               if (needle_cell == NULL)
+                       continue;
+
+               for (auto &conn : needle_cell->connections()) {
+                       RTLIL::SigSpec sig = sigmap(conn.second);
+                       if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) {
+                               for (int i = 0; i < sig.size(); i++)
+                               for (auto &port : sig2port.find(sig[i])) {
+                                       RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1);
+                                       RTLIL::SigSpec new_sig = cell->getPort(port.first);
+                                       new_sig.replace(port.second, bitsig);
+                                       cell->setPort(port.first, new_sig);
                                }
                        }
-
-                       haystack->cells.erase(haystack_cell->name);
-                       delete haystack_cell;
                }
 
-               return cell;
+               haystack->remove(haystack_cell);
        }
 
-       bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
-       {
-               int left_idx = 0, right_idx = 0;
-               if (left->attributes.count("\\extract_order") > 0)
-                       left_idx = left->attributes.at("\\extract_order").as_int();
-               if (right->attributes.count("\\extract_order") > 0)
-                       right_idx = right->attributes.at("\\extract_order").as_int();
-               if (left_idx != right_idx)
-                       return left_idx < right_idx;
-               return left->name < right->name;
-       }
+       return cell;
+}
+
+bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
+{
+       int left_idx = 0, right_idx = 0;
+       if (left->attributes.count(ID(extract_order)) > 0)
+               left_idx = left->attributes.at(ID(extract_order)).as_int();
+       if (right->attributes.count(ID(extract_order)) > 0)
+               right_idx = right->attributes.at(ID(extract_order)).as_int();
+       if (left_idx != right_idx)
+               return left_idx < right_idx;
+       return left->name < right->name;
 }
 
 struct ExtractPass : public Pass {
        ExtractPass() : Pass("extract", "find subcircuits and replace them with cells") { }
-       virtual void help()
+       void help() YS_OVERRIDE
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -373,7 +361,7 @@ struct ExtractPass : public Pass {
                log("\n");
                log("This pass looks for subcircuits that are isomorphic to any of the modules\n");
                log("in the given map file and replaces them with instances of this modules. The\n");
-               log("map file can be a verilog source file (*.v) or an ilang file (*.il).\n");
+               log("map file can be a Verilog source file (*.v) or an ilang file (*.il).\n");
                log("\n");
                log("    -map <map_file>\n");
                log("        use the modules in this file as reference. This option can be used\n");
@@ -402,11 +390,11 @@ struct ExtractPass : public Pass {
                log("        match. This option can be used multiple times.\n");
                log("\n");
                log("    -swap <needle_type> <port1>,<port2>[,...]\n");
-               log("        Register a set of swapable ports for a needle cell type.\n");
+               log("        Register a set of swappable ports for a needle cell type.\n");
                log("        This option can be used multiple times.\n");
                log("\n");
                log("    -perm <needle_type> <port1>,<port2>[,...] <portA>,<portB>[,...]\n");
-               log("        Register a valid permutation of swapable ports for a needle\n");
+               log("        Register a valid permutation of swappable ports for a needle\n");
                log("        cell type. This option can be used multiple times.\n");
                log("\n");
                log("    -cell_attr <attribute_name>\n");
@@ -421,7 +409,7 @@ struct ExtractPass : public Pass {
                log("    -ignore_param <cell_type> <parameter_name>\n");
                log("        Do not use this parameter when matching cells.\n");
                log("\n");
-               log("This pass does not operate on modules with uprocessed processes in it.\n");
+               log("This pass does not operate on modules with unprocessed processes in it.\n");
                log("(I.e. the 'proc' pass should be used first to convert processes to netlists.)\n");
                log("\n");
                log("This pass can also be used for mining for frequent subcircuits. In this mode\n");
@@ -452,9 +440,9 @@ struct ExtractPass : public Pass {
                log("See 'help techmap' for a pass that does the opposite thing.\n");
                log("\n");
        }
-       virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
-               log_header("Executing EXTRACT pass (map subcircuits to cells).\n");
+               log_header(design, "Executing EXTRACT pass (map subcircuits to cells).\n");
                log_push();
 
                SubCircuitSolver solver;
@@ -530,24 +518,21 @@ struct ExtractPass : public Pass {
                        if (args[argidx] == "-swap" && argidx+2 < args.size()) {
                                std::string type = RTLIL::escape_id(args[++argidx]);
                                std::set<std::string> ports;
-                               char *ports_str = strdup(args[++argidx].c_str());
-                               for (char *sptr, *p = strtok_r(ports_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+                               std::string ports_str = args[++argidx], p;
+                               while (!(p = next_token(ports_str, ",\t\r\n ")).empty())
                                        ports.insert(RTLIL::escape_id(p));
-                               free(ports_str);
                                solver.addSwappablePorts(type, ports);
                                continue;
                        }
                        if (args[argidx] == "-perm" && argidx+3 < args.size()) {
                                std::string type = RTLIL::escape_id(args[++argidx]);
                                std::vector<std::string> map_left, map_right;
-                               char *left_str = strdup(args[++argidx].c_str());
-                               char *right_str = strdup(args[++argidx].c_str());
-                               for (char *sptr, *p = strtok_r(left_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+                               std::string left_str = args[++argidx];
+                               std::string right_str = args[++argidx], p;
+                               while (!(p = next_token(left_str, ",\t\r\n ")).empty())
                                        map_left.push_back(RTLIL::escape_id(p));
-                               for (char *sptr, *p = strtok_r(right_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+                               while (!(p = next_token(right_str, ",\t\r\n ")).empty())
                                        map_right.push_back(RTLIL::escape_id(p));
-                               free(left_str);
-                               free(right_str);
                                if (map_left.size() != map_right.size())
                                        log_cmd_error("Arguments to -perm are not a valid permutation!\n");
                                std::map<std::string, std::string> map;
@@ -573,7 +558,7 @@ struct ExtractPass : public Pass {
                                continue;
                        }
                        if (args[argidx] == "-ignore_param" && argidx+2 < args.size()) {
-                               solver.ignored_parameters.insert(std::pair<std::string, std::string>(RTLIL::escape_id(args[argidx+1]), RTLIL::escape_id(args[argidx+2])));
+                               solver.ignored_parameters.insert(std::pair<RTLIL::IdString, RTLIL::IdString>(RTLIL::escape_id(args[argidx+1]), RTLIL::escape_id(args[argidx+2])));
                                argidx += 2;
                                continue;
                        }
@@ -609,27 +594,29 @@ struct ExtractPass : public Pass {
                        map = new RTLIL::Design;
                        for (auto &filename : map_filenames)
                        {
-                               if (filename.substr(0, 1) == "%")
+                               if (filename.compare(0, 1, "%") == 0)
                                {
                                        if (!saved_designs.count(filename.substr(1))) {
                                                delete map;
                                                log_cmd_error("Can't saved design `%s'.\n", filename.c_str()+1);
                                        }
-                                       for (auto &it : saved_designs.at(filename.substr(1))->modules)
-                                               if (!map->modules.count(it.first))
-                                                       map->modules[it.first] = it.second->clone();
+                                       for (auto mod : saved_designs.at(filename.substr(1))->modules())
+                                               if (!map->has(mod->name))
+                                                       map->add(mod->clone());
                                }
                                else
                                {
-                                       FILE *f = fopen(filename.c_str(), "rt");
-                                       if (f == NULL) {
+                                       std::ifstream f;
+                                       rewrite_filename(filename);
+                                       f.open(filename.c_str());
+                                       if (f.fail()) {
                                                delete map;
                                                log_cmd_error("Can't open map file `%s'.\n", filename.c_str());
                                        }
-                                       Frontend::frontend_call(map, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
-                                       fclose(f);
+                                       Frontend::frontend_call(map, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
+                                       f.close();
 
-                                       if (filename.size() <= 3 || filename.substr(filename.size()-3) != ".il") {
+                                       if (filename.size() <= 3 || filename.compare(filename.size()-3, std::string::npos, ".il") != 0) {
                                                Pass::call(map, "proc");
                                                Pass::call(map, "opt_clean");
                                        }
@@ -640,10 +627,10 @@ struct ExtractPass : public Pass {
                std::map<std::string, RTLIL::Module*> needle_map, haystack_map;
                std::vector<RTLIL::Module*> needle_list;
 
-               log_header("Creating graphs for SubCircuit library.\n");
+               log_header(design, "Creating graphs for SubCircuit library.\n");
 
                if (!mine_mode)
-                       for (auto &mod_it : map->modules) {
+                       for (auto &mod_it : map->modules_) {
                                SubCircuit::Graph mod_graph;
                                std::string graph_name = "needle_" + RTLIL::unescape_id(mod_it.first);
                                log("Creating needle graph %s.\n", graph_name.c_str());
@@ -654,7 +641,7 @@ struct ExtractPass : public Pass {
                                }
                        }
 
-               for (auto &mod_it : design->modules) {
+               for (auto &mod_it : design->modules_) {
                        SubCircuit::Graph mod_graph;
                        std::string graph_name = "haystack_" + RTLIL::unescape_id(mod_it.first);
                        log("Creating haystack graph %s.\n", graph_name.c_str());
@@ -663,11 +650,11 @@ struct ExtractPass : public Pass {
                                haystack_map[graph_name] = mod_it.second;
                        }
                }
-               
+
                if (!mine_mode)
                {
                        std::vector<SubCircuit::Solver::Result> results;
-                       log_header("Running solver from SubCircuit library.\n");
+                       log_header(design, "Running solver from SubCircuit library.\n");
 
                        std::sort(needle_list.begin(), needle_list.end(), compareSortNeedleList);
 
@@ -676,11 +663,11 @@ struct ExtractPass : public Pass {
                                log("Solving for %s in %s.\n", ("needle_" + RTLIL::unescape_id(needle->name)).c_str(), haystack_it.first.c_str());
                                solver.solve(results, "needle_" + RTLIL::unescape_id(needle->name), haystack_it.first, false);
                        }
-                       log("Found %zd matches.\n", results.size());
+                       log("Found %d matches.\n", GetSize(results));
 
                        if (results.size() > 0)
                        {
-                               log_header("Substitute SubCircuits with cells.\n");
+                               log_header(design, "Substitute SubCircuits with cells.\n");
 
                                for (int i = 0; i < int(results.size()); i++) {
                                        auto &result = results[i];
@@ -701,7 +688,7 @@ struct ExtractPass : public Pass {
                {
                        std::vector<SubCircuit::Solver::MineResult> results;
 
-                       log_header("Running miner from SubCircuit library.\n");
+                       log_header(design, "Running miner from SubCircuit library.\n");
                        solver.mine(results, mine_cells_min, mine_cells_max, mine_min_freq, mine_limit_mod);
 
                        map = new RTLIL::Design;
@@ -712,7 +699,7 @@ struct ExtractPass : public Pass {
                                log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
                                log("  primary match in %s:", id2cstr(haystack_map.at(result.graphId)->name));
                                for (auto &node : result.nodes)
-                                       log(" %s", id2cstr(node.nodeId));
+                                       log(" %s", RTLIL::unescape_id(node.nodeId).c_str());
                                log("\n");
                                for (auto &it : result.matchesPerGraph)
                                        log("  matches in %s: %d\n", id2cstr(haystack_map.at(it.first)->name), it.second);
@@ -727,7 +714,7 @@ struct ExtractPass : public Pass {
                                        cells.insert((RTLIL::Cell*)node.userData);
 
                                for (auto cell : cells)
-                               for (auto &conn : cell->connections) {
+                               for (auto &conn : cell->connections()) {
                                        RTLIL::SigSpec sig = sigmap(conn.second);
                                        for (auto &chunk : sig.chunks())
                                                if (chunk.wire != NULL)
@@ -736,44 +723,41 @@ struct ExtractPass : public Pass {
 
                                RTLIL::Module *newMod = new RTLIL::Module;
                                newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, id2cstr(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits);
-                               map->modules[newMod->name] = newMod;
+                               map->add(newMod);
 
-                               int portCounter = 1;
                                for (auto wire : wires) {
-                                       RTLIL::Wire *newWire = new RTLIL::Wire;
-                                       newWire->name = wire->name;
-                                       newWire->width = wire->width;
-                                       newWire->port_id = portCounter++;
+                                       RTLIL::Wire *newWire = newMod->addWire(wire->name, wire->width);
                                        newWire->port_input = true;
                                        newWire->port_output = true;
-                                       newMod->add(newWire);
                                }
 
+                               newMod->fixup_ports();
+
                                for (auto cell : cells) {
-                                       RTLIL::Cell *newCell = new RTLIL::Cell;
-                                       newCell->name = cell->name;
-                                       newCell->type = cell->type;
+                                       RTLIL::Cell *newCell = newMod->addCell(cell->name, cell->type);
                                        newCell->parameters = cell->parameters;
-                                       for (auto &conn : cell->connections) {
-                                               RTLIL::SigSpec sig = sigmap(conn.second);
-                                               for (auto &chunk : sig.chunks())
+                                       for (auto &conn : cell->connections()) {
+                                               std::vector<SigChunk> chunks = sigmap(conn.second);
+                                               for (auto &chunk : chunks)
                                                        if (chunk.wire != NULL)
-                                                               chunk.wire = newMod->wires.at(chunk.wire->name);
-                                               newCell->connections[conn.first] = sig;
+                                                               chunk.wire = newMod->wires_.at(chunk.wire->name);
+                                               newCell->setPort(conn.first, chunks);
                                        }
-                                       newMod->add(newCell);
                                }
                        }
 
-                       FILE *f = fopen(mine_outfile.c_str(), "wt");
-                       if (f == NULL)
+                       std::ofstream f;
+                       rewrite_filename(mine_outfile);
+                       f.open(mine_outfile.c_str(), std::ofstream::trunc);
+                       if (f.fail())
                                log_error("Can't open output file `%s'.\n", mine_outfile.c_str());
-                       Backend::backend_call(map, f, mine_outfile, "ilang");
-                       fclose(f);
+                       Backend::backend_call(map, &f, mine_outfile, "ilang");
+                       f.close();
                }
 
                delete map;
                log_pop();
        }
 } ExtractPass;
+
+PRIVATE_NAMESPACE_END