* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2019 Eddie Hung <eddie@fpgeh.com>
+ * 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
-#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if -W 160 -v; &ps -l"
+#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if {W} -v; &ps -l"
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
}
};
-static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
-{
- int pos = -1;
-
- if (name.empty() || name.back() != ']')
- goto failed;
-
- for (int i = 0; i+1 < GetSize(name); i++) {
- if (name[i] == '[')
- pos = i;
- else if (name[i] < '0' || name[i] > '9')
- pos = -1;
- else if (i == pos+1 && name[i] == '0' && name[i+1] != ']')
- pos = -1;
- }
-
- if (pos >= 0)
- return std::pair<RTLIL::IdString, int>(RTLIL::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1));
-
-failed:
- return std::pair<RTLIL::IdString, int>(name, 0);
-}
-
void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
- const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file)
+ const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file,
+ std::string wire_delay)
{
module = current_module;
map_autoidx = autoidx++;
for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
+ for (size_t pos = abc_script.find("{W}"); pos != std::string::npos; pos = abc_script.find("{W}", pos))
+ abc_script = abc_script.substr(0, pos) + wire_delay + abc_script.substr(pos+3);
+
abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
abc_script = add_echos_to_abc_cmd(abc_script);
}
}
- design->selection_stack.emplace_back(false);
- RTLIL::Selection& sel = design->selection_stack.back();
- sel.select(module);
+ bool count_output = false;
+ for (auto port_name : module->ports) {
+ RTLIL::Wire *port_wire = module->wire(port_name);
+ log_assert(port_wire);
+ if (port_wire->port_output) {
+ count_output = true;
+ break;
+ }
+ }
- // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
- Pass::call(design, "setundef -zero");
+ log_push();
- Pass::call(design, "aigmap");
+ if (count_output)
+ {
+ design->selection_stack.emplace_back(false);
+ RTLIL::Selection& sel = design->selection_stack.back();
+ sel.select(module);
- handle_loops(design);
+ // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
+ Pass::call(design, "setundef -zero");
- Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
+ Pass::call(design, "aigmap");
-#if 0
- std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
- std::ifstream ifs;
- ifs.open(buffer);
- if (ifs.fail())
- log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
- buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
- log_assert(!design->module("$__abc9__"));
- AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
- reader.parse_xaiger();
- ifs.close();
- Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
- design->remove(design->module("$__abc9__"));
-#endif
+ handle_loops(design);
- design->selection_stack.pop_back();
+ //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);
+
+ Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
- // Now 'unexpose' those wires by undoing
- // the expose operation -- remove them from PO/PI
- // and re-connecting them back together
- for (auto wire : module->wires()) {
- auto it = wire->attributes.find("\\abc_scc_break");
- if (it != wire->attributes.end()) {
- wire->attributes.erase(it);
- log_assert(wire->port_output);
- wire->port_output = false;
- RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
- log_assert(i_wire);
- log_assert(i_wire->port_input);
- i_wire->port_input = false;
- module->connect(i_wire, wire);
+ std::string buffer;
+ std::ifstream ifs;
+#if 0
+ buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
+ ifs.open(buffer);
+ if (ifs.fail())
+ log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
+ buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
+ log_assert(!design->module("$__abc9__"));
+ {
+ AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
+ reader.parse_xaiger();
}
- }
- module->fixup_ports();
+ ifs.close();
+ Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
+ design->remove(design->module("$__abc9__"));
+#endif
- //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);
+ design->selection_stack.pop_back();
+
+ // Now 'unexpose' those wires by undoing
+ // the expose operation -- remove them from PO/PI
+ // and re-connecting them back together
+ for (auto wire : module->wires()) {
+ auto it = wire->attributes.find("\\abc_scc_break");
+ if (it != wire->attributes.end()) {
+ wire->attributes.erase(it);
+ log_assert(wire->port_output);
+ wire->port_output = false;
+ RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
+ log_assert(i_wire);
+ log_assert(i_wire->port_input);
+ i_wire->port_input = false;
+ module->connect(i_wire, wire);
+ }
+ }
+ module->fixup_ports();
- log_push();
- //if (count_output > 0)
- {
log_header(design, "Executing ABC9.\n");
- std::string buffer;
if (!lut_costs.empty()) {
buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig");
- std::ifstream ifs;
ifs.open(buffer);
if (ifs.fail())
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
//parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__"));
- AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
+ AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger();
ifs.close();
if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx;
if (w->port_output) {
RTLIL::Wire *wire = module->wire(w->name);
- if (wire) {
- for (int i = 0; i < GetSize(wire); i++)
- output_bits.insert({wire, i});
- }
- else {
- // Attempt another wideports_split here because there
- // exists the possibility that different bits of a port
- // could be an input and output, therefore parse_xaiger()
- // could not combine it into a wideport
- auto r = wideports_split(w->name.str());
- wire = module->wire(r.first);
- log_assert(wire);
- int i = r.second;
+ log_assert(wire);
+ for (int i = 0; i < GetSize(wire); i++)
output_bits.insert({wire, i});
- }
}
}
RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
if (!a_bit.wire) {
c->setPort("\\Y", module->addWire(NEW_ID));
- module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1);
+ RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
+ log_assert(wire);
+ module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1);
}
else if (!lut_costs.empty() || !lut_file.empty()) {
RTLIL::Cell* driving_lut = nullptr;
continue;
}
}
- cell_stats[RTLIL::unescape_id(c->type)]++;
+ cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "$lut") {
if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
}
}
else {
- auto it = erased_boxes.find(c->name);
- log_assert(it != erased_boxes.end());
- c->parameters = std::move(it->second);
- }
+ auto it = erased_boxes.find(c->name);
+ log_assert(it != erased_boxes.end());
+ c->parameters = std::move(it->second);
+ }
RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type);
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
if (!w->port_input && !w->port_output)
continue;
RTLIL::Wire *wire = module->wire(w->name);
+ log_assert(wire);
RTLIL::Wire *remap_wire = module->wire(remap_name(w->name));
- RTLIL::SigSpec signal;
- if (wire) {
- signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
- }
- else {
- // Attempt another wideports_split here because there
- // exists the possibility that different bits of a port
- // could be an input and output, therefore parse_xaiger()
- // could not combine it into a wideport
- auto r = wideports_split(w->name.str());
- wire = module->wire(r.first);
- log_assert(wire);
- int i = r.second;
- signal = RTLIL::SigSpec(wire, i);
- }
+ RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
log_assert(GetSize(signal) >= GetSize(remap_wire));
log_assert(w->port_input || w->port_output);
design->remove(mapped_mod);
}
- //else
- //{
- // log("Don't call ABC as there is nothing to map.\n");
- //}
+ else
+ {
+ log("Don't call ABC as there is nothing to map.\n");
+ }
if (cleanup)
{
std::string exe_file = proc_self_dirname() + "yosys-abc";
#endif
std::string script_file, liberty_file, constr_file, clk_str, box_file, lut_file;
- std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
+ std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1", wire_delay;
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
bool show_tempdir = false, sop_mode = false;
vector<int> lut_costs;
box_file = std::string(pwd) + "/" + box_file;
continue;
}
+ if (arg == "-W" && argidx+1 < args.size()) {
+ wire_delay = "-W " + args[++argidx];
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
- box_file, lut_file);
+ box_file, lut_file, wire_delay);
continue;
}
en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
- box_file, lut_file);
+ box_file, lut_file, wire_delay);
assign_map.set(mod);
}
}