mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/xaig_dff' into eddie/abc9_refactor
This commit is contained in:
commit
921ff0f5e3
|
@ -376,10 +376,11 @@ Verilog Attributes and non-standard features
|
|||
- 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,
|
||||
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
|
||||
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
|
||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
||||
|
|
|
@ -787,6 +787,14 @@ struct AigerBackend : public Backend {
|
|||
if (top_module == nullptr)
|
||||
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);
|
||||
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ struct XAigerWriter
|
|||
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> unused_bits;
|
||||
|
@ -157,12 +157,8 @@ struct XAigerWriter
|
|||
if (wire->get_bool_attribute(ID::keep))
|
||||
sigmap.add(wire);
|
||||
|
||||
// First, collect all the ports in port_id order
|
||||
// since module->wires() could be sorted
|
||||
// alphabetically
|
||||
for (auto port : module->ports) {
|
||||
auto wire = module->wire(port);
|
||||
log_assert(wire);
|
||||
|
||||
for (auto wire : module->wires())
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
{
|
||||
SigBit wirebit(wire, i);
|
||||
|
@ -176,6 +172,9 @@ struct XAigerWriter
|
|||
continue;
|
||||
}
|
||||
|
||||
undriven_bits.insert(bit);
|
||||
unused_bits.insert(bit);
|
||||
|
||||
if (wire->port_input)
|
||||
input_bits.insert(bit);
|
||||
|
||||
|
@ -185,19 +184,6 @@ struct XAigerWriter
|
|||
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()) {
|
||||
if (cell->type == "$_NOT_")
|
||||
|
@ -402,12 +388,20 @@ struct XAigerWriter
|
|||
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::S1] = 1;
|
||||
|
||||
// pool<> iterates in LIFO order...
|
||||
for (int i = input_bits.size()-1; i >= 0; i--) {
|
||||
const auto &bit = *input_bits.element(i);
|
||||
for (const auto &bit : input_bits) {
|
||||
aig_m++, aig_i++;
|
||||
log_assert(!aig_map.count(bit));
|
||||
aig_map[bit] = 2*aig_m;
|
||||
|
@ -435,9 +429,7 @@ struct XAigerWriter
|
|||
aig_outputs.push_back(bit2aig(bit));
|
||||
}
|
||||
|
||||
// pool<> iterates in LIFO order...
|
||||
for (int i = output_bits.size()-1; i >= 0; i--) {
|
||||
const auto &bit = *output_bits.element(i);
|
||||
for (const auto &bit : output_bits) {
|
||||
ordered_outputs[bit] = aig_o++;
|
||||
aig_outputs.push_back(bit2aig(bit));
|
||||
}
|
||||
|
@ -618,7 +610,7 @@ struct XAigerWriter
|
|||
|
||||
if (holes_module) {
|
||||
std::stringstream a_buffer;
|
||||
XAigerWriter writer(holes_module);
|
||||
XAigerWriter writer(holes_module, true /* holes_mode */);
|
||||
writer.write_aiger(a_buffer, false /*ascii_mode*/);
|
||||
|
||||
f << "a";
|
||||
|
@ -654,17 +646,13 @@ struct XAigerWriter
|
|||
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> output_lines;
|
||||
dict<int, string> wire_lines;
|
||||
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
//if (!verbose_map && wire->name[0] == '$')
|
||||
// continue;
|
||||
|
||||
SigSpec sig = sigmap(wire);
|
||||
|
||||
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);
|
||||
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)
|
||||
f << it.second;
|
||||
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(" write_xaiger [options] [filename]\n");
|
||||
log("\n");
|
||||
log("Write the current design to an XAIGER file. The design must be flattened and\n");
|
||||
log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n");
|
||||
log("Write the top module (according to the (* top *) attribute or if only one module\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(" -ascii\n");
|
||||
log(" write ASCII version of AIGER format\n");
|
||||
|
@ -730,14 +708,10 @@ struct XAigerBackend : public Backend {
|
|||
log(" -map <filename>\n");
|
||||
log(" write an extra file with port and box symbols\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
|
||||
{
|
||||
bool ascii_mode = false;
|
||||
bool verbose_map = false;
|
||||
std::string map_filename;
|
||||
|
||||
log_header(design, "Executing XAIGER backend.\n");
|
||||
|
@ -753,11 +727,6 @@ struct XAigerBackend : public Backend {
|
|||
map_filename = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) {
|
||||
map_filename = args[++argidx];
|
||||
verbose_map = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx, !ascii_mode);
|
||||
|
@ -767,6 +736,14 @@ struct XAigerBackend : public Backend {
|
|||
if (top_module == nullptr)
|
||||
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);
|
||||
writer.write_aiger(*f, ascii_mode);
|
||||
|
||||
|
@ -775,7 +752,7 @@ struct XAigerBackend : public Backend {
|
|||
mapf.open(map_filename.c_str(), std::ofstream::trunc);
|
||||
if (mapf.fail())
|
||||
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;
|
||||
|
|
|
@ -1514,7 +1514,47 @@ struct AbcPass : public Pass {
|
|||
#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];
|
||||
if (!getcwd(pwd, sizeof(pwd))) {
|
||||
log_cmd_error("getcwd failed: %s\n", strerror(errno));
|
||||
|
@ -1528,23 +1568,14 @@ struct AbcPass : public Pass {
|
|||
}
|
||||
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 == "-liberty" && argidx+1 < args.size()) {
|
||||
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;
|
||||
}
|
||||
if (arg == "-constr" && argidx+1 < args.size()) {
|
||||
rewrite_filename(constr_file);
|
||||
constr_file = args[++argidx];
|
||||
if (!constr_file.empty() && !is_absolute_path(constr_file))
|
||||
constr_file = std::string(pwd) + "/" + constr_file;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-D" && argidx+1 < args.size()) {
|
||||
|
@ -1564,37 +1595,11 @@ struct AbcPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-lut" && argidx+1 < args.size()) {
|
||||
string 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));
|
||||
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) < 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");
|
||||
}
|
||||
luts_arg = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (arg == "-sop") {
|
||||
|
@ -1618,123 +1623,9 @@ struct AbcPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-g" && argidx+1 < args.size()) {
|
||||
for (auto g : split_tokens(args[++argidx], ",")) {
|
||||
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");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
g_arg = args[++argidx];
|
||||
g_argidx = argidx;
|
||||
g_arg_from_cmd = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-fast") {
|
||||
|
@ -1770,6 +1661,174 @@ struct AbcPass : public Pass {
|
|||
}
|
||||
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())
|
||||
log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n");
|
||||
if (!constr_file.empty() && liberty_file.empty())
|
||||
|
|
|
@ -40,7 +40,7 @@ struct Abc9Pass : public ScriptPass
|
|||
log(" abc9 [options] [selection]\n");
|
||||
log("\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(" -exe <command>\n");
|
||||
#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(" 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");
|
||||
|
@ -150,6 +145,25 @@ struct Abc9Pass : public ScriptPass
|
|||
std::string run_from, run_to;
|
||||
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;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
std::string arg = args[argidx];
|
||||
|
@ -161,7 +175,7 @@ struct Abc9Pass : public ScriptPass
|
|||
continue;
|
||||
}
|
||||
if (arg == "-fast" || /* arg == "-dff" || */
|
||||
/* arg == "-nocleanup" || */ arg == "-showtmp" || arg == "-markgroups" ||
|
||||
/* arg == "-nocleanup" || */ arg == "-showtmp" ||
|
||||
arg == "-nomfs") {
|
||||
map_cmd << " " << arg;
|
||||
continue;
|
||||
|
@ -210,6 +224,10 @@ struct Abc9Pass : public ScriptPass
|
|||
log("Skipping module %s as it contains processes.\n", log_id(mod));
|
||||
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);
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ extern "C" int Abc_RealMain(int argc, char *argv[]);
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool markgroups;
|
||||
int map_autoidx;
|
||||
|
||||
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)
|
||||
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 wire : mapped_mod->wires())
|
||||
module->addWire(remap_name(w->name), GetSize(w));
|
||||
|
||||
for (auto it = module->cells_.begin(); it != module->cells_.end(); )
|
||||
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
|
||||
log_abort();
|
||||
if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||
continue;
|
||||
}
|
||||
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_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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||
if (existing_cell) {
|
||||
cell->parameters = existing_cell->parameters;
|
||||
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(" 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");
|
||||
|
@ -683,28 +674,14 @@ struct Abc9MapPass : public Pass {
|
|||
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");
|
||||
|
@ -737,7 +714,6 @@ struct Abc9MapPass : public Pass {
|
|||
bool show_tempdir = false;
|
||||
bool nomfs = false;
|
||||
vector<int> lut_costs;
|
||||
markgroups = false;
|
||||
|
||||
#if 0
|
||||
cleanup = false;
|
||||
|
@ -828,10 +804,6 @@ struct Abc9MapPass : public Pass {
|
|||
show_tempdir = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-markgroups") {
|
||||
markgroups = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-box" && argidx+1 < args.size()) {
|
||||
box_file = args[++argidx];
|
||||
continue;
|
||||
|
@ -871,6 +843,9 @@ struct Abc9MapPass : public Pass {
|
|||
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,
|
||||
delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||
box_file, lut_file, wire_delay, nomfs, tempdir_name);
|
||||
|
|
|
@ -128,6 +128,8 @@ static void run_ice40_opts(Module *module)
|
|||
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)))
|
||||
continue;
|
||||
else if (a.first.begins_with("\\SB_CARRY.\\"))
|
||||
continue;
|
||||
else
|
||||
log_abort();
|
||||
cell->attributes = std::move(new_attr);
|
||||
|
|
|
@ -58,7 +58,7 @@ $__ABC9_ASYNC0 1000 1 2 1
|
|||
# Box 1001 : $__ABC9_ASYNC1
|
||||
# (private cell to emulate async behaviour of FDP*)
|
||||
# name ID w/b ins outs
|
||||
$__ABC9_ASYNC1 1001 1 2 1
|
||||
$__ABC9_ASYNC1 1001 1 2 1
|
||||
#A S
|
||||
0 764 # Y
|
||||
|
||||
|
|
Loading…
Reference in New Issue