diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index a91a17dc1..915899b7d 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -136,7 +136,6 @@ struct AbcConfig bool fast_mode = false; bool show_tempdir = false; bool sop_mode = false; - bool word_mode = false; bool abc_dress = false; bool map_mux4 = false; bool map_mux8 = false; @@ -144,16 +143,6 @@ struct AbcConfig bool markgroups = false; pool enabled_gates; bool cmos_cost = false; - int max_threads = -1; // -1 means auto (use number of modules) - int reserved_cores = 4; // cores reserved for main thread and other work - - bool is_yosys_abc() const { -#ifdef ABCEXTERNAL - return false; -#else - return exe_file == yosys_abc_executable; -#endif - } }; struct AbcSigVal { @@ -166,12 +155,7 @@ struct AbcSigVal { } }; -// REUSE_YOSYS_ABC_PROCESSES only works when ABC is built with ENABLE_READLINE. -#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN) && defined(YOSYS_ENABLE_READLINE) -#define REUSE_YOSYS_ABC_PROCESSES -#endif - -#ifdef REUSE_YOSYS_ABC_PROCESSES +#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN) struct AbcProcess { pid_t pid; @@ -204,10 +188,10 @@ struct AbcProcess int status; int ret = waitpid(pid, &status, 0); if (ret != pid) { - log_error("waitpid(%d) failed\n", pid); + log_error("waitpid(%d) failed", pid); } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - log_error("ABC failed with status %X\n", status); + log_error("ABC failed with status %X", status); } if (from_child_pipe >= 0) close(from_child_pipe); @@ -219,12 +203,12 @@ std::optional spawn_abc(const char* abc_exe, DeferredLogs &logs) { // fork()s. int to_child_pipe[2]; if (pipe2(to_child_pipe, O_CLOEXEC) != 0) { - logs.log_error("pipe failed\n"); + logs.log_error("pipe failed"); return std::nullopt; } int from_child_pipe[2]; if (pipe2(from_child_pipe, O_CLOEXEC) != 0) { - logs.log_error("pipe failed\n"); + logs.log_error("pipe failed"); return std::nullopt; } @@ -237,39 +221,39 @@ std::optional spawn_abc(const char* abc_exe, DeferredLogs &logs) { posix_spawn_file_actions_t file_actions; if (posix_spawn_file_actions_init(&file_actions) != 0) { - logs.log_error("posix_spawn_file_actions_init failed\n"); + logs.log_error("posix_spawn_file_actions_init failed"); return std::nullopt; } if (posix_spawn_file_actions_addclose(&file_actions, to_child_pipe[1]) != 0) { - logs.log_error("posix_spawn_file_actions_addclose failed\n"); + logs.log_error("posix_spawn_file_actions_addclose failed"); return std::nullopt; } if (posix_spawn_file_actions_addclose(&file_actions, from_child_pipe[0]) != 0) { - logs.log_error("posix_spawn_file_actions_addclose failed\n"); + logs.log_error("posix_spawn_file_actions_addclose failed"); return std::nullopt; } if (posix_spawn_file_actions_adddup2(&file_actions, to_child_pipe[0], STDIN_FILENO) != 0) { - logs.log_error("posix_spawn_file_actions_adddup2 failed\n"); + logs.log_error("posix_spawn_file_actions_adddup2 failed"); return std::nullopt; } if (posix_spawn_file_actions_adddup2(&file_actions, from_child_pipe[1], STDOUT_FILENO) != 0) { - logs.log_error("posix_spawn_file_actions_adddup2 failed\n"); + logs.log_error("posix_spawn_file_actions_adddup2 failed"); return std::nullopt; } if (posix_spawn_file_actions_addclose(&file_actions, to_child_pipe[0]) != 0) { - logs.log_error("posix_spawn_file_actions_addclose failed\n"); + logs.log_error("posix_spawn_file_actions_addclose failed"); return std::nullopt; } if (posix_spawn_file_actions_addclose(&file_actions, from_child_pipe[1]) != 0) { - logs.log_error("posix_spawn_file_actions_addclose failed\n"); + logs.log_error("posix_spawn_file_actions_addclose failed"); return std::nullopt; } char arg1[] = "-s"; char* argv[] = { strdup(abc_exe), arg1, nullptr }; if (0 != posix_spawnp(&result.pid, abc_exe, &file_actions, nullptr, argv, environ)) { - logs.log_error("posix_spawnp %s failed (errno=%s)\n", abc_exe, strerror(errno)); + logs.log_error("posix_spawnp %s failed (errno=%s)", abc_exe, strerror(errno)); return std::nullopt; } free(argv[0]); @@ -329,7 +313,7 @@ struct AbcModuleState { void handle_loops(AbcSigMap &assign_map, RTLIL::Module *module); void prepare_module(RTLIL::Design *design, RTLIL::Module *module, AbcSigMap &assign_map, const std::vector &cells, bool dff_mode, std::string clk_str); - void extract(AbcSigMap &assign_map, dict &sig2src, SigMap &orig_sigmap, RTLIL::Design *design, RTLIL::Module *module); + void extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module); void finish(); }; @@ -594,8 +578,12 @@ bool AbcModuleState::extract_cell(const AbcSigMap &assign_map, RTLIL::Module *mo std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire) { std::string abc_sname = abc_name.substr(1); - if (abc_sname.compare(0, 9, "new_ys__n") == 0) + bool isnew = false; + if (abc_sname.compare(0, 4, "new_") == 0) + { abc_sname.erase(0, 4); + isnew = true; + } if (abc_sname.compare(0, 5, "ys__n") == 0) { abc_sname.erase(0, 5); @@ -610,9 +598,11 @@ std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **o const auto &bit = signal_bits.at(sid); if (bit.wire != nullptr) { - std::string s = stringf("\\%s_ix%d", bit.wire->name.c_str()+1, map_autoidx); // SILIMATE: Improve the naming + std::string s = stringf("$abc$%d$%s", map_autoidx, bit.wire->name.c_str()+1); if (bit.wire->width != 1) s += stringf("[%d]", bit.offset); + if (isnew) + s += "_new"; s += postfix; if (orig_wire != nullptr) *orig_wire = bit.wire; @@ -621,7 +611,7 @@ std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **o } } } - return stringf("\\%s_ix%d", abc_sname.c_str(), map_autoidx); // SILIMATE: Improve the naming + return stringf("$abc$%d$%s", map_autoidx, abc_name.substr(1)); } void AbcModuleState::dump_loop_graph(FILE *f, int &nr, dict> &edges, pool &workpool, std::vector &in_counts) @@ -1073,9 +1063,8 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module abc_script += stringf("; dress \"%s/input.blif\"", run_abc.tempdir_name); abc_script += stringf("; write_blif %s/output.blif", run_abc.tempdir_name); abc_script = add_echos_to_abc_cmd(abc_script); -#if defined(REUSE_YOSYS_ABC_PROCESSES) - if (config.is_yosys_abc()) - abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; +#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN) + abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; #endif for (size_t i = 0; i+1 < abc_script.size(); i++) @@ -1138,43 +1127,17 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module handle_loops(assign_map, module); } -#if defined(REUSE_YOSYS_ABC_PROCESSES) -static bool is_abc_prompt(const std::string &line, std::string &rest) { - size_t pos = 0; - while (true) { - // The prompt may not start at the start of the line, because - // ABC can output progress and maybe other data that isn't - // newline-terminated. - size_t start = line.find("abc ", pos); - if (start == std::string::npos) - return false; - pos = start + 4; - - size_t digits = 0; - while (pos + digits < line.size() && line[pos + digits] >= '0' && line[pos + digits] <= '9') - ++digits; - if (digits < 2) - return false; - if (line.substr(pos + digits, 2) == "> ") { - rest = line.substr(pos + digits + 2); - return true; - } - } -} - bool read_until_abc_done(abc_output_filter &filt, int fd, DeferredLogs &logs) { std::string line; char buf[1024]; - bool seen_source_cmd = false; - bool seen_yosys_abc_done = false; while (true) { int ret = read(fd, buf, sizeof(buf) - 1); if (ret < 0) { - logs.log_error("Failed to read from ABC, errno=%d\n", errno); + logs.log_error("Failed to read from ABC, errno=%d", errno); return false; } if (ret == 0) { - logs.log_error("ABC exited prematurely\n"); + logs.log_error("ABC exited prematurely"); return false; } char *start = buf; @@ -1202,13 +1165,8 @@ bool read_until_abc_done(abc_output_filter &filt, int fd, DeferredLogs &logs) { line.append(start, end - start); } } -#endif -#if defined(REUSE_YOSYS_ABC_PROCESSES) void RunAbcState::run(ConcurrentStack &process_pool) -#else -void RunAbcState::run(ConcurrentStack &) -#endif { std::string buffer = stringf("%s/input.blif", tempdir_name); FILE *f = fopen(buffer.c_str(), "wt"); @@ -1333,13 +1291,9 @@ void RunAbcState::run(ConcurrentStack &) logs.log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", count_gates, GetSize(signal_list), count_input, count_output); - if (count_output == 0) { - log("Don't call ABC as there is nothing to map.\n"); - return; - } - int ret; - std::string tmp_script_name = stringf("%s/abc.script", tempdir_name); - do { + if (count_output > 0) + { + std::string tmp_script_name = stringf("%s/abc.script", tempdir_name); logs.log("Running ABC script: %s\n", replace_tempdir(tmp_script_name, tempdir_name, config.show_tempdir)); errno = 0; @@ -1370,7 +1324,7 @@ void RunAbcState::run(ConcurrentStack &) abc_argv[2] = strdup("-f"); abc_argv[3] = strdup(tmp_script_name.c_str()); abc_argv[4] = 0; - ret = abc::Abc_RealMain(4, abc_argv); + int ret = abc::Abc_RealMain(4, abc_argv); free(abc_argv[0]); free(abc_argv[1]); free(abc_argv[2]); @@ -1385,43 +1339,39 @@ void RunAbcState::run(ConcurrentStack &) for (std::string line; std::getline(temp_stdouterr_r, line); ) filt.next_line(line + "\n"); temp_stdouterr_r.close(); - break; -#else -#if defined(REUSE_YOSYS_ABC_PROCESSES) - if (config.is_yosys_abc()) { - AbcProcess process; - if (std::optional process_opt = process_pool.try_pop_back()) { - process = std::move(process_opt.value()); - } else if (std::optional process_opt = spawn_abc(config.exe_file.c_str(), logs)) { - process = std::move(process_opt.value()); - } else { - return; - } - std::string cmd = stringf( - "empty\n" - "source %s\n", tmp_script_name); - ret = write(process.to_child_pipe, cmd.c_str(), cmd.size()); - if (ret != static_cast(cmd.size())) { - logs.log_error("write failed"); - return; - } - ret = read_until_abc_done(filt, process.from_child_pipe, logs) ? 0 : 1; - if (ret == 0) { - process_pool.push_back(std::move(process)); - } - break; +#elif defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN) + AbcProcess process; + if (std::optional process_opt = process_pool.try_pop_back()) { + process = std::move(process_opt.value()); + } else if (std::optional process_opt = spawn_abc(config.exe_file.c_str(), logs)) { + process = std::move(process_opt.value()); + } else { + return; } + std::string cmd = stringf( + "empty\n" + "source %s\n", tmp_script_name); + int ret = write(process.to_child_pipe, cmd.c_str(), cmd.size()); + if (ret != static_cast(cmd.size())) { + logs.log_error("write failed"); + return; + } + ret = read_until_abc_done(filt, process.from_child_pipe, logs) ? 0 : 1; + if (ret == 0) { + process_pool.push_back(std::move(process)); + } +#else + std::string cmd = stringf("\"%s\" -s -f %s/abc.script 2>&1", config.exe_file.c_str(), tempdir_name.c_str()); + int ret = run_command(cmd, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); #endif - std::string cmd = stringf("\"%s\" -s -f %s 2>&1", config.exe_file, tmp_script_name); - ret = run_command(cmd, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); -#endif - } while (false); - if (ret != 0) { - logs.log_error("ABC: execution of script \"%s\" failed: return code %d (errno=%d).\n", tmp_script_name, ret, errno); + if (ret != 0) { + logs.log_error("ABC: execution of script \"%s\" failed: return code %d (errno=%d).\n", tmp_script_name, ret, errno); + return; + } + did_run = true; return; } - logs.log("Don't call ABC as there is nothing to map.\n"); - did_run = true; + log("Don't call ABC as there is nothing to map.\n"); } void emit_global_input_files(const AbcConfig &config) @@ -1483,7 +1433,7 @@ void emit_global_input_files(const AbcConfig &config) } } -void AbcModuleState::extract(AbcSigMap &assign_map, dict &sig2src, SigMap &orig_sigmap, RTLIL::Design *design, RTLIL::Module *module) +void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL::Module *module) { log_push(); log_header(design, "Executed ABC.\n"); @@ -1509,39 +1459,22 @@ void AbcModuleState::extract(AbcSigMap &assign_map, dict & RTLIL::Module *mapped_mod = mapped_design->module(ID(netlist)); if (mapped_mod == nullptr) log_error("ABC output file does not contain a module `netlist'.\n"); - SigMap mapped_sigmap(mapped_mod); // SILIMATE: Move mapped sigmap definition here bool markgroups = run_abc.config.markgroups; for (auto w : mapped_mod->wires()) { RTLIL::Wire *orig_wire = nullptr; RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire)); if (orig_wire != nullptr && orig_wire->attributes.count(ID::src)) wire->attributes[ID::src] = orig_wire->attributes[ID::src]; - - // SILIMATE: Apply src attribute to the wire from the original wire - if (orig_wire != nullptr) { - if (sig2src.count(orig_sigmap(orig_wire))) { - wire->set_src_attribute(sig2src[orig_sigmap(orig_wire)]); - sig2src[mapped_sigmap(wire)] = wire->get_src_attribute(); - log_debug("Matched wire %s to driver attributes:\n", orig_wire->name.c_str()); - } else { - log_debug("No driver attributes found for wire %s\n", orig_wire->name.c_str()); - } - } - if (markgroups) wire->attributes[ID::abcgroup] = map_autoidx; design->select(module, wire); } + SigMap mapped_sigmap(mapped_mod); FfInitVals mapped_initvals(&mapped_sigmap, mapped_mod); dict cell_stats; for (auto c : mapped_mod->cells()) { - // SILIMATE: set output port to either Y or Q depending on the cell's ports and apply src attribute to the driver cell - Wire *out_wire = c->getPort((c->hasPort(ID::Y)) ? ID::Y : ID::Q).as_wire(); - Wire *remapped_out_wire = module->wire(remap_name(out_wire->name)); - std::string src_attribute = sig2src[remapped_out_wire]; - if (builtin_lib) { cell_stats[RTLIL::unescape_id(c->type)]++; @@ -1563,57 +1496,32 @@ void AbcModuleState::extract(AbcSigMap &assign_map, dict & continue; } if (c->type == ID(NOT)) { - // SILIMATE: use word-level primitives - RTLIL::Cell *cell = module->addCell(remap_name(c->name), run_abc.config.word_mode ? ID($not) : ID($_NOT_)); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::Y}) { RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } - cell->set_src_attribute(src_attribute); // SILIMATE: set src attribute from wire - cell->fixup_parameters(); // SILIMATE: fix up parameters design->select(module, cell); continue; } if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) { - // SILIMATE: use word-level primitives - std::string cell_type; - if (c->type == ID(AND) && run_abc.config.word_mode) - cell_type = "$and"; - else if (c->type == ID(OR) && run_abc.config.word_mode) - cell_type = "$or"; - else if (c->type == ID(XOR) && run_abc.config.word_mode) - cell_type = "$xor"; - else - cell_type = stringf("$_%s_", c->type.c_str()+1); - - RTLIL::Cell *cell = module->addCell(remap_name(c->name), cell_type); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::Y}) { RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } - cell->set_src_attribute(src_attribute); // SILIMATE: set src attribute from wire - cell->fixup_parameters(); // SILIMATE: fix up parameters design->select(module, cell); continue; } if (c->type.in(ID(MUX), ID(NMUX))) { - // SILIMATE: use word-level primitives - std::string cell_type; - if (c->type == ID(MUX) && run_abc.config.word_mode) - cell_type = "$mux"; - else - cell_type = stringf("$_%s_", c->type.c_str()+1); - - RTLIL::Cell *cell = module->addCell(remap_name(c->name), cell_type); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::S, ID::Y}) { RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } - cell->set_src_attribute(src_attribute); // SILIMATE: set src attribute from wire - cell->fixup_parameters(); // SILIMATE: fix up parameters design->select(module, cell); continue; } @@ -2051,16 +1959,6 @@ struct AbcPass : public Pass { log(" preserve naming by an equivalence check between the original and\n"); log(" post-ABC netlists (experimental).\n"); log("\n"); - log(" -max_threads \n"); - log(" maximum number of worker threads for parallel ABC runs. Default is -1,\n"); - log(" which means auto (use number of modules). Set to 0 to disable parallel\n"); - log(" execution and run everything on the main thread.\n"); - log("\n"); - log(" -reserved_cores \n"); - log(" number of CPU cores to reserve for the main thread and other work.\n"); - log(" Default is 4. The actual number of worker threads used is:\n"); - log(" min(hardware_threads - reserved_cores, max_threads)\n"); - log("\n"); log("When no target cell library is specified the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -2104,7 +2002,6 @@ struct AbcPass : public Pass { lut_arg = design->scratchpad_get_string("abc.lut", lut_arg); luts_arg = design->scratchpad_get_string("abc.luts", luts_arg); config.sop_mode = design->scratchpad_get_bool("abc.sop", false); - config.word_mode = design->scratchpad_get_bool("abc.word", false); config.map_mux4 = design->scratchpad_get_bool("abc.mux4", false); config.map_mux8 = design->scratchpad_get_bool("abc.mux8", false); config.map_mux16 = design->scratchpad_get_bool("abc.mux16", false); @@ -2122,8 +2019,6 @@ struct AbcPass : public Pass { config.cleanup = !design->scratchpad_get_bool("abc.nocleanup", false); config.show_tempdir = design->scratchpad_get_bool("abc.showtmp", false); config.markgroups = design->scratchpad_get_bool("abc.markgroups", false); - config.max_threads = design->scratchpad_get_int("abc.max_threads", -1); - config.reserved_cores = design->scratchpad_get_int("abc.reserved_cores", 4); if (config.cleanup) config.global_tempdir_name = get_base_tmpdir() + "/"; @@ -2202,10 +2097,6 @@ struct AbcPass : public Pass { config.sop_mode = true; continue; } - if (arg == "-word") { - config.word_mode = true; - continue; - } if (arg == "-mux4") { config.map_mux4 = true; continue; @@ -2259,14 +2150,6 @@ struct AbcPass : public Pass { config.markgroups = true; continue; } - if (arg == "-max_threads" && argidx+1 < args.size()) { - config.max_threads = atoi(args[++argidx].c_str()); - continue; - } - if (arg == "-reserved_cores" && argidx+1 < args.size()) { - config.reserved_cores = atoi(args[++argidx].c_str()); - continue; - } break; } extra_args(args, argidx, design); @@ -2474,156 +2357,6 @@ struct AbcPass : public Pass { emit_global_input_files(config); - // Process non-DFF/non-clock-domain mode in stages - if (!dff_mode || !clk_str.empty()) { - // Maps for collateral storage across stages - dict module_assign_maps; - dict module_sigmaps; - dict> module_sig2srcs; - dict module_initvals; - dict module_states; - - // STAGE 1: Compute assign_maps, sig2src maps, and initvals for all modules - // Then prepare for ABC runs (sequential) - for (auto mod : design->selected_modules()) - { - // Do not allow modules with processes - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - continue; - } - - // Create an assign_map for the module - AbcSigMap assign_map; - assign_map.set(mod); - - // Create an FfInitVals and use it for all ABC runs. FfInitVals only cares about - // wires with the ID::init attribute and we don't add or remove any such wires - // in this pass. - FfInitVals initvals; - initvals.set(&assign_map, mod); - - // Populate assign_map - for (auto wire : mod->wires()) - if (wire->port_id > 0 || wire->get_bool_attribute(ID::keep)) - assign_map.addVal(SigSpec(wire), AbcSigVal(true)); - - // Populate assign_map with cell connections - std::vector cells = mod->selected_cells(); - assign_cell_connection_ports(mod, {&cells}, assign_map); - - // Create a map of all signals and their corresponding src attrs - SigMap sigmap(mod); - dict sig2src; - for (auto wire : mod->wires()) - if (wire->port_input) - for (auto bit : sigmap(wire)) - sig2src[bit] = wire->get_src_attribute(); - for (auto cell : mod->cells()) - for (auto &conn : cell->connections()) - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) { - if (GetSize(cell->attributes) > 0) - sig2src[bit] = cell->get_src_attribute(); - else - sig2src[bit] = bit.wire->get_src_attribute(); - } - - // Prepare modules for ABC runs and set up process pool - AbcModuleState *state = new AbcModuleState(config, initvals, 0); - state->prepare_module(design, mod, assign_map, cells, dff_mode, clk_str); - - // Store collateral for use in later stages - module_assign_maps[mod] = assign_map; - module_sigmaps[mod] = sigmap; - module_sig2srcs[mod] = sig2src; - module_initvals[mod] = initvals; - module_states[mod] = state; - } - - // STAGE 2: Run ABC in parallel - // Reserve cores for main thread and other work, and don't create more worker - // threads than ABC runs (unless explicitly configured). - int num_modules = GetSize(design->selected_modules()); - int max_threads = config.max_threads; - if (max_threads < 0) { - // Auto mode: use number of modules as max threads - max_threads = num_modules; - } - if (max_threads <= 1) { - // Just do everything on the main thread. - max_threads = 0; - } -#ifdef YOSYS_LINK_ABC - // ABC doesn't support multithreaded calls so don't call it off the main thread. - max_threads = 0; -#endif - int num_worker_threads = ThreadPool::pool_size(config.reserved_cores, max_threads); - ConcurrentQueue work_queue(num_worker_threads); - ConcurrentQueue work_finished_queue; - ConcurrentStack process_pool; - ThreadPool worker_threads(num_worker_threads, [&](int){ - while (std::optional work = work_queue.pop_front()) { - // Only the `run_abc` component is safe to touch here! - (*work)->run_abc.run(process_pool); - work_finished_queue.push_back(*work); - } - }); - int work_finished_count = 0; - for (auto mod : design->selected_modules()) { - // Do not allow modules with processes - if (mod->processes.size() > 0) continue; - - // Log - log("Sending module %s to abc...\n", log_id(mod)); - log_flush(); - - // Get the state for the module - AbcModuleState *state = module_states.at(mod); - - // Make sure we process the results in the order we expect. When we can - // process results before the next ABC run, do so, to keep memory usage low(er). - while (std::optional work = work_finished_queue.try_pop_front()) { - ++work_finished_count; - } - if (num_worker_threads > 0) { - work_queue.push_back(state); - } else { - // Just run everything on the main thread. - state->run_abc.run(process_pool); - work_finished_queue.push_back(state); - } - } - work_queue.close(); - while (work_finished_count < num_modules) { - std::optional work = work_finished_queue.pop_front(); - (*work)->run_abc.logs.flush(); - log_flush(); - ++work_finished_count; - log("Completed abc on module %d/%d\n", work_finished_count, num_modules); - log_flush(); - } - - // STAGE 3: Extract results and replace original netlist (sequential) - for (auto mod : design->selected_modules()) - { - // Do not allow modules with processes - if (mod->processes.size() > 0) continue; - - // Extraction - AbcModuleState *state = module_states.at(mod); - SigMap sigmap = module_sigmaps.at(mod); - dict sig2src = module_sig2srcs.at(mod); - AbcSigMap assign_map = module_assign_maps.at(mod); - state->extract(assign_map, sig2src, sigmap, design, mod); - delete state; - } - - // STAGE 4: Cleanup - goto cleanup; - } - - // DFF/clock-domain mode for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { @@ -2643,22 +2376,17 @@ struct AbcPass : public Pass { if (wire->port_id > 0 || wire->get_bool_attribute(ID::keep)) assign_map.addVal(SigSpec(wire), AbcSigVal(true)); - // SILIMATE: Create a map of all signals and their corresponding src attr - SigMap sigmap(mod); - dict sig2src; - for (auto wire : mod->wires()) - if (wire->port_input) - for (auto bit : sigmap(wire)) - sig2src[bit] = wire->get_src_attribute(); - for (auto cell : mod->cells()) - for (auto &conn : cell->connections()) - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) { - if (GetSize(cell->attributes) > 0) - sig2src[bit] = cell->get_src_attribute(); - else - sig2src[bit] = bit.wire->get_src_attribute(); - } + if (!dff_mode || !clk_str.empty()) { + std::vector cells = mod->selected_cells(); + assign_cell_connection_ports(mod, {&cells}, assign_map); + + AbcModuleState state(config, initvals, 0); + state.prepare_module(design, mod, assign_map, cells, dff_mode, clk_str); + ConcurrentStack process_pool; + state.run_abc.run(process_pool); + state.extract(assign_map, design, mod); + continue; + } CellTypes ct(design); @@ -2851,7 +2579,7 @@ struct AbcPass : public Pass { ++work_finished_count; } while (work_finished_by_index[next_state_index_to_process] != nullptr) { - work_finished_by_index[next_state_index_to_process]->extract(assign_map, sig2src, sigmap, design, mod); + work_finished_by_index[next_state_index_to_process]->extract(assign_map, design, mod); work_finished_by_index[next_state_index_to_process] = nullptr; ++next_state_index_to_process; } @@ -2881,13 +2609,12 @@ struct AbcPass : public Pass { ++work_finished_count; } while (next_state_index_to_process < GetSize(work_finished_by_index)) { - work_finished_by_index[next_state_index_to_process]->extract(assign_map, sig2src, sigmap, design, mod); + work_finished_by_index[next_state_index_to_process]->extract(assign_map, design, mod); work_finished_by_index[next_state_index_to_process] = nullptr; ++next_state_index_to_process; } } - cleanup: if (config.cleanup) { log("Removing global temp directory.\n"); remove_directory(config.global_tempdir_name); @@ -2897,4 +2624,4 @@ struct AbcPass : public Pass { } } AbcPass; -PRIVATE_NAMESPACE_END +PRIVATE_NAMESPACE_END \ No newline at end of file