32 #define ABC_COMMAND_LIB "strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; map -v {D}"
33 #define ABC_COMMAND_CTR "strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; stime -p"
34 #define ABC_COMMAND_LUT "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; if -v"
35 #define ABC_COMMAND_DFL "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; map -v"
37 #define ABC_FAST_COMMAND_LIB "retime -v {D}; map -v {D}"
38 #define ABC_FAST_COMMAND_CTR "retime -v {D}; map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; stime -p"
39 #define ABC_FAST_COMMAND_LUT "retime -v; if -v"
40 #define ABC_FAST_COMMAND_DFL "retime -v; map -v"
81 #define G(_name) gate_type_t::G_ ## _name
103 assign_map.
apply(bit);
121 if (gate_type !=
G(NONE))
122 gate.
type = gate_type;
144 if (cell->
type ==
"$_DFF_N_" || cell->
type ==
"$_DFF_P_")
155 for (
auto &c : sig_q.
chunks())
157 c.wire->attributes[
"\\keep"] = 1;
159 assign_map.
apply(sig_d);
160 assign_map.
apply(sig_q);
168 if (cell->
type.
in(
"$_BUF_",
"$_NOT_"))
173 assign_map.
apply(sig_a);
174 assign_map.
apply(sig_y);
182 if (cell->
type.
in(
"$_AND_",
"$_NAND_",
"$_OR_",
"$_NOR_",
"$_XOR_",
"$_XNOR_"))
188 assign_map.
apply(sig_a);
189 assign_map.
apply(sig_b);
190 assign_map.
apply(sig_y);
195 if (cell->
type ==
"$_AND_")
197 else if (cell->
type ==
"$_NAND_")
199 else if (cell->
type ==
"$_OR_")
201 else if (cell->
type ==
"$_NOR_")
203 else if (cell->
type ==
"$_XOR_")
205 else if (cell->
type ==
"$_XNOR_")
214 if (cell->
type ==
"$_MUX_")
221 assign_map.
apply(sig_a);
222 assign_map.
apply(sig_b);
223 assign_map.
apply(sig_s);
224 assign_map.
apply(sig_y);
230 map_signal(sig_y,
G(MUX), mapped_a, mapped_b, mapped_s);
236 if (cell->
type.
in(
"$_AOI3_",
"$_OAI3_"))
243 assign_map.
apply(sig_a);
244 assign_map.
apply(sig_b);
245 assign_map.
apply(sig_c);
246 assign_map.
apply(sig_y);
252 map_signal(sig_y, cell->
type ==
"$_AOI3_" ?
G(AOI3) :
G(OAI3), mapped_a, mapped_b, mapped_c);
258 if (cell->
type.
in(
"$_AOI4_",
"$_OAI4_"))
266 assign_map.
apply(sig_a);
267 assign_map.
apply(sig_b);
268 assign_map.
apply(sig_c);
269 assign_map.
apply(sig_d);
270 assign_map.
apply(sig_y);
277 map_signal(sig_y, cell->
type ==
"$_AOI4_" ?
G(AOI4) :
G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
286 std::stringstream sstr;
291 void dump_loop_graph(FILE *f,
int &nr, std::map<
int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
296 log(
"Dumping loop state graph to slide %d.\n", ++nr);
298 fprintf(f,
"digraph \"slide%d\" {\n", nr);
299 fprintf(f,
" label=\"slide%d\";\n", nr);
300 fprintf(f,
" rankdir=\"TD\";\n");
303 for (
auto &e : edges) {
304 nodes.insert(e.first);
305 for (
auto n : e.second)
311 n, in_counts[
n], workpool.count(n) ?
", shape=box" :
"");
313 for (
auto &e : edges)
314 for (
auto n : e.second)
315 fprintf(f,
" n%d -> n%d;\n", e.first, n);
325 std::map<int, std::set<int>> edges;
326 std::vector<int> in_edges_count(
signal_list.size());
327 std::set<int> workpool;
336 if (g.type ==
G(NONE) || g.type ==
G(FF)) {
337 workpool.insert(g.id);
340 edges[g.in1].insert(g.id);
341 in_edges_count[g.id]++;
343 if (g.in2 >= 0 && g.in2 != g.in1) {
344 edges[g.in2].insert(g.id);
345 in_edges_count[g.id]++;
347 if (g.in3 >= 0 && g.in3 != g.in2 && g.in3 != g.in1) {
348 edges[g.in3].insert(g.id);
349 in_edges_count[g.id]++;
351 if (g.in4 >= 0 && g.in4 != g.in3 && g.in4 != g.in2 && g.in4 != g.in1) {
352 edges[g.in4].insert(g.id);
353 in_edges_count[g.id]++;
360 while (workpool.size() > 0)
362 int id = *workpool.begin();
367 for (
int id2 : edges[
id]) {
369 if (--in_edges_count[id2] == 0)
370 workpool.insert(id2);
376 while (workpool.size() == 0)
378 if (edges.size() == 0)
381 int id1 = edges.begin()->first;
383 for (
auto &edge_it : edges) {
384 int id2 = edge_it.first;
391 else if (w1->
name[0] ==
'$' && w2->
name[0] ==
'\\')
393 else if (w1->
name[0] ==
'\\' && w2->
name[0] ==
'$')
395 else if (edges[id1].size() < edges[id2].size())
397 else if (edges[id1].size() > edges[id2].size())
403 if (edges[id1].size() == 0) {
410 std::stringstream sstr;
411 sstr <<
"$abcloop$" << (
autoidx++);
414 bool first_line =
true;
415 for (
int id2 : edges[id1]) {
426 signal_list[id1].is_port =
true;
427 signal_list[id3].is_port =
true;
428 log_assert(id3 ==
int(in_edges_count.size()));
429 in_edges_count.push_back(0);
430 workpool.insert(id3);
432 for (
int id2 : edges[id1]) {
433 if (signal_list[id2].in1 == id1)
434 signal_list[id2].in1 = id3;
435 if (signal_list[id2].in2 == id1)
436 signal_list[id2].in2 = id3;
437 if (signal_list[id2].in3 == id1)
438 signal_list[id2].in3 = id3;
439 if (signal_list[id2].in4 == id1)
440 signal_list[id2].in4 = id3;
442 edges[id1].swap(edges[id3]);
455 std::string new_str, token;
456 for (
size_t i = 0; i < str.size(); i++) {
459 while (i+1 < str.size() && str[i+1] ==
' ')
461 if (!new_str.empty())
463 new_str +=
"echo + " + token +
" " + token +
" ";
468 if (!token.empty()) {
469 if (!new_str.empty())
470 new_str +=
"echo; echo + " + token +
"; ";
479 std::string token, new_str =
" ";
480 int char_counter = 10;
482 for (
size_t i = 0; i <= str.size(); i++) {
485 if (i == str.size() || str[i] ==
';') {
486 if (char_counter + token.size() > 75)
487 new_str +=
"\n ", char_counter = 14;
488 new_str += token, char_counter += token.size();
519 if ((ch <
'0' ||
'9' < ch) && ch !=
';')
546 std::string liberty_file, std::string constr_file,
bool cleanup,
int lut_mode,
bool dff_mode, std::string clk_str,
547 bool keepff, std::string delay_target,
bool fast_mode)
554 assign_map.
set(module);
559 std::string tempdir_name =
"/tmp/yosys-abc-XXXXXX";
561 tempdir_name[0] = tempdir_name[4] =
'_';
563 log_header(
"Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->
name.
c_str(), tempdir_name.c_str());
565 std::string abc_script =
stringf(
"read_blif %s/input.blif; ", tempdir_name.c_str());
567 if (!liberty_file.empty()) {
568 abc_script +=
stringf(
"read_lib -w %s; ", liberty_file.c_str());
569 if (!constr_file.empty())
570 abc_script +=
stringf(
"read_constr -v %s; ", constr_file.c_str());
573 abc_script +=
stringf(
"read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
575 abc_script +=
stringf(
"read_library %s/stdcells.genlib; ", tempdir_name.c_str());
577 if (!script_file.empty()) {
578 if (script_file[0] ==
'+') {
579 for (
size_t i = 1; i < script_file.size(); i++)
580 if (script_file[i] ==
'\'')
581 abc_script +=
"'\\''";
582 else if (script_file[i] ==
',')
585 abc_script += script_file[i];
587 abc_script +=
stringf(
"source %s", script_file.c_str());
590 else if (!liberty_file.empty())
595 for (
size_t pos = abc_script.find(
"{D}"); pos != std::string::npos; pos = abc_script.find(
"{D}", pos))
596 abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
598 abc_script +=
stringf(
"; write_blif %s/output.blif", tempdir_name.c_str());
601 for (
size_t i = 0; i+1 < abc_script.size(); i++)
602 if (abc_script[i] ==
';' && abc_script[i+1] ==
' ')
603 abc_script[i+1] =
'\n';
605 FILE *f = fopen(
stringf(
"%s/abc.script", tempdir_name.c_str()).c_str(),
"wt");
606 fprintf(f,
"%s\n", abc_script.c_str());
609 if (clk_str.empty()) {
610 if (clk_str[0] ==
'!') {
612 clk_str = clk_str.substr(1);
618 if (dff_mode && clk_sig.
size() == 0)
620 int best_dff_counter = 0;
621 std::map<std::pair<bool, RTLIL::SigSpec>,
int> dff_counters;
623 for (
auto &it : module->
cells_)
626 if (cell->
type !=
"$_DFF_N_" && cell->
type !=
"$_DFF_P_")
629 std::pair<bool, RTLIL::SigSpec> key(cell->
type ==
"$_DFF_P_", assign_map(cell->
getPort(
"\\C")));
630 if (++dff_counters[key] > best_dff_counter) {
631 best_dff_counter = dff_counters[key];
633 clk_sig = key.second;
638 if (dff_mode || !clk_str.empty()) {
639 if (clk_sig.
size() == 0)
640 log(
"No (matching) clock domain found. Not extracting any FF cells.\n");
645 if (clk_sig.
size() != 0)
648 std::vector<RTLIL::Cell*> cells;
649 cells.reserve(module->
cells_.size());
650 for (
auto &it : module->
cells_)
651 if (design->
selected(current_module, it.second))
652 cells.push_back(it.second);
656 for (
auto &wire_it : module->
wires_) {
657 if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(
"\\keep"))
661 for (
auto &cell_it : module->
cells_)
662 for (
auto &port_it : cell_it.second->connections())
667 std::string buffer =
stringf(
"%s/input.blif", tempdir_name.c_str());
668 f = fopen(buffer.c_str(),
"wt");
670 log_error(
"Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
672 fprintf(f,
".model netlist\n");
675 fprintf(f,
".inputs");
677 if (!si.is_port || si.type !=
G(NONE))
679 fprintf(f,
" n%d", si.id);
682 if (count_input == 0)
683 fprintf(f,
" dummy_input\n");
686 int count_output = 0;
687 fprintf(f,
".outputs");
688 for (
auto &si : signal_list) {
689 if (!si.is_port || si.type ==
G(NONE))
691 fprintf(f,
" n%d", si.id);
696 for (
auto &si : signal_list)
697 fprintf(f,
"# n%-5d %s\n", si.id,
log_signal(si.bit));
699 for (
auto &si : signal_list) {
700 if (si.bit.wire ==
NULL) {
701 fprintf(f,
".names n%d\n", si.id);
708 for (
auto &si : signal_list) {
709 if (si.type ==
G(BUF)) {
710 fprintf(f,
".names n%d n%d\n", si.in1, si.id);
712 }
else if (si.type ==
G(NOT)) {
713 fprintf(f,
".names n%d n%d\n", si.in1, si.id);
715 }
else if (si.type ==
G(AND)) {
716 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
717 fprintf(f,
"11 1\n");
718 }
else if (si.type ==
G(NAND)) {
719 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
720 fprintf(f,
"0- 1\n");
721 fprintf(f,
"-0 1\n");
722 }
else if (si.type ==
G(OR)) {
723 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
724 fprintf(f,
"-1 1\n");
725 fprintf(f,
"1- 1\n");
726 }
else if (si.type ==
G(NOR)) {
727 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
728 fprintf(f,
"00 1\n");
729 }
else if (si.type ==
G(XOR)) {
730 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
731 fprintf(f,
"01 1\n");
732 fprintf(f,
"10 1\n");
733 }
else if (si.type ==
G(XNOR)) {
734 fprintf(f,
".names n%d n%d n%d\n", si.in1, si.in2, si.id);
735 fprintf(f,
"00 1\n");
736 fprintf(f,
"11 1\n");
737 }
else if (si.type ==
G(MUX)) {
738 fprintf(f,
".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
739 fprintf(f,
"1-0 1\n");
740 fprintf(f,
"-11 1\n");
741 }
else if (si.type ==
G(AOI3)) {
742 fprintf(f,
".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
743 fprintf(f,
"-00 1\n");
744 fprintf(f,
"0-0 1\n");
745 }
else if (si.type ==
G(OAI3)) {
746 fprintf(f,
".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
747 fprintf(f,
"00- 1\n");
748 fprintf(f,
"--0 1\n");
749 }
else if (si.type ==
G(AOI4)) {
750 fprintf(f,
".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
751 fprintf(f,
"-0-0 1\n");
752 fprintf(f,
"-00- 1\n");
753 fprintf(f,
"0--0 1\n");
754 fprintf(f,
"0-0- 1\n");
755 }
else if (si.type ==
G(OAI4)) {
756 fprintf(f,
".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
757 fprintf(f,
"00-- 1\n");
758 fprintf(f,
"--00 1\n");
759 }
else if (si.type ==
G(FF)) {
760 fprintf(f,
".latch n%d n%d\n", si.in1, si.id);
761 }
else if (si.type !=
G(NONE))
763 if (si.type !=
G(NONE))
767 fprintf(f,
".end\n");
770 log(
"Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
771 count_gates,
GetSize(signal_list), count_input, count_output);
774 if (count_output > 0)
778 buffer =
stringf(
"%s/stdcells.genlib", tempdir_name.c_str());
779 f = fopen(buffer.c_str(),
"wt");
781 log_error(
"Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
782 fprintf(f,
"GATE ZERO 1 Y=CONST0;\n");
783 fprintf(f,
"GATE ONE 1 Y=CONST1;\n");
784 fprintf(f,
"GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n",
get_cell_cost(
"$_BUF_"));
785 fprintf(f,
"GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_NOT_"));
786 fprintf(f,
"GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n",
get_cell_cost(
"$_AND_"));
787 fprintf(f,
"GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_NAND_"));
788 fprintf(f,
"GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n",
get_cell_cost(
"$_OR_"));
789 fprintf(f,
"GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_NOR_"));
790 fprintf(f,
"GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n",
get_cell_cost(
"$_XOR_"));
791 fprintf(f,
"GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n",
get_cell_cost(
"$_XNOR_"));
792 fprintf(f,
"GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_AOI3_"));
793 fprintf(f,
"GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_OAI3_"));
794 fprintf(f,
"GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_AOI4_"));
795 fprintf(f,
"GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n",
get_cell_cost(
"$_OAI4_"));
796 fprintf(f,
"GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n",
get_cell_cost(
"$_MUX_"));
800 buffer =
stringf(
"%s/lutdefs.txt", tempdir_name.c_str());
801 f = fopen(buffer.c_str(),
"wt");
803 log_error(
"Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
804 for (
int i = 0; i < lut_mode; i++)
805 fprintf(f,
"%d 1.00 1.00\n", i+1);
809 buffer =
stringf(
"%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
810 log(
"Running ABC command: %s\n", buffer.c_str());
815 log_error(
"ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
817 buffer =
stringf(
"%s/%s", tempdir_name.c_str(),
"output.blif");
818 f = fopen(buffer.c_str(),
"rt");
820 log_error(
"Can't open ABC output file `%s'.\n", buffer.c_str());
822 bool builtin_lib = liberty_file.empty() && script_file.empty() && !lut_mode;
829 if (mapped_mod ==
NULL)
830 log_error(
"ABC output file does not contain a module `netlist'.\n");
831 for (
auto &it : mapped_mod->
wires_) {
834 design->
select(module, wire);
837 std::map<std::string, int> cell_stats;
840 for (
auto &it : mapped_mod->
cells_) {
843 if (c->
type ==
"\\ZERO" || c->
type ==
"\\ONE") {
850 if (c->
type ==
"\\BUF") {
857 if (c->
type ==
"\\NOT") {
861 design->
select(module, cell);
864 if (c->
type ==
"\\AND" || c->
type ==
"\\OR" || c->
type ==
"\\XOR" || c->
type ==
"\\NAND" || c->
type ==
"\\NOR" || c->
type ==
"\\XNOR") {
869 design->
select(module, cell);
872 if (c->
type ==
"\\MUX") {
878 design->
select(module, cell);
881 if (c->
type ==
"\\AOI3" || c->
type ==
"\\OAI3") {
887 design->
select(module, cell);
890 if (c->
type ==
"\\AOI4" || c->
type ==
"\\OAI4") {
897 design->
select(module, cell);
900 if (c->
type ==
"\\DFF") {
905 cell->setPort(
"\\C", clk_sig);
906 design->
select(module, cell);
914 for (
auto &it : mapped_mod->
cells_)
918 if (c->
type ==
"\\_const0_" || c->
type ==
"\\_const1_") {
925 if (c->
type ==
"\\_dff_") {
930 cell->setPort(
"\\C", clk_sig);
931 design->
select(module, cell);
938 for (
auto &c : conn.second.chunks()) {
944 cell->
setPort(conn.first, newsig);
946 design->
select(module, cell);
951 if (!conn.first.is_fully_const())
953 if (!conn.second.is_fully_const())
958 for (
auto &it : cell_stats)
959 log(
"ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
960 int in_wires = 0, out_wires = 0;
961 for (
auto &si : signal_list)
964 snprintf(buffer, 100,
"\\n%d", si.id);
966 if (si.type !=
G(NONE)) {
972 conn.second = si.bit;
977 log(
"ABC RESULTS: internal signals: %8d\n",
int(signal_list.size()) - in_wires - out_wires);
978 log(
"ABC RESULTS: input signals: %8d\n", in_wires);
979 log(
"ABC RESULTS: output signals: %8d\n", out_wires);
981 delete mapped_design;
985 log(
"Don't call ABC as there is nothing to map.\n");
990 log_header(
"Removing temp directory `%s':\n", tempdir_name.c_str());
1003 log(
" abc [options] [selection]\n");
1005 log(
"This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n");
1006 log(
"library to a target architecture.\n");
1008 log(
" -exe <command>\n");
1009 log(
" use the specified command name instead of \"yosys-abc\" to execute ABC.\n");
1010 log(
" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
1012 log(
" -script <file>\n");
1013 log(
" use the specified ABC script file instead of the default script.\n");
1015 log(
" if <file> starts with a plus sign (+), then the rest of the filename\n");
1016 log(
" string is interprated as the command string to be passed to ABC. the\n");
1017 log(
" leading plus sign is removed and all commas (,) in the string are\n");
1018 log(
" replaced with blanks before the string is passed to ABC.\n");
1020 log(
" if no -script parameter is given, the following scripts are used:\n");
1022 log(
" for -liberty without -constr:\n");
1025 log(
" for -liberty with -constr:\n");
1028 log(
" for -lut:\n");
1031 log(
" otherwise:\n");
1035 log(
" use different default scripts that are slightly faster (at the cost\n");
1036 log(
" of output quality):\n");
1038 log(
" for -liberty without -constr:\n");
1041 log(
" for -liberty with -constr:\n");
1044 log(
" for -lut:\n");
1047 log(
" otherwise:\n");
1050 log(
" -liberty <file>\n");
1051 log(
" generate netlists for the specified cell library (using the liberty\n");
1052 log(
" file format).\n");
1054 log(
" -constr <file>\n");
1055 log(
" pass this file with timing constraints to ABC. use with -liberty.\n");
1057 log(
" a constr file contains two lines:\n");
1058 log(
" set_driving_cell <cell_name>\n");
1059 log(
" set_load <floating_point_number>\n");
1061 log(
" the set_driving_cell statement defines which cell type is assumed to\n");
1062 log(
" drive the primary inputs and the set_load statement sets the load in\n");
1063 log(
" femtofarads for each primary output.\n");
1065 log(
" -D <picoseconds>\n");
1066 log(
" set delay target. the string {D} in the default scripts above is\n");
1067 log(
" replaced by this option when used, and an empty string otherwise.\n");
1069 log(
" -lut <width>\n");
1070 log(
" generate netlist using luts of (max) the specified width.\n");
1073 log(
" also pass $_DFF_?_ cells through ABC (only one clock domain, if many\n");
1074 log(
" clock domains are present in a module, the one with the largest number\n");
1075 log(
" of $_DFF_?_ cells in it is used)\n");
1077 log(
" -clk [!]<signal-name>\n");
1078 log(
" use the specified clock domain. (when this option is used in combination\n");
1079 log(
" with -dff, then it falls back to the automatic dection of clock domain\n");
1080 log(
" if the specified clock is not found in a module.)\n");
1083 log(
" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
1084 log(
" them, for example for equivialence checking.)\n");
1086 log(
" -nocleanup\n");
1087 log(
" when this option is used, the temporary files created by this pass\n");
1088 log(
" are not removed. this is useful for debugging.\n");
1090 log(
"When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
1091 log(
"loaded into ABC before the ABC script is executed.\n");
1093 log(
"This pass does not operate on modules with unprocessed processes in it.\n");
1094 log(
"(I.e. the 'proc' pass should be used first to convert processes to netlists.)\n");
1096 log(
"[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
1101 log_header(
"Executing ABC pass (technology mapping using ABC).\n");
1105 std::string script_file, liberty_file, constr_file, clk_str, delay_target;
1106 bool fast_mode =
false, dff_mode =
false, keepff =
false, cleanup =
true;
1115 char pwd [PATH_MAX];
1116 if (!getcwd(pwd,
sizeof(pwd))) {
1120 for (argidx = 1; argidx < args.size(); argidx++) {
1121 std::string arg = args[argidx];
1122 if (arg ==
"-exe" && argidx+1 < args.size()) {
1123 exe_file = args[++argidx];
1126 if (arg ==
"-script" && argidx+1 < args.size()) {
1127 script_file = args[++argidx];
1128 if (!script_file.empty() && script_file[0] !=
'/' && script_file[0] !=
'+')
1129 script_file = std::string(pwd) +
"/" + script_file;
1132 if (arg ==
"-liberty" && argidx+1 < args.size()) {
1133 liberty_file = args[++argidx];
1134 if (!liberty_file.empty() && liberty_file[0] !=
'/')
1135 liberty_file = std::string(pwd) +
"/" + liberty_file;
1138 if (arg ==
"-constr" && argidx+1 < args.size()) {
1139 constr_file = args[++argidx];
1140 if (!constr_file.empty() && constr_file[0] !=
'/')
1141 constr_file = std::string(pwd) +
"/" + constr_file;
1144 if (arg ==
"-D" && argidx+1 < args.size()) {
1145 delay_target =
"-D " + args[++argidx];
1148 if (arg ==
"-lut" && argidx+1 < args.size()) {
1149 lut_mode = atoi(args[++argidx].c_str());
1152 if (arg ==
"-fast") {
1156 if (arg ==
"-dff") {
1160 if (arg ==
"-clk" && argidx+1 < args.size()) {
1161 clk_str = args[++argidx];
1164 if (arg ==
"-keepff") {
1168 if (arg ==
"-nocleanup") {
1176 if (lut_mode != 0 && !liberty_file.empty())
1177 log_cmd_error(
"Got -lut and -liberty! This two options are exclusive.\n");
1178 if (!constr_file.empty() && liberty_file.empty())
1181 for (
auto &mod_it : design->
modules_)
1182 if (design->
selected(mod_it.second)) {
1183 if (mod_it.second->processes.size() > 0)
1184 log(
"Skipping module %s as it contains processes.\n", mod_it.second->name.c_str());
1186 abc_module(design, mod_it.second, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode);
const char * c_str() const
bool selected(T1 *module) const
#define ABC_FAST_COMMAND_DFL
std::string add_echos_to_abc_cmd(std::string str)
std::string stringf(const char *fmt,...)
void remove_directory(std::string dirname)
void extract_cell(RTLIL::Cell *cell, bool keepff)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
const std::vector< RTLIL::SigSig > & connections() const
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
static std::string unescape_id(std::string str)
void mark_port(RTLIL::SigSpec sig)
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
void log_error(const char *format,...)
std::map< RTLIL::IdString, RTLIL::Const > parameters
bool in(T first, Args...rest)
void select(T1 *module, T2 *member)
int run_command(const std::string &command, std::function< void(const std::string &)> process_line)
void apply(RTLIL::SigBit &bit) const
static std::string escape_id(std::string str)
RTLIL::Design * abc_parse_blif(FILE *f, std::string dff_name)
void set(RTLIL::Module *module)
void connect(const RTLIL::SigSig &conn)
std::string proc_self_dirname()
#define PRIVATE_NAMESPACE_BEGIN
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
int GetSize(RTLIL::Wire *wire)
void abc_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, int lut_mode, bool dff_mode, std::string clk_str, bool keepff, std::string delay_target, bool fast_mode)
#define log_assert(_assert_expr_)
void dump_loop_graph(FILE *f, int &nr, std::map< int, std::set< int >> &edges, std::set< int > &workpool, std::vector< int > &in_counts)
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
int map_signal(RTLIL::SigBit bit, gate_type_t gate_type=G(NONE), int in1=-1, int in2=-1, int in3=-1, int in4=-1)
std::vector< gate_t > signal_list
YOSYS_NAMESPACE_BEGIN int get_cell_cost(RTLIL::Cell *cell, std::map< RTLIL::Module *, int > *mod_cost_cache=nullptr)
std::string make_temp_dir(std::string template_str)
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
#define PRIVATE_NAMESPACE_END
void log_cmd_error(const char *format,...)
bool check_file_exists(std::string filename, bool is_exec)
#define ABC_FAST_COMMAND_LUT
std::string substr(size_t pos=0, size_t len=std::string::npos) const
#define USING_YOSYS_NAMESPACE
std::map< RTLIL::SigBit, int > signal_map
std::string fold_abc_cmd(std::string str)
std::map< RTLIL::IdString, RTLIL::Module * > modules_
void next_line(const std::string &line)
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
void remove(const std::set< RTLIL::Wire * > &wires)
void log(const char *format,...)
#define ABC_FAST_COMMAND_CTR
std::string remap_name(RTLIL::IdString abc_name)
void append(const RTLIL::SigSpec &signal)
#define ABC_FAST_COMMAND_LIB
AstModule * current_module
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
RTLIL::Wire * as_wire() const
std::pair< SigSpec, SigSpec > SigSig
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
YOSYS_NAMESPACE_BEGIN int autoidx
const std::vector< RTLIL::SigChunk > & chunks() const