diff options
Diffstat (limited to 'passes/abc/abc.cc')
-rw-r--r-- | passes/abc/abc.cc | 655 |
1 files changed, 460 insertions, 195 deletions
diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 5aa13572e..f1d56b23a 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -29,65 +29,88 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558–562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; retime; balance; dch; map; topo" -#define ABC_COMMAND_CTR "strash; retime; balance; dch; map; topo; buffer; upsize; dnsize; stime" -#define ABC_COMMAND_LUT "strash; retime; balance; dch; if" -#define ABC_COMMAND_DFL "strash; retime; balance; dch; map" +#define ABC_COMMAND_LIB "strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; map -v {D}" +#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" +#define ABC_COMMAND_LUT "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; if -v" +#define ABC_COMMAND_DFL "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; map -v" + +#define ABC_FAST_COMMAND_LIB "retime -v {D}; map -v {D}" +#define ABC_FAST_COMMAND_CTR "retime -v {D}; map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "retime -v; if -v" +#define ABC_FAST_COMMAND_DFL "retime -v; map -v" #include "kernel/register.h" #include "kernel/sigtools.h" #include "kernel/log.h" #include <unistd.h> #include <stdlib.h> -#include <assert.h> #include <stdio.h> #include <string.h> #include <dirent.h> +#include <cerrno> #include <sstream> +#include <climits> #include "blifparse.h" +enum class gate_type_t { + G_NONE, + G_FF, + G_NOT, + G_AND, + G_NAND, + G_OR, + G_NOR, + G_XOR, + G_XNOR, + G_MUX, + G_AOI3, + G_OAI3, + G_AOI4, + G_OAI4 +}; + +#define G(_name) gate_type_t::G_ ## _name + struct gate_t { int id; - char type; - int in1, in2, in3; + gate_type_t type; + int in1, in2, in3, in4; bool is_port; - RTLIL::SigSpec sig; + RTLIL::SigBit bit; }; static int map_autoidx; static SigMap assign_map; static RTLIL::Module *module; static std::vector<gate_t> signal_list; -static std::map<RTLIL::SigSpec, int> signal_map; +static std::map<RTLIL::SigBit, int> signal_map; static bool clk_polarity; static RTLIL::SigSpec clk_sig; -static int map_signal(RTLIL::SigSpec sig, char gate_type = -1, int in1 = -1, int in2 = -1, int in3 = -1) +static 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) { - assert(sig.width == 1); - assert(sig.chunks.size() == 1); + assign_map.apply(bit); - assign_map.apply(sig); - - if (signal_map.count(sig) == 0) { + if (signal_map.count(bit) == 0) { gate_t gate; gate.id = signal_list.size(); - gate.type = -1; + gate.type = G(NONE); gate.in1 = -1; gate.in2 = -1; gate.in3 = -1; + gate.in4 = -1; gate.is_port = false; - gate.sig = sig; + gate.bit = bit; signal_list.push_back(gate); - signal_map[sig] = gate.id; + signal_map[bit] = gate.id; } - gate_t &gate = signal_list[signal_map[sig]]; + gate_t &gate = signal_list[signal_map[bit]]; - if (gate_type >= 0) + if (gate_type != G(NONE)) gate.type = gate_type; if (in1 >= 0) gate.in1 = in1; @@ -95,62 +118,64 @@ static int map_signal(RTLIL::SigSpec sig, char gate_type = -1, int in1 = -1, int gate.in2 = in2; if (in3 >= 0) gate.in3 = in3; + if (in4 >= 0) + gate.in4 = in4; return gate.id; } static void mark_port(RTLIL::SigSpec sig) { - assign_map.apply(sig); - sig.expand(); - for (auto &c : sig.chunks) { - if (c.wire != NULL && signal_map.count(c) > 0) - signal_list[signal_map[c]].is_port = true; - } + for (auto &bit : assign_map(sig)) + if (bit.wire != NULL && signal_map.count(bit) > 0) + signal_list[signal_map[bit]].is_port = true; } -static void extract_cell(RTLIL::Cell *cell) +static void extract_cell(RTLIL::Cell *cell, bool keepff) { if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") { if (clk_polarity != (cell->type == "$_DFF_P_")) return; - if (clk_sig != assign_map(cell->connections["\\C"])) + if (clk_sig != assign_map(cell->getPort("\\C"))) return; - RTLIL::SigSpec sig_d = cell->connections["\\D"]; - RTLIL::SigSpec sig_q = cell->connections["\\Q"]; + RTLIL::SigSpec sig_d = cell->getPort("\\D"); + RTLIL::SigSpec sig_q = cell->getPort("\\Q"); + + if (keepff) + for (auto &c : sig_q.chunks()) + if (c.wire != NULL) + c.wire->attributes["\\keep"] = 1; assign_map.apply(sig_d); assign_map.apply(sig_q); - map_signal(sig_q, 'f', map_signal(sig_d)); + map_signal(sig_q, G(FF), map_signal(sig_d)); - module->cells.erase(cell->name); - delete cell; + module->remove(cell); return; } - if (cell->type == "$_INV_") + if (cell->type == "$_NOT_") { - RTLIL::SigSpec sig_a = cell->connections["\\A"]; - RTLIL::SigSpec sig_y = cell->connections["\\Y"]; + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); assign_map.apply(sig_a); assign_map.apply(sig_y); - map_signal(sig_y, 'n', map_signal(sig_a)); + map_signal(sig_y, G(NOT), map_signal(sig_a)); - module->cells.erase(cell->name); - delete cell; + module->remove(cell); return; } - if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { - RTLIL::SigSpec sig_a = cell->connections["\\A"]; - RTLIL::SigSpec sig_b = cell->connections["\\B"]; - RTLIL::SigSpec sig_y = cell->connections["\\Y"]; + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); assign_map.apply(sig_a); assign_map.apply(sig_b); @@ -160,25 +185,30 @@ static void extract_cell(RTLIL::Cell *cell) int mapped_b = map_signal(sig_b); if (cell->type == "$_AND_") - map_signal(sig_y, 'a', mapped_a, mapped_b); + map_signal(sig_y, G(AND), mapped_a, mapped_b); + else if (cell->type == "$_NAND_") + map_signal(sig_y, G(NAND), mapped_a, mapped_b); else if (cell->type == "$_OR_") - map_signal(sig_y, 'o', mapped_a, mapped_b); + map_signal(sig_y, G(OR), mapped_a, mapped_b); + else if (cell->type == "$_NOR_") + map_signal(sig_y, G(NOR), mapped_a, mapped_b); else if (cell->type == "$_XOR_") - map_signal(sig_y, 'x', mapped_a, mapped_b); + map_signal(sig_y, G(XOR), mapped_a, mapped_b); + else if (cell->type == "$_XNOR_") + map_signal(sig_y, G(XNOR), mapped_a, mapped_b); else log_abort(); - module->cells.erase(cell->name); - delete cell; + module->remove(cell); return; } if (cell->type == "$_MUX_") { - RTLIL::SigSpec sig_a = cell->connections["\\A"]; - RTLIL::SigSpec sig_b = cell->connections["\\B"]; - RTLIL::SigSpec sig_s = cell->connections["\\S"]; - RTLIL::SigSpec sig_y = cell->connections["\\Y"]; + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_s = cell->getPort("\\S"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); assign_map.apply(sig_a); assign_map.apply(sig_b); @@ -189,15 +219,61 @@ static void extract_cell(RTLIL::Cell *cell) int mapped_b = map_signal(sig_b); int mapped_s = map_signal(sig_s); - map_signal(sig_y, 'm', mapped_a, mapped_b, mapped_s); + map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s); + + module->remove(cell); + return; + } + + if (cell->type.in("$_AOI3_", "$_OAI3_")) + { + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_c = cell->getPort("\\C"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + + assign_map.apply(sig_a); + assign_map.apply(sig_b); + assign_map.apply(sig_c); + assign_map.apply(sig_y); + + int mapped_a = map_signal(sig_a); + int mapped_b = map_signal(sig_b); + int mapped_c = map_signal(sig_c); + + map_signal(sig_y, cell->type == "$_AOI3_" ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c); + + module->remove(cell); + return; + } + + if (cell->type.in("$_AOI4_", "$_OAI4_")) + { + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_c = cell->getPort("\\C"); + RTLIL::SigSpec sig_d = cell->getPort("\\D"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + + assign_map.apply(sig_a); + assign_map.apply(sig_b); + assign_map.apply(sig_c); + assign_map.apply(sig_d); + assign_map.apply(sig_y); + + int mapped_a = map_signal(sig_a); + int mapped_b = map_signal(sig_b); + int mapped_c = map_signal(sig_c); + int mapped_d = map_signal(sig_d); + + map_signal(sig_y, cell->type == "$_AOI4_" ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d); - module->cells.erase(cell->name); - delete cell; + module->remove(cell); return; } } -static std::string remap_name(std::string abc_name) +static std::string remap_name(RTLIL::IdString abc_name) { std::stringstream sstr; sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1); @@ -211,8 +287,9 @@ static void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edge log("Dumping loop state graph to slide %d.\n", ++nr); - fprintf(f, "digraph slide%d {\n", nr); - fprintf(f, " rankdir=\"LR\";\n"); + fprintf(f, "digraph \"slide%d\" {\n", nr); + fprintf(f, " label=\"slide%d\";\n", nr); + fprintf(f, " rankdir=\"TD\";\n"); std::set<int> nodes; for (auto &e : edges) { @@ -222,7 +299,7 @@ static void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edge } for (auto n : nodes) - fprintf(f, " n%d [label=\"%s\\nid=%d, count=%d\"%s];\n", n, log_signal(signal_list[n].sig), + fprintf(f, " n%d [label=\"%s\\nid=%d, count=%d\"%s];\n", n, log_signal(signal_list[n].bit), n, in_counts[n], workpool.count(n) ? ", shape=box" : ""); for (auto &e : edges) @@ -248,7 +325,7 @@ static void handle_loops() // dot_f = fopen("test.dot", "w"); for (auto &g : signal_list) { - if (g.type == -1 || g.type == 'f') { + if (g.type == G(NONE) || g.type == G(FF)) { workpool.insert(g.id); } else { if (g.in1 >= 0) { @@ -263,6 +340,10 @@ static void handle_loops() edges[g.in3].insert(g.id); in_edges_count[g.id]++; } + if (g.in4 >= 0 && g.in4 != g.in3 && g.in4 != g.in2 && g.in4 != g.in1) { + edges[g.in4].insert(g.id); + in_edges_count[g.id]++; + } } } @@ -273,10 +354,10 @@ static void handle_loops() int id = *workpool.begin(); workpool.erase(id); - // log("Removing non-loop node %d from graph: %s\n", id, log_signal(signal_list[id].sig)); + // log("Removing non-loop node %d from graph: %s\n", id, log_signal(signal_list[id].bit)); for (int id2 : edges[id]) { - assert(in_edges_count[id2] > 0); + log_assert(in_edges_count[id2] > 0); if (--in_edges_count[id2] == 0) workpool.insert(id2); } @@ -293,12 +374,12 @@ static void handle_loops() for (auto &edge_it : edges) { int id2 = edge_it.first; - RTLIL::Wire *w1 = signal_list[id1].sig.chunks[0].wire; - RTLIL::Wire *w2 = signal_list[id2].sig.chunks[0].wire; - if (w1 != NULL) - continue; - else if (w2 == NULL) + RTLIL::Wire *w1 = signal_list[id1].bit.wire; + RTLIL::Wire *w2 = signal_list[id2].bit.wire; + if (w1 == NULL) id1 = id2; + else if (w2 == NULL) + continue; else if (w1->name[0] == '$' && w2->name[0] == '\\') id1 = id2; else if (w1->name[0] == '\\' && w2->name[0] == '$') @@ -307,7 +388,7 @@ static void handle_loops() id1 = id2; else if (edges[id1].size() > edges[id2].size()) continue; - else if (w1->name > w2->name) + else if (w2->name.str() < w1->name.str()) id1 = id2; } @@ -316,27 +397,27 @@ static void handle_loops() continue; } - RTLIL::Wire *wire = new RTLIL::Wire; + log_assert(signal_list[id1].bit.wire != NULL); + std::stringstream sstr; - sstr << "$abcloop$" << (RTLIL::autoidx++); - wire->name = sstr.str(); - module->wires[wire->name] = wire; + sstr << "$abcloop$" << (autoidx++); + RTLIL::Wire *wire = module->addWire(sstr.str()); bool first_line = true; for (int id2 : edges[id1]) { if (first_line) log("Breaking loop using new signal %s: %s -> %s\n", log_signal(RTLIL::SigSpec(wire)), - log_signal(signal_list[id1].sig), log_signal(signal_list[id2].sig)); + log_signal(signal_list[id1].bit), log_signal(signal_list[id2].bit)); else log(" %*s %s -> %s\n", int(strlen(log_signal(RTLIL::SigSpec(wire)))), "", - log_signal(signal_list[id1].sig), log_signal(signal_list[id2].sig)); + log_signal(signal_list[id1].bit), log_signal(signal_list[id2].bit)); first_line = false; } int id3 = map_signal(RTLIL::SigSpec(wire)); signal_list[id1].is_port = true; signal_list[id3].is_port = true; - assert(id3 == int(in_edges_count.size())); + log_assert(id3 == int(in_edges_count.size())); in_edges_count.push_back(0); workpool.insert(id3); @@ -347,10 +428,12 @@ static void handle_loops() signal_list[id2].in2 = id3; if (signal_list[id2].in3 == id1) signal_list[id2].in3 = id3; + if (signal_list[id2].in4 == id1) + signal_list[id2].in4 = id3; } edges[id1].swap(edges[id3]); - module->connections.push_back(RTLIL::SigSig(signal_list[id3].sig, signal_list[id1].sig)); + module->connect(RTLIL::SigSig(signal_list[id3].bit, signal_list[id1].bit)); dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); } } @@ -359,11 +442,55 @@ static void handle_loops() fclose(dot_f); } +static std::string add_echos_to_abc_cmd(std::string str) +{ + std::string new_str, token; + for (size_t i = 0; i < str.size(); i++) { + token += str[i]; + if (str[i] == ';') { + while (i+1 < str.size() && str[i+1] == ' ') + i++; + if (!new_str.empty()) + new_str += "echo; "; + new_str += "echo + " + token + " " + token + " "; + token.clear(); + } + } + + if (!token.empty()) { + if (!new_str.empty()) + new_str += "echo; echo + " + token + "; "; + new_str += token; + } + + return new_str; +} + +static std::string fold_abc_cmd(std::string str) +{ + std::string token, new_str = " "; + int char_counter = 10; + + for (size_t i = 0; i <= str.size(); i++) { + if (i < str.size()) + token += str[i]; + if (i == str.size() || str[i] == ';') { + if (char_counter + token.size() > 75) + new_str += "\n ", char_counter = 14; + new_str += token, char_counter += token.size(); + token.clear(); + } + } + + return new_str; +} + static 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) + 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) { module = current_module; - map_autoidx = RTLIL::autoidx++; + map_autoidx = autoidx++; signal_map.clear(); signal_list.clear(); @@ -393,33 +520,48 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std } else abc_command = stringf("source %s", script_file.c_str()); } else if (lut_mode) - abc_command = ABC_COMMAND_LUT; + abc_command = fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; else if (!liberty_file.empty()) - abc_command = constr_file.empty() ? ABC_COMMAND_LIB : ABC_COMMAND_CTR; + abc_command = constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); else - abc_command = ABC_COMMAND_DFL; + abc_command = fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + + for (size_t pos = abc_command.find("{D}"); pos != std::string::npos; pos = abc_command.find("{D}", pos)) + abc_command = abc_command.substr(0, pos) + delay_target + abc_command.substr(pos+3); + + abc_command = add_echos_to_abc_cmd(abc_command); + + if (abc_command.size() > 128) { + for (size_t i = 0; i+1 < abc_command.size(); i++) + if (abc_command[i] == ';' && abc_command[i+1] == ' ') + abc_command[i+1] = '\n'; + FILE *f = fopen(stringf("%s/abc.script", tempdir_name).c_str(), "wt"); + fprintf(f, "%s\n", abc_command.c_str()); + fclose(f); + abc_command = stringf("source %s/abc.script", tempdir_name); + } if (clk_str.empty()) { if (clk_str[0] == '!') { clk_polarity = false; clk_str = clk_str.substr(1); } - if (module->wires.count(RTLIL::escape_id(clk_str)) != 0) - clk_sig = assign_map(RTLIL::SigSpec(module->wires.at(RTLIL::escape_id(clk_str)), 1)); + if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0) + clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); } - if (dff_mode && clk_sig.width == 0) + if (dff_mode && clk_sig.size() == 0) { int best_dff_counter = 0; std::map<std::pair<bool, RTLIL::SigSpec>, int> dff_counters; - for (auto &it : module->cells) + for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; if (cell->type != "$_DFF_N_" && cell->type != "$_DFF_P_") continue; - std::pair<bool, RTLIL::SigSpec> key(cell->type == "$_DFF_P_", assign_map(cell->connections.at("\\C"))); + std::pair<bool, RTLIL::SigSpec> key(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C"))); if (++dff_counters[key] > best_dff_counter) { best_dff_counter = dff_counters[key]; clk_polarity = key.first; @@ -429,30 +571,30 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std } if (dff_mode || !clk_str.empty()) { - if (clk_sig.width == 0) + if (clk_sig.size() == 0) log("No (matching) clock domain found. Not extracting any FF cells.\n"); else log("Found (matching) %s clock domain: %s\n", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); } - if (clk_sig.width != 0) + if (clk_sig.size() != 0) mark_port(clk_sig); std::vector<RTLIL::Cell*> cells; - cells.reserve(module->cells.size()); - for (auto &it : module->cells) + cells.reserve(module->cells_.size()); + for (auto &it : module->cells_) if (design->selected(current_module, it.second)) cells.push_back(it.second); for (auto c : cells) - extract_cell(c); + extract_cell(c, keepff); - for (auto &wire_it : module->wires) { + for (auto &wire_it : module->wires_) { if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute("\\keep")) mark_port(RTLIL::SigSpec(wire_it.second)); } - for (auto &cell_it : module->cells) - for (auto &port_it : cell_it.second->connections) + for (auto &cell_it : module->cells_) + for (auto &port_it : cell_it.second->connections()) mark_port(port_it.second); handle_loops(); @@ -468,17 +610,19 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std int count_input = 0; fprintf(f, ".inputs"); for (auto &si : signal_list) { - if (!si.is_port || si.type >= 0) + if (!si.is_port || si.type != G(NONE)) continue; fprintf(f, " n%d", si.id); count_input++; } + if (count_input == 0) + fprintf(f, " dummy_input\n"); fprintf(f, "\n"); int count_output = 0; fprintf(f, ".outputs"); for (auto &si : signal_list) { - if (!si.is_port || si.type < 0) + if (!si.is_port || si.type == G(NONE)) continue; fprintf(f, " n%d", si.id); count_output++; @@ -486,42 +630,70 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std fprintf(f, "\n"); for (auto &si : signal_list) - fprintf(f, "# n%-5d %s\n", si.id, log_signal(si.sig)); + fprintf(f, "# n%-5d %s\n", si.id, log_signal(si.bit)); for (auto &si : signal_list) { - assert(si.sig.width == 1 && si.sig.chunks.size() == 1); - if (si.sig.chunks[0].wire == NULL) { + if (si.bit.wire == NULL) { fprintf(f, ".names n%d\n", si.id); - if (si.sig.chunks[0].data.bits[0] == RTLIL::State::S1) + if (si.bit == RTLIL::State::S1) fprintf(f, "1\n"); } } int count_gates = 0; for (auto &si : signal_list) { - if (si.type == 'n') { + if (si.type == G(NOT)) { fprintf(f, ".names n%d n%d\n", si.in1, si.id); fprintf(f, "0 1\n"); - } else if (si.type == 'a') { + } else if (si.type == G(AND)) { fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); fprintf(f, "11 1\n"); - } else if (si.type == 'o') { + } else if (si.type == G(NAND)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "0- 1\n"); + fprintf(f, "-0 1\n"); + } else if (si.type == G(OR)) { fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); fprintf(f, "-1 1\n"); fprintf(f, "1- 1\n"); - } else if (si.type == 'x') { + } else if (si.type == G(NOR)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "00 1\n"); + } else if (si.type == G(XOR)) { fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); fprintf(f, "01 1\n"); fprintf(f, "10 1\n"); - } else if (si.type == 'm') { + } else if (si.type == G(XNOR)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "00 1\n"); + fprintf(f, "11 1\n"); + } else if (si.type == G(MUX)) { fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id); fprintf(f, "1-0 1\n"); fprintf(f, "-11 1\n"); - } else if (si.type == 'f') { + } else if (si.type == G(AOI3)) { + fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id); + fprintf(f, "-00 1\n"); + fprintf(f, "0-0 1\n"); + } else if (si.type == G(OAI3)) { + fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id); + fprintf(f, "00- 1\n"); + fprintf(f, "--0 1\n"); + } else if (si.type == G(AOI4)) { + fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id); + fprintf(f, "-0-0 1\n"); + fprintf(f, "-00- 1\n"); + fprintf(f, "0--0 1\n"); + fprintf(f, "0-0- 1\n"); + } else if (si.type == G(OAI4)) { + fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id); + fprintf(f, "00-- 1\n"); + fprintf(f, "--00 1\n"); + } else if (si.type == G(FF)) { fprintf(f, ".latch n%d n%d\n", si.in1, si.id); - } else if (si.type >= 0) + } else if (si.type != G(NONE)) log_abort(); - if (si.type >= 0) + if (si.type != G(NONE)) count_gates++; } @@ -543,11 +715,18 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); fprintf(f, "GATE ONE 1 Y=CONST1;\n"); fprintf(f, "GATE BUF 1 Y=A; PIN * NONINV 1 999 1 0 1 0\n"); - fprintf(f, "GATE INV 1 Y=!A; PIN * INV 1 999 1 0 1 0\n"); + fprintf(f, "GATE NOT 1 Y=!A; PIN * INV 1 999 1 0 1 0\n"); fprintf(f, "GATE AND 1 Y=A*B; PIN * NONINV 1 999 1 0 1 0\n"); + fprintf(f, "GATE NAND 1 Y=!(A*B); PIN * INV 1 999 1 0 1 0\n"); fprintf(f, "GATE OR 1 Y=A+B; PIN * NONINV 1 999 1 0 1 0\n"); + fprintf(f, "GATE NOR 1 Y=!(A+B); PIN * INV 1 999 1 0 1 0\n"); fprintf(f, "GATE XOR 1 Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n"); + fprintf(f, "GATE XNOR 1 Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n"); fprintf(f, "GATE MUX 1 Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n"); + fprintf(f, "GATE AOI3 1 Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n"); + fprintf(f, "GATE OAI3 1 Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n"); + fprintf(f, "GATE AOI4 1 Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n"); + fprintf(f, "GATE OAI4 1 Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n"); fclose(f); free(p); @@ -564,10 +743,10 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std std::string buffer; if (!liberty_file.empty()) { - buffer += stringf("%s -s -c 'read_blif %s/input.blif; read_lib %s; ", + buffer += stringf("%s -s -c 'read_blif %s/input.blif; read_lib -w %s; ", exe_file.c_str(), tempdir_name, liberty_file.c_str()); if (!constr_file.empty()) - buffer += stringf("read_constr %s; ", constr_file.c_str()); + buffer += stringf("read_constr -v %s; ", constr_file.c_str()); buffer += abc_command + "; "; } else if (lut_mode) @@ -578,13 +757,53 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std exe_file.c_str(), tempdir_name, tempdir_name, abc_command.c_str()); buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name); + log("%s\n", buffer.c_str()); + errno = ENOMEM; // popen does not set errno if memory allocation fails, therefore set it by hand f = popen(buffer.c_str(), "r"); if (f == NULL) log_error("Opening pipe to `%s' for reading failed: %s\n", buffer.c_str(), strerror(errno)); +#if 0 char logbuf[1024]; while (fgets(logbuf, 1024, f) != NULL) log("ABC: %s", logbuf); +#else + bool got_cr = false; + int escape_seq_state = 0; + std::string linebuf; + char logbuf[1024]; + while (fgets(logbuf, 1024, f) != NULL) + for (char *p = logbuf; *p; p++) { + if (escape_seq_state == 0 && *p == '\033') { + escape_seq_state = 1; + continue; + } + if (escape_seq_state == 1) { + escape_seq_state = *p == '[' ? 2 : 0; + continue; + } + if (escape_seq_state == 2) { + if ((*p < '0' || '9' < *p) && *p != ';') + escape_seq_state = 0; + continue; + } + escape_seq_state = 0; + if (*p == '\r') { + got_cr = true; + continue; + } + if (*p == '\n') { + log("ABC: %s\n", linebuf.c_str()); + got_cr = false, linebuf.clear(); + continue; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += *p; + } + if (!linebuf.empty()) + log("ABC: %s\n", linebuf.c_str()); +#endif errno = 0; int ret = pclose(f); if (ret < 0) @@ -609,79 +828,84 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std free(p); log_header("Re-integrating ABC results.\n"); - RTLIL::Module *mapped_mod = mapped_design->modules["\\netlist"]; + RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); - for (auto &it : mapped_mod->wires) { + for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; - RTLIL::Wire *wire = new RTLIL::Wire; - wire->name = remap_name(w->name); - module->wires[wire->name] = wire; + RTLIL::Wire *wire = module->addWire(remap_name(w->name)); design->select(module, wire); } std::map<std::string, int> cell_stats; if (builtin_lib) { - for (auto &it : mapped_mod->cells) { + for (auto &it : mapped_mod->cells_) { RTLIL::Cell *c = it.second; cell_stats[RTLIL::unescape_id(c->type)]++; if (c->type == "\\ZERO" || c->type == "\\ONE") { RTLIL::SigSig conn; - conn.first = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Y"].chunks[0].wire->name)]); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]); conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1); - module->connections.push_back(conn); + module->connect(conn); continue; } if (c->type == "\\BUF") { RTLIL::SigSig conn; - conn.first = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Y"].chunks[0].wire->name)]); - conn.second = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\A"].chunks[0].wire->name)]); - module->connections.push_back(conn); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]); + conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]); + module->connect(conn); continue; } - if (c->type == "\\INV") { - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = "$_INV_"; - cell->name = remap_name(c->name); - cell->connections["\\A"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\A"].chunks[0].wire->name)]); - cell->connections["\\Y"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Y"].chunks[0].wire->name)]); - module->cells[cell->name] = cell; + if (c->type == "\\NOT") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_"); + cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); + cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); design->select(module, cell); continue; } - if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR") { - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = "$_" + c->type.substr(1) + "_"; - cell->name = remap_name(c->name); - cell->connections["\\A"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\A"].chunks[0].wire->name)]); - cell->connections["\\B"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\B"].chunks[0].wire->name)]); - cell->connections["\\Y"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Y"].chunks[0].wire->name)]); - module->cells[cell->name] = cell; + if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || c->type == "\\XNOR") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); + cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); + cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); design->select(module, cell); continue; } if (c->type == "\\MUX") { - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = "$_MUX_"; - cell->name = remap_name(c->name); - cell->connections["\\A"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\A"].chunks[0].wire->name)]); - cell->connections["\\B"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\B"].chunks[0].wire->name)]); - cell->connections["\\S"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\S"].chunks[0].wire->name)]); - cell->connections["\\Y"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Y"].chunks[0].wire->name)]); - module->cells[cell->name] = cell; + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); + cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); + cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); + cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); + cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); + design->select(module, cell); + continue; + } + if (c->type == "\\AOI3" || c->type == "\\OAI3") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); + cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); + cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); + cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); + design->select(module, cell); + continue; + } + if (c->type == "\\AOI4" || c->type == "\\OAI4") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); + cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); + cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); + cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); + cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); design->select(module, cell); continue; } if (c->type == "\\DFF") { - log_assert(clk_sig.width == 1); - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = clk_polarity ? "$_DFF_P_" : "$_DFF_N_"; - cell->name = remap_name(c->name); - cell->connections["\\D"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\D"].chunks[0].wire->name)]); - cell->connections["\\Q"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Q"].chunks[0].wire->name)]); - cell->connections["\\C"] = clk_sig; - module->cells[cell->name] = cell; + log_assert(clk_sig.size() == 1); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); + cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); + cell->setPort("\\C", clk_sig); design->select(module, cell); continue; } @@ -690,54 +914,48 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std } else { - for (auto &it : mapped_mod->cells) + for (auto &it : mapped_mod->cells_) { RTLIL::Cell *c = it.second; cell_stats[RTLIL::unescape_id(c->type)]++; if (c->type == "\\_const0_" || c->type == "\\_const1_") { RTLIL::SigSig conn; - conn.first = RTLIL::SigSpec(module->wires[remap_name(c->connections.begin()->second.chunks[0].wire->name)]); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]); conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1); - module->connections.push_back(conn); + module->connect(conn); continue; } if (c->type == "\\_dff_") { - log_assert(clk_sig.width == 1); - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = clk_polarity ? "$_DFF_P_" : "$_DFF_N_"; - cell->name = remap_name(c->name); - cell->connections["\\D"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\D"].chunks[0].wire->name)]); - cell->connections["\\Q"] = RTLIL::SigSpec(module->wires[remap_name(c->connections["\\Q"].chunks[0].wire->name)]); - cell->connections["\\C"] = clk_sig; - module->cells[cell->name] = cell; + log_assert(clk_sig.size() == 1); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); + cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); + cell->setPort("\\C", clk_sig); design->select(module, cell); continue; } - RTLIL::Cell *cell = new RTLIL::Cell; - cell->type = c->type; + RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); cell->parameters = c->parameters; - cell->name = remap_name(c->name); - for (auto &conn : c->connections) { + for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; - for (auto &c : conn.second.chunks) { + for (auto &c : conn.second.chunks()) { if (c.width == 0) continue; - assert(c.width == 1); - newsig.append(module->wires[remap_name(c.wire->name)]); + log_assert(c.width == 1); + newsig.append(module->wires_[remap_name(c.wire->name)]); } - cell->connections[conn.first] = newsig; + cell->setPort(conn.first, newsig); } - module->cells[cell->name] = cell; design->select(module, cell); } } - for (auto conn : mapped_mod->connections) { + for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) - conn.first = RTLIL::SigSpec(module->wires[remap_name(conn.first.chunks[0].wire->name)]); + conn.first = RTLIL::SigSpec(module->wires_[remap_name(conn.first.as_wire()->name)]); if (!conn.second.is_fully_const()) - conn.second = RTLIL::SigSpec(module->wires[remap_name(conn.second.chunks[0].wire->name)]); - module->connections.push_back(conn); + conn.second = RTLIL::SigSpec(module->wires_[remap_name(conn.second.as_wire()->name)]); + module->connect(conn); } for (auto &it : cell_stats) @@ -748,16 +966,16 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std char buffer[100]; snprintf(buffer, 100, "\\n%d", si.id); RTLIL::SigSig conn; - if (si.type >= 0) { - conn.first = si.sig; - conn.second = RTLIL::SigSpec(module->wires[remap_name(buffer)]); + if (si.type != G(NONE)) { + conn.first = si.bit; + conn.second = RTLIL::SigSpec(module->wires_[remap_name(buffer)]); out_wires++; } else { - conn.first = RTLIL::SigSpec(module->wires[remap_name(buffer)]); - conn.second = si.sig; + conn.first = RTLIL::SigSpec(module->wires_[remap_name(buffer)]); + conn.second = si.bit; in_wires++; } - module->connections.push_back(conn); + module->connect(conn); } log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); @@ -776,7 +994,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std struct dirent **namelist; int n = scandir(tempdir_name, &namelist, 0, alphasort); - assert(n >= 0); + log_assert(n >= 0); for (int i = 0; i < n; i++) { if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { if (asprintf(&p, "%s/%s", tempdir_name, namelist[i]->d_name) < 0) log_abort(); @@ -820,16 +1038,32 @@ struct AbcPass : public Pass { log(" if no -script parameter is given, the following scripts are used:\n"); log("\n"); log(" for -liberty without -constr:\n"); - log(" %s\n", ABC_COMMAND_LIB); + log("%s\n", fold_abc_cmd(ABC_COMMAND_LIB).c_str()); + log("\n"); + log(" for -liberty with -constr:\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_CTR).c_str()); + log("\n"); + log(" for -lut:\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str()); + log("\n"); + log(" otherwise:\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_DFL).c_str()); + log("\n"); + log(" -fast\n"); + log(" use different default scripts that are slightly faster (at the cost\n"); + log(" of output quality):\n"); + log("\n"); + log(" for -liberty without -constr:\n"); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LIB).c_str()); log("\n"); log(" for -liberty with -constr:\n"); - log(" %s\n", ABC_COMMAND_CTR); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str()); log("\n"); log(" for -lut:\n"); - log(" %s\n", ABC_COMMAND_LUT); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str()); log("\n"); log(" otherwise:\n"); - log(" %s\n", ABC_COMMAND_DFL); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str()); log("\n"); log(" -liberty <file>\n"); log(" generate netlists for the specified cell library (using the liberty\n"); @@ -838,6 +1072,18 @@ struct AbcPass : public Pass { log(" -constr <file>\n"); log(" pass this file with timing constraints to ABC. use with -liberty.\n"); log("\n"); + log(" a constr file contains two lines:\n"); + log(" set_driving_cell <cell_name>\n"); + log(" set_load <floating_point_number>\n"); + log("\n"); + log(" the set_driving_cell statement defines which cell type is assumed to\n"); + log(" drive the primary inputs and the set_load statement sets the load in\n"); + log(" femtofarads for each primary output.\n"); + log("\n"); + log(" -D <picoseconds>\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("\n"); log(" -lut <width>\n"); log(" generate netlist using luts of (max) the specified width.\n"); log("\n"); @@ -851,6 +1097,10 @@ struct AbcPass : public Pass { log(" with -dff, then it falls back to the automatic dection of clock domain\n"); log(" if the specified clock is not found in a module.)\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 equivialence checking.)\n"); + log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); @@ -869,13 +1119,17 @@ struct AbcPass : public Pass { log_header("Executing ABC pass (technology mapping using ABC).\n"); log_push(); - std::string exe_file = rewrite_yosys_exe("yosys-abc"); - std::string script_file, liberty_file, constr_file, clk_str; - bool dff_mode = false, cleanup = true; + std::string exe_file = proc_self_dirname() + "yosys-abc"; + std::string script_file, liberty_file, constr_file, clk_str, delay_target; + bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; int lut_mode = 0; size_t argidx; - char *pwd = get_current_dir_name(); + char pwd [PATH_MAX]; + if (!getcwd(pwd, sizeof(pwd))) { + log_cmd_error("getcwd failed: %s\n", strerror(errno)); + log_abort(); + } for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if (arg == "-exe" && argidx+1 < args.size()) { @@ -900,10 +1154,18 @@ struct AbcPass : public Pass { constr_file = std::string(pwd) + "/" + constr_file; continue; } + if (arg == "-D" && argidx+1 < args.size()) { + delay_target = "-D " + args[++argidx]; + continue; + } if (arg == "-lut" && argidx+1 < args.size()) { lut_mode = atoi(args[++argidx].c_str()); continue; } + if (arg == "-fast") { + fast_mode = true; + continue; + } if (arg == "-dff") { dff_mode = true; continue; @@ -912,13 +1174,16 @@ struct AbcPass : public Pass { clk_str = args[++argidx]; continue; } + if (arg == "-keepff") { + keepff = true; + continue; + } if (arg == "-nocleanup") { cleanup = false; continue; } break; } - free(pwd); extra_args(args, argidx, design); if (lut_mode != 0 && !liberty_file.empty()) @@ -926,12 +1191,12 @@ struct AbcPass : public Pass { if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); - for (auto &mod_it : design->modules) + for (auto &mod_it : design->modules_) if (design->selected(mod_it.second)) { if (mod_it.second->processes.size() > 0) log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str()); else - abc_module(design, mod_it.second, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str); + 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); } assign_map.clear(); |