mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-19 13:45:48 +00:00
Please just stop modifying yosys...
This commit is contained in:
parent
ea6b968618
commit
c57c49873e
1 changed files with 79 additions and 352 deletions
|
|
@ -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<std::string> 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<AbcProcess> 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<AbcProcess> 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<RTLIL::Cell*> &cells,
|
||||
bool dff_mode, std::string clk_str);
|
||||
void extract(AbcSigMap &assign_map, dict<SigSpec, std::string> &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<int, pool<int>> &edges, pool<int> &workpool, std::vector<int> &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<AbcProcess> &process_pool)
|
||||
#else
|
||||
void RunAbcState::run(ConcurrentStack<AbcProcess> &)
|
||||
#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<AbcProcess> &)
|
|||
|
||||
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<AbcProcess> &)
|
|||
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<AbcProcess> &)
|
|||
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<AbcProcess> process_opt = process_pool.try_pop_back()) {
|
||||
process = std::move(process_opt.value());
|
||||
} else if (std::optional<AbcProcess> 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<int>(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<AbcProcess> process_opt = process_pool.try_pop_back()) {
|
||||
process = std::move(process_opt.value());
|
||||
} else if (std::optional<AbcProcess> 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<int>(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<SigSpec, std::string> &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<SigSpec, std::string> &
|
|||
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<std::string, int> 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<SigSpec, std::string> &
|
|||
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 <num>\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 <num>\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<RTLIL::Module*, AbcSigMap> module_assign_maps;
|
||||
dict<RTLIL::Module*, SigMap> module_sigmaps;
|
||||
dict<RTLIL::Module*, dict<SigSpec, std::string>> module_sig2srcs;
|
||||
dict<RTLIL::Module*, FfInitVals> module_initvals;
|
||||
dict<RTLIL::Module*, AbcModuleState*> 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<RTLIL::Cell*> 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<SigSpec, std::string> 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<AbcModuleState*> work_queue(num_worker_threads);
|
||||
ConcurrentQueue<AbcModuleState*> work_finished_queue;
|
||||
ConcurrentStack<AbcProcess> process_pool;
|
||||
ThreadPool worker_threads(num_worker_threads, [&](int){
|
||||
while (std::optional<AbcModuleState*> 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<AbcModuleState*> 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<AbcModuleState*> 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<SigSpec, std::string> 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<SigSpec, std::string> 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<RTLIL::Cell*> 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<AbcProcess> 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue