559 std::string tempdir_name =
"/tmp/yosys-abc-XXXXXX";
561 tempdir_name[0] = tempdir_name[4] =
'_';
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);
620 int best_dff_counter = 0;
621 std::map<std::pair<bool, RTLIL::SigSpec>,
int> dff_counters;
626 if (cell->
type !=
"$_DFF_N_" && cell->
type !=
"$_DFF_P_")
630 if (++dff_counters[key] > best_dff_counter) {
631 best_dff_counter = dff_counters[key];
638 if (dff_mode || !clk_str.empty()) {
640 log(
"No (matching) clock domain found. Not extracting any FF cells.\n");
648 std::vector<RTLIL::Cell*> cells;
651 if (design->
selected(current_module, it.second))
652 cells.push_back(it.second);
657 if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(
"\\keep"))
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_) {
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") {
864 if (c->
type ==
"\\AND" || c->
type ==
"\\OR" || c->
type ==
"\\XOR" || c->
type ==
"\\NAND" || c->
type ==
"\\NOR" || c->
type ==
"\\XNOR") {
872 if (c->
type ==
"\\MUX") {
881 if (c->
type ==
"\\AOI3" || c->
type ==
"\\OAI3") {
890 if (c->
type ==
"\\AOI4" || c->
type ==
"\\OAI4") {
900 if (c->
type ==
"\\DFF") {
914 for (
auto &it : mapped_mod->
cells_)
918 if (c->
type ==
"\\_const0_" || c->
type ==
"\\_const1_") {
925 if (c->
type ==
"\\_dff_") {
938 for (
auto &c : conn.second.chunks()) {
944 cell->
setPort(conn.first, newsig);
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());
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
void select(T1 *module, T2 *member)
int run_command(const std::string &command, std::function< void(const std::string &)> process_line)
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)
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
int GetSize(RTLIL::Wire *wire)
#define log_assert(_assert_expr_)
RTLIL::Wire * addWire(RTLIL::IdString name, int width=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)
#define ABC_FAST_COMMAND_LUT
std::string substr(size_t pos=0, size_t len=std::string::npos) const
std::map< RTLIL::SigBit, int > signal_map
std::map< RTLIL::IdString, RTLIL::Module * > modules_
void next_line(const std::string &line)
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
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
RTLIL::Wire * as_wire() const
std::pair< SigSpec, SigSpec > SigSig
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
YOSYS_NAMESPACE_BEGIN int autoidx