3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-03 01:40:23 +00:00

Compute is_port in AbcPass without iterating through all cells and wires in the module every time we run ABC.

This does not scale when we run ABC thousands of times in a single AbcPass.
This commit is contained in:
Robert O'Callahan 2025-07-27 23:44:41 +00:00
parent d3b0c0df1a
commit a54a673586
5 changed files with 264 additions and 91 deletions

View file

@ -27,10 +27,10 @@ YOSYS_NAMESPACE_BEGIN
struct FfInitVals struct FfInitVals
{ {
const SigMap *sigmap; const SigMapView *sigmap;
dict<SigBit, std::pair<State,SigBit>> initbits; dict<SigBit, std::pair<State,SigBit>> initbits;
void set(const SigMap *sigmap_, RTLIL::Module *module) void set(const SigMapView *sigmap_, RTLIL::Module *module)
{ {
sigmap = sigmap_; sigmap = sigmap_;
initbits.clear(); initbits.clear();
@ -126,7 +126,7 @@ struct FfInitVals
initbits.clear(); initbits.clear();
} }
FfInitVals (const SigMap *sigmap, RTLIL::Module *module) FfInitVals (const SigMapView *sigmap, RTLIL::Module *module)
{ {
set(sigmap, module); set(sigmap, module);
} }

View file

@ -58,7 +58,7 @@ YOSYS_NAMESPACE_BEGIN
struct FfMergeHelper struct FfMergeHelper
{ {
const SigMap *sigmap; const SigMapView *sigmap;
RTLIL::Module *module; RTLIL::Module *module;
FfInitVals *initvals; FfInitVals *initvals;

View file

@ -1327,7 +1327,8 @@ public:
return p; return p;
} }
// Merge sets if the given indices belong to different sets // Merge sets if the given indices belong to different sets.
// Makes ifind(j) the root of the merged set.
void imerge(int i, int j) void imerge(int i, int j)
{ {
i = ifind(i); i = ifind(i);

View file

@ -237,6 +237,42 @@ using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell
template<typename T> template<typename T>
class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {}; class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};
struct SigMapView
{
mfp<SigBit> database;
// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
}
void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
apply(bit);
}
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
{
apply(bit);
return bit;
}
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
SigSpec sig(wire);
apply(sig);
return sig;
}
};
/** /**
* SigMap wraps a union-find "database" * SigMap wraps a union-find "database"
* to map SigBits of a module to canonical representative SigBits. * to map SigBits of a module to canonical representative SigBits.
@ -244,10 +280,8 @@ class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name
* If a SigBit has a const state (impl: bit.wire is nullptr), * If a SigBit has a const state (impl: bit.wire is nullptr),
* it's promoted to a representative. * it's promoted to a representative.
*/ */
struct SigMap struct SigMap final : public SigMapView
{ {
mfp<SigBit> database;
SigMap(RTLIL::Module *module = NULL) SigMap(RTLIL::Module *module = NULL)
{ {
if (module != NULL) if (module != NULL)
@ -320,37 +354,6 @@ struct SigMap
inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); } inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); }
// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
}
void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
apply(bit);
}
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
{
apply(bit);
return bit;
}
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
SigSpec sig(wire);
apply(sig);
return sig;
}
// All non-const bits // All non-const bits
RTLIL::SigSpec allbits() const RTLIL::SigSpec allbits() const
{ {
@ -362,6 +365,107 @@ struct SigMap
} }
}; };
/**
* SiValgMap wraps a union-find "database" to map SigBits of a module to
* canonical representative SigBits plus some optional Val value associated with the bits.
* Val has a commutative, associative, idempotent operator|=, a default constructor
* which constructs an identity element, and a copy constructor.
* SigBits that are connected share a set in the underlying database;
* the associated value is the "sum" of all the values associated with the contributing bits.
* If any of the SigBits in a set are a constant, the canonical SigBit is a constant.
*/
template <class Val>
struct SigValMap final : public SigMapView
{
dict<SigBit, Val> values;
void swap(SigValMap<Val> &other)
{
database.swap(other.database);
values.swap(other.values);
}
void clear()
{
database.clear();
values.clear();
}
// Rebuild SigMap for all connections in module
void set(RTLIL::Module *module)
{
int bitcount = 0;
for (auto &it : module->connections())
bitcount += it.first.size();
database.clear();
values.clear();
database.reserve(bitcount);
for (auto &it : module->connections())
add(it.first, it.second);
}
// Add connections from "from" to "to", bit-by-bit.
void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to)
{
log_assert(GetSize(from) == GetSize(to));
for (int i = 0; i < GetSize(from); i++)
{
int bfi = database.lookup(from[i]);
int bti = database.lookup(to[i]);
if (bfi == bti) {
continue;
}
const RTLIL::SigBit &bf = database[bfi];
const RTLIL::SigBit &bt = database[bti];
if (bf.wire == nullptr) {
// bf is constant so make it the canonical representative.
database.imerge(bti, bfi);
merge_value(bt, bf);
} else {
// Make bt the canonical representative.
database.imerge(bfi, bti);
merge_value(bf, bt);
}
}
}
void addVal(const RTLIL::SigBit &bit, const Val &val)
{
values[database.find(bit)] |= val;
}
void addVal(const RTLIL::SigSpec &sig, const Val &val)
{
for (const auto &bit : sig)
addVal(bit, val);
}
Val apply_and_get_value(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
auto it = values.find(bit);
return it == values.end() ? Val() : it->second;
}
private:
void merge_value(const RTLIL::SigBit &from, const RTLIL::SigBit &to)
{
auto it = values.find(from);
if (it == values.end()) {
return;
}
// values[to] could resize the underlying `entries` so
// finish using `it` first.
Val v = it->second;
values.erase(it);
values[to] |= v;
}
};
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END
#endif /* SIGTOOLS_H */ #endif /* SIGTOOLS_H */

View file

@ -138,6 +138,18 @@ struct AbcConfig
bool abc_dress = false; bool abc_dress = false;
}; };
struct AbcSigVal {
bool is_port;
AbcSigVal(bool is_port = false) : is_port(is_port) {}
AbcSigVal &operator|=(const AbcSigVal &other) {
is_port |= other.is_port;
return *this;
}
};
using AbcSigMap = SigValMap<AbcSigVal>;
struct AbcModuleState { struct AbcModuleState {
const AbcConfig &config; const AbcConfig &config;
@ -161,21 +173,21 @@ struct AbcModuleState {
AbcModuleState(const AbcConfig &config) : config(config) {} AbcModuleState(const AbcConfig &config) : config(config) {}
int map_signal(const SigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1); int map_signal(const AbcSigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1);
void mark_port(const SigMap &assign_map, RTLIL::SigSpec sig); void mark_port(const AbcSigMap &assign_map, RTLIL::SigSpec sig);
void extract_cell(const SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff); bool extract_cell(const AbcSigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff);
std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr); std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr);
void dump_loop_graph(FILE *f, int &nr, dict<int, pool<int>> &edges, pool<int> &workpool, std::vector<int> &in_counts); void dump_loop_graph(FILE *f, int &nr, dict<int, pool<int>> &edges, pool<int> &workpool, std::vector<int> &in_counts);
void handle_loops(SigMap &assign_map, RTLIL::Module *module); void handle_loops(AbcSigMap &assign_map, RTLIL::Module *module);
void abc_module(RTLIL::Design *design, RTLIL::Module *module, SigMap &assign_map, const std::vector<RTLIL::Cell*> &cells, void abc_module(RTLIL::Design *design, RTLIL::Module *module, AbcSigMap &assign_map, const std::vector<RTLIL::Cell*> &cells,
bool dff_mode, std::string clk_str); bool dff_mode, std::string clk_str);
void extract(SigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module); void extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module);
void finish(); void finish();
}; };
int AbcModuleState::map_signal(const SigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type, int in1, int in2, int in3, int in4) int AbcModuleState::map_signal(const AbcSigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type, int in1, int in2, int in3, int in4)
{ {
assign_map.apply(bit); AbcSigVal val = assign_map.apply_and_get_value(bit);
if (bit == State::Sx) if (bit == State::Sx)
undef_bits_lost++; undef_bits_lost++;
@ -188,7 +200,7 @@ int AbcModuleState::map_signal(const SigMap &assign_map, RTLIL::SigBit bit, gate
gate.in2 = -1; gate.in2 = -1;
gate.in3 = -1; gate.in3 = -1;
gate.in4 = -1; gate.in4 = -1;
gate.is_port = false; gate.is_port = bit.wire != nullptr && val.is_port;
gate.bit = bit; gate.bit = bit;
gate.init = initvals(bit); gate.init = initvals(bit);
signal_list.push_back(gate); signal_list.push_back(gate);
@ -211,40 +223,40 @@ int AbcModuleState::map_signal(const SigMap &assign_map, RTLIL::SigBit bit, gate
return gate.id; return gate.id;
} }
void AbcModuleState::mark_port(const SigMap &assign_map, RTLIL::SigSpec sig) void AbcModuleState::mark_port(const AbcSigMap &assign_map, RTLIL::SigSpec sig)
{ {
for (auto &bit : assign_map(sig)) for (auto &bit : assign_map(sig))
if (bit.wire != nullptr && signal_map.count(bit) > 0) if (bit.wire != nullptr && signal_map.count(bit) > 0)
signal_list[signal_map[bit]].is_port = true; signal_list[signal_map[bit]].is_port = true;
} }
void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff) bool AbcModuleState::extract_cell(const AbcSigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff)
{ {
if (RTLIL::builtin_ff_cell_types().count(cell->type)) { if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
FfData ff(&initvals, cell); FfData ff(&initvals, cell);
gate_type_t type = G(FF); gate_type_t type = G(FF);
if (!ff.has_clk) if (!ff.has_clk)
return; return false;
if (ff.has_gclk) if (ff.has_gclk)
return; return false;
if (ff.has_aload) if (ff.has_aload)
return; return false;
if (ff.has_sr) if (ff.has_sr)
return; return false;
if (!ff.is_fine) if (!ff.is_fine)
return; return false;
if (clk_polarity != ff.pol_clk) if (clk_polarity != ff.pol_clk)
return; return false;
if (clk_sig != assign_map(ff.sig_clk)) if (clk_sig != assign_map(ff.sig_clk))
return; return false;
if (ff.has_ce) { if (ff.has_ce) {
if (en_polarity != ff.pol_ce) if (en_polarity != ff.pol_ce)
return; return false;
if (en_sig != assign_map(ff.sig_ce)) if (en_sig != assign_map(ff.sig_ce))
return; return false;
} else { } else {
if (GetSize(en_sig) != 0) if (GetSize(en_sig) != 0)
return; return false;
} }
if (ff.val_init == State::S1) { if (ff.val_init == State::S1) {
type = G(FF1); type = G(FF1);
@ -255,39 +267,39 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
} }
if (ff.has_arst) { if (ff.has_arst) {
if (arst_polarity != ff.pol_arst) if (arst_polarity != ff.pol_arst)
return; return false;
if (arst_sig != assign_map(ff.sig_arst)) if (arst_sig != assign_map(ff.sig_arst))
return; return false;
if (ff.val_arst == State::S1) { if (ff.val_arst == State::S1) {
if (type == G(FF0)) if (type == G(FF0))
return; return false;
type = G(FF1); type = G(FF1);
} else if (ff.val_arst == State::S0) { } else if (ff.val_arst == State::S0) {
if (type == G(FF1)) if (type == G(FF1))
return; return false;
type = G(FF0); type = G(FF0);
} }
} else { } else {
if (GetSize(arst_sig) != 0) if (GetSize(arst_sig) != 0)
return; return false;
} }
if (ff.has_srst) { if (ff.has_srst) {
if (srst_polarity != ff.pol_srst) if (srst_polarity != ff.pol_srst)
return; return false;
if (srst_sig != assign_map(ff.sig_srst)) if (srst_sig != assign_map(ff.sig_srst))
return; return false;
if (ff.val_srst == State::S1) { if (ff.val_srst == State::S1) {
if (type == G(FF0)) if (type == G(FF0))
return; return false;
type = G(FF1); type = G(FF1);
} else if (ff.val_srst == State::S0) { } else if (ff.val_srst == State::S0) {
if (type == G(FF1)) if (type == G(FF1))
return; return false;
type = G(FF0); type = G(FF0);
} }
} else { } else {
if (GetSize(srst_sig) != 0) if (GetSize(srst_sig) != 0)
return; return false;
} }
int gate_id = map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d)); int gate_id = map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d));
@ -301,7 +313,7 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d)); map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d));
ff.remove(); ff.remove();
return; return true;
} }
if (cell->type.in(ID($_BUF_), ID($_NOT_))) if (cell->type.in(ID($_BUF_), ID($_NOT_)))
@ -315,7 +327,7 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
map_signal(assign_map, sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(assign_map, sig_a)); map_signal(assign_map, sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(assign_map, sig_a));
module->remove(cell); module->remove(cell);
return; return true;
} }
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_))) if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
@ -351,7 +363,7 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
log_abort(); log_abort();
module->remove(cell); module->remove(cell);
return; return true;
} }
if (cell->type.in(ID($_MUX_), ID($_NMUX_))) if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
@ -373,7 +385,7 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
map_signal(assign_map, sig_y, cell->type == ID($_MUX_) ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s); map_signal(assign_map, sig_y, cell->type == ID($_MUX_) ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
module->remove(cell); module->remove(cell);
return; return true;
} }
if (cell->type.in(ID($_AOI3_), ID($_OAI3_))) if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
@ -395,7 +407,7 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
map_signal(assign_map, sig_y, cell->type == ID($_AOI3_) ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c); map_signal(assign_map, sig_y, cell->type == ID($_AOI3_) ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
module->remove(cell); module->remove(cell);
return; return true;
} }
if (cell->type.in(ID($_AOI4_), ID($_OAI4_))) if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
@ -420,8 +432,10 @@ void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *modul
map_signal(assign_map, sig_y, cell->type == ID($_AOI4_) ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d); map_signal(assign_map, sig_y, cell->type == ID($_AOI4_) ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
module->remove(cell); module->remove(cell);
return; return true;
} }
return false;
} }
std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire) std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire)
@ -492,13 +506,13 @@ void AbcModuleState::dump_loop_graph(FILE *f, int &nr, dict<int, pool<int>> &edg
fprintf(f, "}\n"); fprintf(f, "}\n");
} }
void connect(SigMap &assign_map, RTLIL::Module *module, const RTLIL::SigSig &conn) void connect(AbcSigMap &assign_map, RTLIL::Module *module, const RTLIL::SigSig &conn)
{ {
module->connect(conn); module->connect(conn);
assign_map.add(conn.first, conn.second); assign_map.add(conn.first, conn.second);
} }
void AbcModuleState::handle_loops(SigMap &assign_map, RTLIL::Module *module) void AbcModuleState::handle_loops(AbcSigMap &assign_map, RTLIL::Module *module)
{ {
// http://en.wikipedia.org/wiki/Topological_sorting // http://en.wikipedia.org/wiki/Topological_sorting
// (Kahn, Arthur B. (1962), "Topological sorting of large networks") // (Kahn, Arthur B. (1962), "Topological sorting of large networks")
@ -758,7 +772,7 @@ struct abc_output_filter
} }
}; };
void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, SigMap &assign_map, const std::vector<RTLIL::Cell*> &cells, void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, AbcSigMap &assign_map, const std::vector<RTLIL::Cell*> &cells,
bool dff_mode, std::string clk_str) bool dff_mode, std::string clk_str)
{ {
initvals.set(&assign_map, module); initvals.set(&assign_map, module);
@ -943,18 +957,18 @@ void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, Si
undef_bits_lost = 0; undef_bits_lost = 0;
had_init = false; had_init = false;
std::vector<RTLIL::Cell *> kept_cells;
for (auto c : cells) for (auto c : cells)
extract_cell(assign_map, module, c, config.keepff); if (!extract_cell(assign_map, module, c, config.keepff))
kept_cells.push_back(c);
if (undef_bits_lost) if (undef_bits_lost)
log("Replacing %d occurrences of constant undef bits with constant zero bits\n", undef_bits_lost); log("Replacing %d occurrences of constant undef bits with constant zero bits\n", undef_bits_lost);
for (auto wire : module->wires()) { // Wires with port_id > 0 and connections to cells outside our cell set have already
if (wire->port_id > 0) // been accounted for via AbcSigVal::is_port. Now we just need to account for
mark_port(assign_map, wire); // connections to cells inside our cell set that weren't removed by extract_cell().
} for (auto cell : kept_cells)
for (auto cell : module->cells())
for (auto &port_it : cell->connections()) for (auto &port_it : cell->connections())
mark_port(assign_map, port_it.second); mark_port(assign_map, port_it.second);
@ -1213,7 +1227,7 @@ void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, Si
log("Don't call ABC as there is nothing to map.\n"); log("Don't call ABC as there is nothing to map.\n");
} }
void AbcModuleState::extract(SigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module) void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module)
{ {
if (!did_run_abc) { if (!did_run_abc) {
return; return;
@ -1510,6 +1524,47 @@ void AbcModuleState::finish()
log_pop(); log_pop();
} }
// For every signal that connects cells from different sets, or a cell in a set to a cell not in any set,
// mark it as a port in `assign_map`.
void assign_cell_connection_ports(RTLIL::Module *module, const std::vector<std::vector<RTLIL::Cell *> *> &cell_sets,
AbcSigMap &assign_map)
{
pool<RTLIL::Cell *> cells_in_no_set;
for (RTLIL::Cell *cell : module->cells()) {
cells_in_no_set.insert(cell);
}
// For every canonical signal in `assign_map`, the index of the set it is connected to,
// or -1 if it connects a cell in one set to a cell in another set or not in any set.
dict<SigBit, int> signal_cell_set;
for (int i = 0; i < int(cell_sets.size()); ++i) {
for (RTLIL::Cell *cell : *cell_sets[i]) {
cells_in_no_set.erase(cell);
for (auto &port_it : cell->connections()) {
for (SigBit bit : port_it.second) {
assign_map.apply(bit);
auto it = signal_cell_set.find(bit);
if (it == signal_cell_set.end())
signal_cell_set[bit] = i;
else if (it->second >= 0 && it->second != i) {
it->second = -1;
assign_map.addVal(bit, AbcSigVal(true));
}
}
}
}
}
for (RTLIL::Cell *cell : cells_in_no_set) {
for (auto &port_it : cell->connections()) {
for (SigBit bit : port_it.second) {
assign_map.apply(bit);
auto it = signal_cell_set.find(bit);
if (it != signal_cell_set.end() && it->second >= 0)
assign_map.addVal(bit, AbcSigVal(true));
}
}
}
}
struct AbcPass : public Pass { struct AbcPass : public Pass {
AbcPass() : Pass("abc", "use ABC for technology mapping") { } AbcPass() : Pass("abc", "use ABC for technology mapping") { }
void help() override void help() override
@ -2084,17 +2139,24 @@ struct AbcPass : public Pass {
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())
{ {
SigMap assign_map;
assign_map.set(mod);
if (mod->processes.size() > 0) { if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod)); log("Skipping module %s as it contains processes.\n", log_id(mod));
continue; continue;
} }
AbcSigMap assign_map;
assign_map.set(mod);
for (auto wire : mod->wires())
if (wire->port_id > 0)
assign_map.addVal(SigSpec(wire), AbcSigVal(true));
if (!dff_mode || !clk_str.empty()) { if (!dff_mode || !clk_str.empty()) {
std::vector<RTLIL::Cell*> cells = mod->selected_cells();
assign_cell_connection_ports(mod, {&cells}, assign_map);
AbcModuleState state(config); AbcModuleState state(config);
state.abc_module(design, mod, assign_map, mod->selected_cells(), dff_mode, clk_str); state.abc_module(design, mod, assign_map, cells, dff_mode, clk_str);
state.extract(assign_map, design, mod); state.extract(assign_map, design, mod);
state.finish(); state.finish();
continue; continue;
@ -2250,6 +2312,12 @@ struct AbcPass : public Pass {
std::get<4>(it.first) ? "" : "!", log_signal(std::get<5>(it.first)), std::get<4>(it.first) ? "" : "!", log_signal(std::get<5>(it.first)),
std::get<6>(it.first) ? "" : "!", log_signal(std::get<7>(it.first))); std::get<6>(it.first) ? "" : "!", log_signal(std::get<7>(it.first)));
{
std::vector<std::vector<RTLIL::Cell*>*> cell_sets;
for (auto &it : assigned_cells)
cell_sets.push_back(&it.second);
assign_cell_connection_ports(mod, cell_sets, assign_map);
}
for (auto &it : assigned_cells) { for (auto &it : assigned_cells) {
AbcModuleState state(config); AbcModuleState state(config);
state.clk_polarity = std::get<0>(it.first); state.clk_polarity = std::get<0>(it.first);