From d3b0c0df1adcef1cce02edf0c28821e42dcc5c89 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 17 Jul 2025 06:16:54 +0000 Subject: [PATCH] Preserve `assign_map` across ABC invocations. Currently `assign_map` is rebuilt from the module from scratch every time we invoke ABC. That doesn't scale when we do thousands of ABC runs over large modules. Instead, create it once and then maintain incrementally it as we update the module. --- passes/techmap/abc.cc | 130 ++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 62ce8da96..8a2816307 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -142,7 +142,6 @@ struct AbcModuleState { const AbcConfig &config; int map_autoidx = 0; - SigMap assign_map; std::vector signal_list; dict signal_map; FfInitVals initvals; @@ -162,19 +161,19 @@ struct AbcModuleState { AbcModuleState(const AbcConfig &config) : config(config) {} - int map_signal(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(RTLIL::SigSpec sig); - void extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool keepff); + 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); + void mark_port(const SigMap &assign_map, RTLIL::SigSpec sig); + void extract_cell(const SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff); std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr); void dump_loop_graph(FILE *f, int &nr, dict> &edges, pool &workpool, std::vector &in_counts); - void handle_loops(RTLIL::Module *module); - void abc_module(RTLIL::Design *design, RTLIL::Module *module, const std::vector &cells, + void handle_loops(SigMap &assign_map, RTLIL::Module *module); + void abc_module(RTLIL::Design *design, RTLIL::Module *module, SigMap &assign_map, const std::vector &cells, bool dff_mode, std::string clk_str); - void extract(RTLIL::Design *design, RTLIL::Module *module); + void extract(SigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module); void finish(); }; -int AbcModuleState::map_signal(RTLIL::SigBit bit, gate_type_t gate_type, int in1, int in2, int in3, int in4) +int AbcModuleState::map_signal(const SigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type, int in1, int in2, int in3, int in4) { assign_map.apply(bit); @@ -212,14 +211,14 @@ int AbcModuleState::map_signal(RTLIL::SigBit bit, gate_type_t gate_type, int in1 return gate.id; } -void AbcModuleState::mark_port(RTLIL::SigSpec sig) +void AbcModuleState::mark_port(const SigMap &assign_map, RTLIL::SigSpec sig) { for (auto &bit : assign_map(sig)) if (bit.wire != nullptr && signal_map.count(bit) > 0) signal_list[signal_map[bit]].is_port = true; } -void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool keepff) +void AbcModuleState::extract_cell(const SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff) { if (RTLIL::builtin_ff_cell_types().count(cell->type)) { FfData ff(&initvals, cell); @@ -291,7 +290,7 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool return; } - int gate_id = map_signal(ff.sig_q, type, map_signal(ff.sig_d)); + int gate_id = map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d)); if (keepff) { SigBit bit = ff.sig_q; if (assign_map(bit).wire != nullptr) { @@ -299,6 +298,8 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool } } + map_signal(assign_map, ff.sig_q, type, map_signal(assign_map, ff.sig_d)); + ff.remove(); return; } @@ -311,7 +312,7 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool assign_map.apply(sig_a); assign_map.apply(sig_y); - map_signal(sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(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); return; @@ -327,25 +328,25 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool assign_map.apply(sig_b); assign_map.apply(sig_y); - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); + int mapped_a = map_signal(assign_map, sig_a); + int mapped_b = map_signal(assign_map, sig_b); if (cell->type == ID($_AND_)) - map_signal(sig_y, G(AND), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(AND), mapped_a, mapped_b); else if (cell->type == ID($_NAND_)) - map_signal(sig_y, G(NAND), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(NAND), mapped_a, mapped_b); else if (cell->type == ID($_OR_)) - map_signal(sig_y, G(OR), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(OR), mapped_a, mapped_b); else if (cell->type == ID($_NOR_)) - map_signal(sig_y, G(NOR), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(NOR), mapped_a, mapped_b); else if (cell->type == ID($_XOR_)) - map_signal(sig_y, G(XOR), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(XOR), mapped_a, mapped_b); else if (cell->type == ID($_XNOR_)) - map_signal(sig_y, G(XNOR), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(XNOR), mapped_a, mapped_b); else if (cell->type == ID($_ANDNOT_)) - map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(ANDNOT), mapped_a, mapped_b); else if (cell->type == ID($_ORNOT_)) - map_signal(sig_y, G(ORNOT), mapped_a, mapped_b); + map_signal(assign_map, sig_y, G(ORNOT), mapped_a, mapped_b); else log_abort(); @@ -365,11 +366,11 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool assign_map.apply(sig_s); assign_map.apply(sig_y); - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); - int mapped_s = map_signal(sig_s); + int mapped_a = map_signal(assign_map, sig_a); + int mapped_b = map_signal(assign_map, sig_b); + int mapped_s = map_signal(assign_map, sig_s); - map_signal(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); return; @@ -387,11 +388,11 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool assign_map.apply(sig_c); assign_map.apply(sig_y); - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); - int mapped_c = map_signal(sig_c); + int mapped_a = map_signal(assign_map, sig_a); + int mapped_b = map_signal(assign_map, sig_b); + int mapped_c = map_signal(assign_map, sig_c); - map_signal(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); return; @@ -411,12 +412,12 @@ void AbcModuleState::extract_cell(RTLIL::Module *module, RTLIL::Cell *cell, bool assign_map.apply(sig_d); assign_map.apply(sig_y); - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); - int mapped_c = map_signal(sig_c); - int mapped_d = map_signal(sig_d); + int mapped_a = map_signal(assign_map, sig_a); + int mapped_b = map_signal(assign_map, sig_b); + int mapped_c = map_signal(assign_map, sig_c); + int mapped_d = map_signal(assign_map, sig_d); - map_signal(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); return; @@ -491,7 +492,13 @@ void AbcModuleState::dump_loop_graph(FILE *f, int &nr, dict> &edg fprintf(f, "}\n"); } -void AbcModuleState::handle_loops(RTLIL::Module *module) +void connect(SigMap &assign_map, RTLIL::Module *module, const RTLIL::SigSig &conn) +{ + module->connect(conn); + assign_map.add(conn.first, conn.second); +} + +void AbcModuleState::handle_loops(SigMap &assign_map, RTLIL::Module *module) { // http://en.wikipedia.org/wiki/Topological_sorting // (Kahn, Arthur B. (1962), "Topological sorting of large networks") @@ -596,7 +603,7 @@ void AbcModuleState::handle_loops(RTLIL::Module *module) first_line = false; } - int id3 = map_signal(RTLIL::SigSpec(wire)); + int id3 = map_signal(assign_map, RTLIL::SigSpec(wire)); signal_list[id1].is_port = true; signal_list[id3].is_port = true; log_assert(id3 == int(in_edges_count.size())); @@ -615,7 +622,7 @@ void AbcModuleState::handle_loops(RTLIL::Module *module) } edges[id1].swap(edges[id3]); - module->connect(RTLIL::SigSig(signal_list[id3].bit, signal_list[id1].bit)); + connect(assign_map, module, RTLIL::SigSig(signal_list[id3].bit, signal_list[id1].bit)); dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); } } @@ -751,7 +758,7 @@ struct abc_output_filter } }; -void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, const std::vector &cells, +void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, SigMap &assign_map, const std::vector &cells, bool dff_mode, std::string clk_str) { initvals.set(&assign_map, module); @@ -937,33 +944,33 @@ void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, co had_init = false; for (auto c : cells) - extract_cell(module, c, config.keepff); + extract_cell(assign_map, module, c, config.keepff); if (undef_bits_lost) log("Replacing %d occurrences of constant undef bits with constant zero bits\n", undef_bits_lost); for (auto wire : module->wires()) { if (wire->port_id > 0) - mark_port(wire); + mark_port(assign_map, wire); } for (auto cell : module->cells()) for (auto &port_it : cell->connections()) - mark_port(port_it.second); + mark_port(assign_map, port_it.second); if (clk_sig.size() != 0) - mark_port(clk_sig); + mark_port(assign_map, clk_sig); if (en_sig.size() != 0) - mark_port(en_sig); + mark_port(assign_map, en_sig); if (arst_sig.size() != 0) - mark_port(arst_sig); + mark_port(assign_map, arst_sig); if (srst_sig.size() != 0) - mark_port(srst_sig); + mark_port(assign_map, srst_sig); - handle_loops(module); + handle_loops(assign_map, module); buffer = stringf("%s/input.blif", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); @@ -1206,7 +1213,7 @@ void AbcModuleState::abc_module(RTLIL::Design *design, RTLIL::Module *module, co log("Don't call ABC as there is nothing to map.\n"); } -void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) +void AbcModuleState::extract(SigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module) { if (!did_run_abc) { return; @@ -1251,7 +1258,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); conn.first = module->wire(name_y); conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1); - module->connect(conn); + connect(assign_map, module, conn); continue; } if (c->type == ID(BUF)) { @@ -1260,7 +1267,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) RTLIL::IdString name_a = remap_name(c->getPort(ID::A).as_wire()->name); conn.first = module->wire(name_y); conn.second = module->wire(name_a); - module->connect(conn); + connect(assign_map, module, conn); continue; } if (c->type == ID(NOT)) { @@ -1392,7 +1399,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) RTLIL::SigSig conn; conn.first = module->wire(remap_name(c->connections().begin()->second.as_wire()->name)); conn.second = RTLIL::SigSpec(c->type == ID(_const0_) ? 0 : 1, 1); - module->connect(conn); + connect(assign_map, module, conn); continue; } @@ -1437,7 +1444,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID::LUT).as_int() == 2) { SigSpec my_a = module->wire(remap_name(c->getPort(ID::A).as_wire()->name)); SigSpec my_y = module->wire(remap_name(c->getPort(ID::Y).as_wire()->name)); - module->connect(my_y, my_a); + connect(assign_map, module, RTLIL::SigSig(my_a, my_y)); continue; } @@ -1462,7 +1469,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) conn.first = module->wire(remap_name(conn.first.as_wire()->name)); if (!conn.second.is_fully_const()) conn.second = module->wire(remap_name(conn.second.as_wire()->name)); - module->connect(conn); + connect(assign_map, module, conn); } cell_stats.sort(); @@ -1483,7 +1490,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) conn.second = si.bit; in_wires++; } - module->connect(conn); + connect(assign_map, module, conn); } log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); @@ -2077,6 +2084,9 @@ struct AbcPass : public Pass { for (auto mod : design->selected_modules()) { + SigMap assign_map; + assign_map.set(mod); + if (mod->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(mod)); continue; @@ -2084,9 +2094,8 @@ struct AbcPass : public Pass { if (!dff_mode || !clk_str.empty()) { AbcModuleState state(config); - state.assign_map.set(mod); - state.abc_module(design, mod, mod->selected_cells(), dff_mode, clk_str); - state.extract(design, mod); + state.abc_module(design, mod, assign_map, mod->selected_cells(), dff_mode, clk_str); + state.extract(assign_map, design, mod); state.finish(); continue; } @@ -2107,8 +2116,6 @@ struct AbcPass : public Pass { dict> cell_to_bit, cell_to_bit_up, cell_to_bit_down; dict> bit_to_cell, bit_to_cell_up, bit_to_cell_down; - SigMap assign_map; - assign_map.set(mod); FfInitVals initvals; initvals.set(&assign_map, mod); for (auto cell : all_cells) @@ -2245,7 +2252,6 @@ struct AbcPass : public Pass { for (auto &it : assigned_cells) { AbcModuleState state(config); - state.assign_map.set(mod); state.clk_polarity = std::get<0>(it.first); state.clk_sig = assign_map(std::get<1>(it.first)); state.en_polarity = std::get<2>(it.first); @@ -2254,8 +2260,8 @@ struct AbcPass : public Pass { state.arst_sig = assign_map(std::get<5>(it.first)); state.srst_polarity = std::get<6>(it.first); state.srst_sig = assign_map(std::get<7>(it.first)); - state.abc_module(design, mod, it.second, !state.clk_sig.empty(), "$"); - state.extract(design, mod); + state.abc_module(design, mod, assign_map, it.second, !state.clk_sig.empty(), "$"); + state.extract(assign_map, design, mod); state.finish(); } }