3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-13 04:28:18 +00:00

Merge remote-tracking branch 'origin/xaig_dff' into eddie/abc9_refactor

This commit is contained in:
Eddie Hung 2020-01-06 12:04:08 -08:00
commit 921ff0f5e3
8 changed files with 295 additions and 255 deletions

View file

@ -376,10 +376,11 @@ Verilog Attributes and non-standard features
- The port attribute ``abc9_arrival`` specifies an integer (for output ports - The port attribute ``abc9_arrival`` specifies an integer (for output ports
only) to be used as the arrival time of this sequential port. It can be used, only) to be used as the arrival time of this sequential port. It can be used,
for example, to specify the clk-to-Q delay of a flip-flop for consideration for example, to specify the clk-to-Q delay of a flip-flop for consideration
during techmapping. during `abc9` techmapping.
- The module attribute ``abc9_flop`` is a boolean marking the module as a - The module attribute ``abc9_flop`` is a boolean marking the module as a
whitebox that describes the synchronous behaviour of a flip-flop. flip-flop. This allows `abc9` to analyse its contents in order to perform
sequential synthesis.
- The frontend sets attributes ``always_comb``, ``always_latch`` and - The frontend sets attributes ``always_comb``, ``always_latch`` and
``always_ff`` on processes derived from SystemVerilog style always blocks ``always_ff`` on processes derived from SystemVerilog style always blocks

View file

@ -787,6 +787,14 @@ struct AigerBackend : public Backend {
if (top_module == nullptr) if (top_module == nullptr)
log_error("Can't find top module in current design!\n"); log_error("Can't find top module in current design!\n");
if (!design->selected_whole_module(top_module))
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
if (!top_module->processes.empty())
log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module));
if (!top_module->memories.empty())
log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module));
AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode); AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode);
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);

View file

@ -137,7 +137,7 @@ struct XAigerWriter
return a; return a;
} }
XAigerWriter(Module *module) : module(module), sigmap(module) XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module)
{ {
pool<SigBit> undriven_bits; pool<SigBit> undriven_bits;
pool<SigBit> unused_bits; pool<SigBit> unused_bits;
@ -157,12 +157,8 @@ struct XAigerWriter
if (wire->get_bool_attribute(ID::keep)) if (wire->get_bool_attribute(ID::keep))
sigmap.add(wire); sigmap.add(wire);
// First, collect all the ports in port_id order
// since module->wires() could be sorted for (auto wire : module->wires())
// alphabetically
for (auto port : module->ports) {
auto wire = module->wire(port);
log_assert(wire);
for (int i = 0; i < GetSize(wire); i++) for (int i = 0; i < GetSize(wire); i++)
{ {
SigBit wirebit(wire, i); SigBit wirebit(wire, i);
@ -176,6 +172,9 @@ struct XAigerWriter
continue; continue;
} }
undriven_bits.insert(bit);
unused_bits.insert(bit);
if (wire->port_input) if (wire->port_input)
input_bits.insert(bit); input_bits.insert(bit);
@ -185,19 +184,6 @@ struct XAigerWriter
output_bits.insert(wirebit); output_bits.insert(wirebit);
} }
} }
}
for (auto wire : module->wires())
for (int i = 0; i < GetSize(wire); i++)
{
SigBit wirebit(wire, i);
SigBit bit = sigmap(wirebit);
if (bit.wire) {
undriven_bits.insert(bit);
unused_bits.insert(bit);
}
}
for (auto cell : module->cells()) { for (auto cell : module->cells()) {
if (cell->type == "$_NOT_") if (cell->type == "$_NOT_")
@ -402,12 +388,20 @@ struct XAigerWriter
undriven_bits.erase(bit); undriven_bits.erase(bit);
} }
if (holes_mode) {
struct sort_by_port_id {
bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const {
return a.wire->port_id < b.wire->port_id;
}
};
input_bits.sort(sort_by_port_id());
output_bits.sort(sort_by_port_id());
}
aig_map[State::S0] = 0; aig_map[State::S0] = 0;
aig_map[State::S1] = 1; aig_map[State::S1] = 1;
// pool<> iterates in LIFO order... for (const auto &bit : input_bits) {
for (int i = input_bits.size()-1; i >= 0; i--) {
const auto &bit = *input_bits.element(i);
aig_m++, aig_i++; aig_m++, aig_i++;
log_assert(!aig_map.count(bit)); log_assert(!aig_map.count(bit));
aig_map[bit] = 2*aig_m; aig_map[bit] = 2*aig_m;
@ -435,9 +429,7 @@ struct XAigerWriter
aig_outputs.push_back(bit2aig(bit)); aig_outputs.push_back(bit2aig(bit));
} }
// pool<> iterates in LIFO order... for (const auto &bit : output_bits) {
for (int i = output_bits.size()-1; i >= 0; i--) {
const auto &bit = *output_bits.element(i);
ordered_outputs[bit] = aig_o++; ordered_outputs[bit] = aig_o++;
aig_outputs.push_back(bit2aig(bit)); aig_outputs.push_back(bit2aig(bit));
} }
@ -618,7 +610,7 @@ struct XAigerWriter
if (holes_module) { if (holes_module) {
std::stringstream a_buffer; std::stringstream a_buffer;
XAigerWriter writer(holes_module); XAigerWriter writer(holes_module, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/); writer.write_aiger(a_buffer, false /*ascii_mode*/);
f << "a"; f << "a";
@ -654,17 +646,13 @@ struct XAigerWriter
module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size());
} }
void write_map(std::ostream &f, bool verbose_map) void write_map(std::ostream &f)
{ {
dict<int, string> input_lines; dict<int, string> input_lines;
dict<int, string> output_lines; dict<int, string> output_lines;
dict<int, string> wire_lines;
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
//if (!verbose_map && wire->name[0] == '$')
// continue;
SigSpec sig = sigmap(wire); SigSpec sig = sigmap(wire);
for (int i = 0; i < GetSize(wire); i++) for (int i = 0; i < GetSize(wire); i++)
@ -682,14 +670,6 @@ struct XAigerWriter
output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init);
continue; continue;
} }
if (verbose_map) {
if (aig_map.count(sig[i]) == 0)
continue;
int a = aig_map.at(sig[i]);
wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire));
}
} }
} }
@ -706,10 +686,6 @@ struct XAigerWriter
for (auto &it : output_lines) for (auto &it : output_lines)
f << it.second; f << it.second;
log_assert(output_lines.size() == output_bits.size()); log_assert(output_lines.size() == output_bits.size());
wire_lines.sort();
for (auto &it : wire_lines)
f << it.second;
} }
}; };
@ -721,8 +697,10 @@ struct XAigerBackend : public Backend {
log("\n"); log("\n");
log(" write_xaiger [options] [filename]\n"); log(" write_xaiger [options] [filename]\n");
log("\n"); log("\n");
log("Write the current design to an XAIGER file. The design must be flattened and\n"); log("Write the top module (according to the (* top *) attribute or if only one module\n");
log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or");
log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n");
log("pseudo-outputs.\n");
log("\n"); log("\n");
log(" -ascii\n"); log(" -ascii\n");
log(" write ASCII version of AIGER format\n"); log(" write ASCII version of AIGER format\n");
@ -730,14 +708,10 @@ struct XAigerBackend : public Backend {
log(" -map <filename>\n"); log(" -map <filename>\n");
log(" write an extra file with port and box symbols\n"); log(" write an extra file with port and box symbols\n");
log("\n"); log("\n");
log(" -vmap <filename>\n");
log(" like -map, but more verbose\n");
log("\n");
} }
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{ {
bool ascii_mode = false; bool ascii_mode = false;
bool verbose_map = false;
std::string map_filename; std::string map_filename;
log_header(design, "Executing XAIGER backend.\n"); log_header(design, "Executing XAIGER backend.\n");
@ -753,11 +727,6 @@ struct XAigerBackend : public Backend {
map_filename = args[++argidx]; map_filename = args[++argidx];
continue; continue;
} }
if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) {
map_filename = args[++argidx];
verbose_map = true;
continue;
}
break; break;
} }
extra_args(f, filename, args, argidx, !ascii_mode); extra_args(f, filename, args, argidx, !ascii_mode);
@ -767,6 +736,14 @@ struct XAigerBackend : public Backend {
if (top_module == nullptr) if (top_module == nullptr)
log_error("Can't find top module in current design!\n"); log_error("Can't find top module in current design!\n");
if (!design->selected_whole_module(top_module))
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
if (!top_module->processes.empty())
log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module));
if (!top_module->memories.empty())
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module));
XAigerWriter writer(top_module); XAigerWriter writer(top_module);
writer.write_aiger(*f, ascii_mode); writer.write_aiger(*f, ascii_mode);
@ -775,7 +752,7 @@ struct XAigerBackend : public Backend {
mapf.open(map_filename.c_str(), std::ofstream::trunc); mapf.open(map_filename.c_str(), std::ofstream::trunc);
if (mapf.fail()) if (mapf.fail())
log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
writer.write_map(mapf, verbose_map); writer.write_map(mapf);
} }
} }
} XAigerBackend; } XAigerBackend;

View file

@ -1514,7 +1514,47 @@ struct AbcPass : public Pass {
#endif #endif
#endif #endif
size_t argidx; // get arguments from scratchpad first, then override by command arguments
std::string lut_arg, luts_arg, g_arg;
exe_file = design->scratchpad_get_string("abc.exe", exe_file /* inherit default value if not set */);
script_file = design->scratchpad_get_string("abc.script", script_file);
liberty_file = design->scratchpad_get_string("abc.liberty", liberty_file);
constr_file = design->scratchpad_get_string("abc.constr", constr_file);
if (design->scratchpad.count("abc.D")) {
delay_target = "-D " + design->scratchpad_get_string("abc.D");
}
if (design->scratchpad.count("abc.I")) {
sop_inputs = "-I " + design->scratchpad_get_string("abc.I");
}
if (design->scratchpad.count("abc.P")) {
sop_products = "-P " + design->scratchpad_get_string("abc.P");
}
if (design->scratchpad.count("abc.S")) {
lutin_shared = "-S " + design->scratchpad_get_string("abc.S");
}
lut_arg = design->scratchpad_get_string("abc.lut", lut_arg);
luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
sop_mode = design->scratchpad_get_bool("abc.sop", sop_mode);
map_mux4 = design->scratchpad_get_bool("abc.mux4", map_mux4);
map_mux8 = design->scratchpad_get_bool("abc.mux8", map_mux8);
map_mux16 = design->scratchpad_get_bool("abc.mux16", map_mux16);
abc_dress = design->scratchpad_get_bool("abc.dress", abc_dress);
g_arg = design->scratchpad_get_string("abc.g", g_arg);
fast_mode = design->scratchpad_get_bool("abc.fast", fast_mode);
dff_mode = design->scratchpad_get_bool("abc.dff", dff_mode);
if (design->scratchpad.count("abc.clk")) {
clk_str = design->scratchpad_get_string("abc.clk");
dff_mode = true;
}
keepff = design->scratchpad_get_bool("abc.keepff", keepff);
cleanup = !design->scratchpad_get_bool("abc.nocleanup", !cleanup);
keepff = design->scratchpad_get_bool("abc.keepff", keepff);
show_tempdir = design->scratchpad_get_bool("abc.showtmp", show_tempdir);
markgroups = design->scratchpad_get_bool("abc.markgroups", markgroups);
size_t argidx, g_argidx;
bool g_arg_from_cmd = false;
char pwd [PATH_MAX]; char pwd [PATH_MAX];
if (!getcwd(pwd, sizeof(pwd))) { if (!getcwd(pwd, sizeof(pwd))) {
log_cmd_error("getcwd failed: %s\n", strerror(errno)); log_cmd_error("getcwd failed: %s\n", strerror(errno));
@ -1528,23 +1568,14 @@ struct AbcPass : public Pass {
} }
if (arg == "-script" && argidx+1 < args.size()) { if (arg == "-script" && argidx+1 < args.size()) {
script_file = args[++argidx]; 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; continue;
} }
if (arg == "-liberty" && argidx+1 < args.size()) { if (arg == "-liberty" && argidx+1 < args.size()) {
liberty_file = args[++argidx]; liberty_file = args[++argidx];
rewrite_filename(liberty_file);
if (!liberty_file.empty() && !is_absolute_path(liberty_file))
liberty_file = std::string(pwd) + "/" + liberty_file;
continue; continue;
} }
if (arg == "-constr" && argidx+1 < args.size()) { if (arg == "-constr" && argidx+1 < args.size()) {
rewrite_filename(constr_file);
constr_file = args[++argidx]; constr_file = args[++argidx];
if (!constr_file.empty() && !is_absolute_path(constr_file))
constr_file = std::string(pwd) + "/" + constr_file;
continue; continue;
} }
if (arg == "-D" && argidx+1 < args.size()) { if (arg == "-D" && argidx+1 < args.size()) {
@ -1564,37 +1595,11 @@ struct AbcPass : public Pass {
continue; continue;
} }
if (arg == "-lut" && argidx+1 < args.size()) { if (arg == "-lut" && argidx+1 < args.size()) {
string arg = args[++argidx]; lut_arg = args[++argidx];
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));
continue; continue;
} }
if (arg == "-luts" && argidx+1 < args.size()) { if (arg == "-luts" && argidx+1 < args.size()) {
lut_costs.clear(); luts_arg = args[++argidx];
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) < std::atoi(parts.at(0).c_str()))
lut_costs.push_back(atoi(parts.at(1).c_str()));
else
log_cmd_error("Invalid -luts syntax.\n");
}
continue; continue;
} }
if (arg == "-sop") { if (arg == "-sop") {
@ -1618,123 +1623,9 @@ struct AbcPass : public Pass {
continue; continue;
} }
if (arg == "-g" && argidx+1 < args.size()) { if (arg == "-g" && argidx+1 < args.size()) {
for (auto g : split_tokens(args[++argidx], ",")) { g_arg = args[++argidx];
vector<string> gate_list; g_argidx = argidx;
bool remove_gates = false; g_arg_from_cmd = true;
if (GetSize(g) > 0 && g[0] == '-') {
remove_gates = true;
g = g.substr(1);
}
if (g == "AND") goto ok_gate;
if (g == "NAND") goto ok_gate;
if (g == "OR") goto ok_gate;
if (g == "NOR") goto ok_gate;
if (g == "XOR") goto ok_gate;
if (g == "XNOR") goto ok_gate;
if (g == "ANDNOT") goto ok_gate;
if (g == "ORNOT") goto ok_gate;
if (g == "MUX") goto ok_gate;
if (g == "NMUX") goto ok_gate;
if (g == "AOI3") goto ok_gate;
if (g == "OAI3") goto ok_gate;
if (g == "AOI4") goto ok_gate;
if (g == "OAI4") goto ok_gate;
if (g == "simple") {
gate_list.push_back("AND");
gate_list.push_back("OR");
gate_list.push_back("XOR");
gate_list.push_back("MUX");
goto ok_alias;
}
if (g == "cmos2") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
goto ok_alias;
}
if (g == "cmos3") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
goto ok_alias;
}
if (g == "cmos4") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
goto ok_alias;
}
if (g == "cmos") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("NMUX");
gate_list.push_back("MUX");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
goto ok_alias;
}
if (g == "gates") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
goto ok_alias;
}
if (g == "aig") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
goto ok_alias;
}
if (g == "all") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("MUX");
gate_list.push_back("NMUX");
}
cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
ok_gate:
gate_list.push_back(g);
ok_alias:
for (auto gate : gate_list) {
if (remove_gates)
enabled_gates.erase(gate);
else
enabled_gates.insert(gate);
}
}
continue; continue;
} }
if (arg == "-fast") { if (arg == "-fast") {
@ -1770,6 +1661,174 @@ struct AbcPass : public Pass {
} }
extra_args(args, argidx, design); 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;
rewrite_filename(liberty_file);
if (!liberty_file.empty() && !is_absolute_path(liberty_file))
liberty_file = std::string(pwd) + "/" + liberty_file;
rewrite_filename(constr_file);
if (!constr_file.empty() && !is_absolute_path(constr_file))
constr_file = std::string(pwd) + "/" + constr_file;
// handle -lut argument
if (!lut_arg.empty()) {
size_t pos = lut_arg.find_first_of(':');
int lut_mode = 0, lut_mode2 = 0;
if (pos != string::npos) {
lut_mode = atoi(lut_arg.substr(0, pos).c_str());
lut_mode2 = atoi(lut_arg.substr(pos+1).c_str());
} else {
lut_mode = atoi(lut_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));
}
//handle -luts argument
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) < std::atoi(parts.at(0).c_str()))
lut_costs.push_back(atoi(parts.at(1).c_str()));
else
log_cmd_error("Invalid -luts syntax.\n");
}
}
// handle -g argument
if (!g_arg.empty()){
for (auto g : split_tokens(g_arg, ",")) {
vector<string> gate_list;
bool remove_gates = false;
if (GetSize(g) > 0 && g[0] == '-') {
remove_gates = true;
g = g.substr(1);
}
if (g == "AND") goto ok_gate;
if (g == "NAND") goto ok_gate;
if (g == "OR") goto ok_gate;
if (g == "NOR") goto ok_gate;
if (g == "XOR") goto ok_gate;
if (g == "XNOR") goto ok_gate;
if (g == "ANDNOT") goto ok_gate;
if (g == "ORNOT") goto ok_gate;
if (g == "MUX") goto ok_gate;
if (g == "NMUX") goto ok_gate;
if (g == "AOI3") goto ok_gate;
if (g == "OAI3") goto ok_gate;
if (g == "AOI4") goto ok_gate;
if (g == "OAI4") goto ok_gate;
if (g == "simple") {
gate_list.push_back("AND");
gate_list.push_back("OR");
gate_list.push_back("XOR");
gate_list.push_back("MUX");
goto ok_alias;
}
if (g == "cmos2") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
goto ok_alias;
}
if (g == "cmos3") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
goto ok_alias;
}
if (g == "cmos4") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
goto ok_alias;
}
if (g == "cmos") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("NMUX");
gate_list.push_back("MUX");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
goto ok_alias;
}
if (g == "gates") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
goto ok_alias;
}
if (g == "aig") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
goto ok_alias;
}
if (g == "all") {
gate_list.push_back("AND");
gate_list.push_back("NAND");
gate_list.push_back("OR");
gate_list.push_back("NOR");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
gate_list.push_back("ANDNOT");
gate_list.push_back("ORNOT");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("MUX");
gate_list.push_back("NMUX");
}
if (g_arg_from_cmd)
cmd_error(args, g_argidx, stringf("Unsupported gate type: %s", g.c_str()));
else
log_cmd_error("Unsupported gate type: %s", g.c_str());
ok_gate:
gate_list.push_back(g);
ok_alias:
for (auto gate : gate_list) {
if (remove_gates)
enabled_gates.erase(gate);
else
enabled_gates.insert(gate);
}
}
}
if (!lut_costs.empty() && !liberty_file.empty()) if (!lut_costs.empty() && !liberty_file.empty())
log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n"); log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n");
if (!constr_file.empty() && liberty_file.empty()) if (!constr_file.empty() && liberty_file.empty())

View file

@ -40,7 +40,7 @@ struct Abc9Pass : public ScriptPass
log(" abc9 [options] [selection]\n"); log(" abc9 [options] [selection]\n");
log("\n"); log("\n");
log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n"); log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n");
log("library to a target architecture.\n"); log("library to a target architecture. Only fully-selected modules are supported.\n");
log("\n"); log("\n");
log(" -exe <command>\n"); log(" -exe <command>\n");
#ifdef ABCEXTERNAL #ifdef ABCEXTERNAL
@ -113,11 +113,6 @@ struct Abc9Pass : public ScriptPass
log(" print the temp dir name in log. usually this is suppressed so that the\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(" command output is identical across runs.\n");
log("\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(" -box <file>\n");
log(" pass this file with box library to ABC. Use with -lut.\n"); log(" pass this file with box library to ABC. Use with -lut.\n");
log("\n"); log("\n");
@ -150,6 +145,25 @@ struct Abc9Pass : public ScriptPass
std::string run_from, run_to; std::string run_from, run_to;
clear_flags(); clear_flags();
// get arguments from scratchpad first, then override by command arguments
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);
dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode);
cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup);
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; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) { for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx]; std::string arg = args[argidx];
@ -161,7 +175,7 @@ struct Abc9Pass : public ScriptPass
continue; continue;
} }
if (arg == "-fast" || /* arg == "-dff" || */ if (arg == "-fast" || /* arg == "-dff" || */
/* arg == "-nocleanup" || */ arg == "-showtmp" || arg == "-markgroups" || /* arg == "-nocleanup" || */ arg == "-showtmp" ||
arg == "-nomfs") { arg == "-nomfs") {
map_cmd << " " << arg; map_cmd << " " << arg;
continue; continue;
@ -210,6 +224,10 @@ struct Abc9Pass : public ScriptPass
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;
} }
log_assert(!module->attributes.count(ID(abc9_box_id)));
if (!design->selected_whole_module(module))
log_error("Can't handle partially selected module %s!\n", log_id(module));
active_design->selection().select(mod); active_design->selection().select(mod);

View file

@ -63,7 +63,6 @@ extern "C" int Abc_RealMain(int argc, char *argv[]);
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
bool markgroups;
int map_autoidx; int map_autoidx;
inline std::string remap_name(RTLIL::IdString abc9_name) inline std::string remap_name(RTLIL::IdString abc9_name)
@ -349,11 +348,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
if (mapped_mod == NULL) if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n"); log_error("ABC output file does not contain a module `$__abc9__'.\n");
for (auto &it : mapped_mod->wires_) { for (auto wire : mapped_mod->wires())
RTLIL::Wire *w = it.second; module->addWire(remap_name(w->name), GetSize(w));
RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
}
for (auto it = module->cells_.begin(); it != module->cells_.end(); ) for (auto it = module->cells_.begin(); it != module->cells_.end(); )
if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
@ -416,7 +412,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
} }
else else
log_abort(); log_abort();
if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue; continue;
} }
cell_stats[mapped_cell->type]++; cell_stats[mapped_cell->type]++;
@ -429,7 +424,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name)); 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)); SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name));
module->connect(my_y, my_a); module->connect(my_y, my_a);
if (markgroups) mapped_cell->attributes[ID(abcgroup)] = map_autoidx;
log_abort(); log_abort();
continue; continue;
} }
@ -441,7 +435,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
} }
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
if (existing_cell) { if (existing_cell) {
cell->parameters = existing_cell->parameters; cell->parameters = existing_cell->parameters;
cell->attributes = existing_cell->attributes; cell->attributes = existing_cell->attributes;
@ -660,8 +653,6 @@ struct Abc9MapPass : public Pass {
log(" set delay target. the string {D} in the default scripts above is\n"); 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(" replaced by this option when used, and an empty string otherwise\n");
log(" (indicating best possible delay).\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("\n");
// log(" -S <num>\n"); // log(" -S <num>\n");
// log(" maximum number of LUT inputs shared.\n"); // log(" maximum number of LUT inputs shared.\n");
@ -683,28 +674,14 @@ struct Abc9MapPass : public Pass {
log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n"); log(" 2, 3, .. inputs.\n");
log("\n"); log("\n");
// log(" -dff\n"); log(" -dff\n");
// log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
// log(" clock domains are automatically partitioned in clock domains and each\n"); log(" domains are marked as such and automatically partitioned by ABC.\n");
// log(" domain is passed through ABC independently.\n"); log("\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(" -showtmp\n"); log(" -showtmp\n");
log(" print the temp dir name in log. usually this is suppressed so that the\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(" command output is identical across runs.\n");
log("\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(" -box <file>\n");
log(" pass this file with box library to ABC. Use with -lut.\n"); log(" pass this file with box library to ABC. Use with -lut.\n");
log("\n"); log("\n");
@ -737,7 +714,6 @@ struct Abc9MapPass : public Pass {
bool show_tempdir = false; bool show_tempdir = false;
bool nomfs = false; bool nomfs = false;
vector<int> lut_costs; vector<int> lut_costs;
markgroups = false;
#if 0 #if 0
cleanup = false; cleanup = false;
@ -828,10 +804,6 @@ struct Abc9MapPass : public Pass {
show_tempdir = true; show_tempdir = true;
continue; continue;
} }
if (arg == "-markgroups") {
markgroups = true;
continue;
}
if (arg == "-box" && argidx+1 < args.size()) { if (arg == "-box" && argidx+1 < args.size()) {
box_file = args[++argidx]; box_file = args[++argidx];
continue; continue;
@ -871,6 +843,9 @@ struct Abc9MapPass : public Pass {
continue; continue;
} }
if (!design->selected_whole_module(mod))
log_error("Can't handle partially selected module %s!\n", log_id(module));
abc9_module(design, mod, script_file, exe_file, lut_costs, abc9_module(design, mod, script_file, exe_file, lut_costs,
delay_target, lutin_shared, fast_mode, show_tempdir, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, nomfs, tempdir_name); box_file, lut_file, wire_delay, nomfs, tempdir_name);

View file

@ -128,6 +128,8 @@ static void run_ice40_opts(Module *module)
new_attr.insert(std::make_pair(a.first, a.second)); new_attr.insert(std::make_pair(a.first, a.second));
else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived))) else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived)))
continue; continue;
else if (a.first.begins_with("\\SB_CARRY.\\"))
continue;
else else
log_abort(); log_abort();
cell->attributes = std::move(new_attr); cell->attributes = std::move(new_attr);

View file

@ -58,7 +58,7 @@ $__ABC9_ASYNC0 1000 1 2 1
# Box 1001 : $__ABC9_ASYNC1 # Box 1001 : $__ABC9_ASYNC1
# (private cell to emulate async behaviour of FDP*) # (private cell to emulate async behaviour of FDP*)
# name ID w/b ins outs # name ID w/b ins outs
$__ABC9_ASYNC1 1001 1 2 1 $__ABC9_ASYNC1 1001 1 2 1
#A S #A S
0 764 # Y 0 764 # Y