USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool markgroups;
int map_autoidx;
inline std::string remap_name(RTLIL::IdString abc9_name)
void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
vector<int> lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
- const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, std::string box_file, std::string lut_file,
+ bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay, bool nomfs, std::string tempdir_name
)
{
fprintf(f, "%s\n", abc9_script.c_str());
fclose(f);
- log_push();
-
int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs");
log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
design->scratchpad_get_int("write_xaiger.num_ands"),
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n");
- for (auto &it : mapped_mod->wires_) {
- RTLIL::Wire *w = it.second;
- RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
- if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
- }
+ for (auto w : mapped_mod->wires())
+ module->addWire(remap_name(w->name), GetSize(w));
- dict<IdString, bool> abc9_box;
- vector<RTLIL::Cell*> boxes;
- for (auto cell : cells) {
- if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) {
- module->remove(cell);
- continue;
- }
- auto jt = abc9_box.find(cell->type);
- if (jt == abc9_box.end()) {
- RTLIL::Module* box_module = design->module(cell->type);
- jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
- }
- if (jt->second) {
- auto kt = cell->attributes.find("\\abc9_keep");
- bool abc9_keep = false;
- if (kt != cell->attributes.end()) {
- abc9_keep = kt->second.as_bool();
- cell->attributes.erase(kt);
- }
- if (!abc9_keep)
- boxes.emplace_back(cell);
- }
- }
+ for (auto it = module->cells_.begin(); it != module->cells_.end(); )
+ if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
+ it = module->cells_.erase(it);
+ else
+ ++it;
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
}
else
log_abort();
- if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue;
}
cell_stats[mapped_cell->type]++;
SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name));
SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name));
module->connect(my_y, my_a);
- if (markgroups) mapped_cell->attributes[ID(abcgroup)] = map_autoidx;
log_abort();
continue;
}
cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
}
- if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
- if (existing_cell) {
- cell->parameters = existing_cell->parameters;
- cell->attributes = existing_cell->attributes;
- }
- else {
- cell->parameters = mapped_cell->parameters;
- cell->attributes = mapped_cell->attributes;
- }
-
RTLIL::Module* box_module = design->module(mapped_cell->type);
auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop");
- for (auto &conn : mapped_cell->connections()) {
+ for (auto &mapped_conn : mapped_cell->connections()) {
RTLIL::SigSpec newsig;
- for (auto c : conn.second.chunks()) {
+ for (auto c : mapped_conn.second.chunks()) {
if (c.width == 0)
continue;
//log_assert(c.width == 1);
c.wire = module->wires_.at(remap_name(c.wire->name));
newsig.append(c);
}
- cell->setPort(conn.first, newsig);
-
- if (!abc9_flop) {
- if (cell->input(conn.first)) {
- for (auto i : newsig)
- bit2sinks[i].push_back(cell);
- for (auto i : conn.second)
- bit_users[i].insert(mapped_cell->name);
- }
- if (cell->output(conn.first))
- for (auto i : conn.second)
- bit_drivers[i].insert(mapped_cell->name);
+ if (existing_cell) {
+ auto it = existing_cell->connections_.find(mapped_conn.first);
+ if (it == existing_cell->connections_.end())
+ continue;
+ log_assert(GetSize(newsig) >= GetSize(it->second));
+ newsig = newsig.extract(0, GetSize(it->second));
+ }
+ cell->setPort(mapped_conn.first, newsig);
+
+ if (abc9_flop)
+ continue;
+
+ if (cell->input(mapped_conn.first)) {
+ for (auto i : newsig)
+ bit2sinks[i].push_back(cell);
+ for (auto i : mapped_conn.second)
+ bit_users[i].insert(mapped_cell->name);
}
+ if (cell->output(mapped_conn.first))
+ for (auto i : mapped_conn.second)
+ bit_drivers[i].insert(mapped_cell->name);
}
- }
- for (auto existing_cell : boxes) {
- Cell *cell = module->cell(remap_name(existing_cell->name));
- if (cell) {
- for (auto &conn : existing_cell->connections()) {
- if (!conn.second.is_wire())
- continue;
- Wire *wire = conn.second.as_wire();
- if (!wire->get_bool_attribute(ID(abc9_padding)))
- continue;
- cell->unsetPort(conn.first);
- log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second));
+ if (existing_cell) {
+ cell->parameters = existing_cell->parameters;
+ cell->attributes = existing_cell->attributes;
+ if (cell->attributes.erase("\\abc9_box_seq")) {
+ module->swap_names(cell, existing_cell);
+ module->remove(existing_cell);
}
- module->swap_names(cell, existing_cell);
}
- module->remove(existing_cell);
+ else {
+ cell->parameters = mapped_cell->parameters;
+ cell->attributes = mapped_cell->attributes;
+ }
}
// Copy connections (and rename) from mapped_mod to module
//{
// log("Don't call ABC as there is nothing to map.\n");
//}
-
- log_pop();
}
struct Abc9MapPass : public Pass {
log(" set delay target. the string {D} in the default scripts above is\n");
log(" replaced by this option when used, and an empty string otherwise\n");
log(" (indicating best possible delay).\n");
-// log(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n");
-// log(" default scripts above.\n");
log("\n");
// log(" -S <num>\n");
// log(" maximum number of LUT inputs shared.\n");
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n");
log("\n");
-// log(" -dff\n");
-// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
-// log(" clock domains are automatically partitioned in clock domains and each\n");
-// log(" domain is passed through ABC independently.\n");
-// log("\n");
-// log(" -clk [!]<clock-signal-name>[,[!]<enable-signal-name>]\n");
-// log(" use only the specified clock domain. this is like -dff, but only FF\n");
-// log(" cells that belong to the specified clock domain are used.\n");
-// log("\n");
-// log(" -keepff\n");
-// log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
-// log(" them, for example for equivalence checking.)\n");
-// log("\n");
+ log(" -dff\n");
+ log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
+ log(" domains are marked as such and automatically partitioned by ABC.\n");
+ log("\n");
log(" -showtmp\n");
log(" print the temp dir name in log. usually this is suppressed so that the\n");
log(" command output is identical across runs.\n");
log("\n");
- log(" -markgroups\n");
- log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
- log(" this attribute is a unique integer for each ABC process started. This\n");
- log(" is useful for debugging the partitioning of clock domains.\n");
- log("\n");
log(" -box <file>\n");
log(" pass this file with box library to ABC. Use with -lut.\n");
log("\n");
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n");
- log_push();
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
bool show_tempdir = false;
bool nomfs = false;
vector<int> lut_costs;
- markgroups = false;
#if 0
cleanup = false;
#endif
#endif
+ std::string lut_arg, luts_arg;
+ exe_file = design->scratchpad_get_string("abc9.exe", exe_file /* inherit default value if not set */);
+ script_file = design->scratchpad_get_string("abc9.script", script_file);
+ if (design->scratchpad.count("abc9.D")) {
+ delay_target = "-D " + design->scratchpad_get_string("abc9.D");
+ }
+ lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg);
+ luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg);
+ fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode);
+ show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir);
+ box_file = design->scratchpad_get_string("abc9.box", box_file);
+ if (design->scratchpad.count("abc9.W")) {
+ wire_delay = "-W " + design->scratchpad_get_string("abc9.W");
+ }
+ nomfs = design->scratchpad_get_bool("abc9.nomfs", nomfs);
+
size_t argidx;
char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) {
}
if (arg == "-script" && argidx+1 < args.size()) {
script_file = args[++argidx];
- rewrite_filename(script_file);
- if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
- script_file = std::string(pwd) + "/" + script_file;
continue;
}
if (arg == "-D" && argidx+1 < args.size()) {
// continue;
//}
if (arg == "-lut" && argidx+1 < args.size()) {
- string arg = args[++argidx];
- if (arg.find_first_not_of("0123456789:") == std::string::npos) {
- size_t pos = arg.find_first_of(':');
- int lut_mode = 0, lut_mode2 = 0;
- if (pos != string::npos) {
- lut_mode = atoi(arg.substr(0, pos).c_str());
- lut_mode2 = atoi(arg.substr(pos+1).c_str());
- } else {
- lut_mode = atoi(arg.c_str());
- lut_mode2 = lut_mode;
- }
- lut_costs.clear();
- for (int i = 0; i < lut_mode; i++)
- lut_costs.push_back(1);
- for (int i = lut_mode; i < lut_mode2; i++)
- lut_costs.push_back(2 << (i - lut_mode));
- }
- else {
- lut_file = arg;
- rewrite_filename(lut_file);
- if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
- lut_file = std::string(pwd) + "/" + lut_file;
- }
+ lut_arg = args[++argidx];
continue;
}
if (arg == "-luts" && argidx+1 < args.size()) {
- lut_costs.clear();
- for (auto &tok : split_tokens(args[++argidx], ",")) {
- auto parts = split_tokens(tok, ":");
- if (GetSize(parts) == 0 && !lut_costs.empty())
- lut_costs.push_back(lut_costs.back());
- else if (GetSize(parts) == 1)
- lut_costs.push_back(atoi(parts.at(0).c_str()));
- else if (GetSize(parts) == 2)
- while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
- lut_costs.push_back(atoi(parts.at(1).c_str()));
- else
- log_cmd_error("Invalid -luts syntax.\n");
- }
+ lut_arg = args[++argidx];
continue;
}
if (arg == "-fast") {
show_tempdir = true;
continue;
}
- if (arg == "-markgroups") {
- markgroups = true;
- continue;
- }
if (arg == "-box" && argidx+1 < args.size()) {
box_file = args[++argidx];
continue;
}
extra_args(args, argidx, design);
+ rewrite_filename(script_file);
+ if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
+ script_file = std::string(pwd) + "/" + script_file;
+
+ // handle -lut / -luts args
+ if (!lut_arg.empty()) {
+ string arg = lut_arg;
+ if (arg.find_first_not_of("0123456789:") == std::string::npos) {
+ size_t pos = arg.find_first_of(':');
+ int lut_mode = 0, lut_mode2 = 0;
+ if (pos != string::npos) {
+ lut_mode = atoi(arg.substr(0, pos).c_str());
+ lut_mode2 = atoi(arg.substr(pos+1).c_str());
+ } else {
+ lut_mode = atoi(arg.c_str());
+ lut_mode2 = lut_mode;
+ }
+ lut_costs.clear();
+ for (int i = 0; i < lut_mode; i++)
+ lut_costs.push_back(1);
+ for (int i = lut_mode; i < lut_mode2; i++)
+ lut_costs.push_back(2 << (i - lut_mode));
+ }
+ else {
+ lut_file = arg;
+ rewrite_filename(lut_file);
+ if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
+ lut_file = std::string(pwd) + "/" + lut_file;
+ }
+ }
+ if (!luts_arg.empty()) {
+ lut_costs.clear();
+ for (auto &tok : split_tokens(luts_arg, ",")) {
+ auto parts = split_tokens(tok, ":");
+ if (GetSize(parts) == 0 && !lut_costs.empty())
+ lut_costs.push_back(lut_costs.back());
+ else if (GetSize(parts) == 1)
+ lut_costs.push_back(atoi(parts.at(0).c_str()));
+ else if (GetSize(parts) == 2)
+ while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
+ lut_costs.push_back(atoi(parts.at(1).c_str()));
+ else
+ log_cmd_error("Invalid -luts syntax.\n");
+ }
+ }
+
// ABC expects a box file for XAIG
if (box_file.empty())
box_file = "+/dummy.box";
continue;
}
- const std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
+ if (!design->selected_whole_module(mod))
+ log_error("Can't handle partially selected module %s!\n", log_id(mod));
abc9_module(design, mod, script_file, exe_file, lut_costs,
- delay_target, lutin_shared, fast_mode, all_cells, show_tempdir,
+ delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, nomfs, tempdir_name);
}
-
- log_pop();
}
} Abc9MapPass;