From e25a22015f1b422a7a5cb176fd1c509af056e796 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:23:54 -0800 Subject: [PATCH 001/514] Copy abc.cc to abc9.cc --- passes/techmap/abc9.cc | 1868 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1868 insertions(+) create mode 100644 passes/techmap/abc9.cc diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc new file mode 100644 index 000000000..d2d15a4a9 --- /dev/null +++ b/passes/techmap/abc9.cc @@ -0,0 +1,1868 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// [[CITE]] ABC +// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification +// http://www.eecs.berkeley.edu/~alanmi/abc/ + +// [[CITE]] Berkeley Logic Interchange Format (BLIF) +// University of California. Berkeley. July 28, 1992 +// http://www.ece.cmu.edu/~ee760/760docs/blif.pdf + +// [[CITE]] Kahn's Topological sorting algorithm +// 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; 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_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" + +#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" +#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "strash; dretime; if" +#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" +#define ABC_FAST_COMMAND_DFL "strash; dretime; map" + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/cost.h" +#include "kernel/log.h" +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +# include +# include +#endif + +#include "frontends/blif/blifparse.h" + +#ifdef YOSYS_LINK_ABC +extern "C" int Abc_RealMain(int argc, char *argv[]); +#endif + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +enum class gate_type_t { + G_NONE, + G_FF, + G_BUF, + G_NOT, + G_AND, + G_NAND, + G_OR, + G_NOR, + G_XOR, + G_XNOR, + G_ANDNOT, + G_ORNOT, + G_MUX, + G_AOI3, + G_OAI3, + G_AOI4, + G_OAI4 +}; + +#define G(_name) gate_type_t::G_ ## _name + +struct gate_t +{ + int id; + gate_type_t type; + int in1, in2, in3, in4; + bool is_port; + RTLIL::SigBit bit; + RTLIL::State init; +}; + +bool map_mux4; +bool map_mux8; +bool map_mux16; + +bool markgroups; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; +std::vector signal_list; +std::map signal_map; +std::map signal_init; +pool enabled_gates; +bool recover_init; + +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; +dict pi_map, po_map; + +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) +{ + assign_map.apply(bit); + + if (signal_map.count(bit) == 0) { + gate_t gate; + gate.id = signal_list.size(); + gate.type = G(NONE); + gate.in1 = -1; + gate.in2 = -1; + gate.in3 = -1; + gate.in4 = -1; + gate.is_port = false; + gate.bit = bit; + if (signal_init.count(bit)) + gate.init = signal_init.at(bit); + else + gate.init = State::Sx; + signal_list.push_back(gate); + signal_map[bit] = gate.id; + } + + gate_t &gate = signal_list[signal_map[bit]]; + + if (gate_type != G(NONE)) + gate.type = gate_type; + if (in1 >= 0) + gate.in1 = in1; + if (in2 >= 0) + gate.in2 = in2; + if (in3 >= 0) + gate.in3 = in3; + if (in4 >= 0) + gate.in4 = in4; + + return gate.id; +} + +void mark_port(RTLIL::SigSpec sig) +{ + for (auto &bit : assign_map(sig)) + if (bit.wire != NULL && signal_map.count(bit) > 0) + signal_list[signal_map[bit]].is_port = true; +} + +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->getPort("\\C"))) + return; + if (GetSize(en_sig) != 0) + return; + goto matching_dff; + } + + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + if (clk_polarity != (cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")) + return; + if (en_polarity != (cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_")) + return; + if (clk_sig != assign_map(cell->getPort("\\C"))) + return; + if (en_sig != assign_map(cell->getPort("\\E"))) + return; + goto matching_dff; + } + + if (0) { + matching_dff: + 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, G(FF), map_signal(sig_d)); + + module->remove(cell); + return; + } + + if (cell->type.in("$_BUF_", "$_NOT_")) + { + 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, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a)); + + module->remove(cell); + return; + } + + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) + { + 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); + assign_map.apply(sig_y); + + int mapped_a = map_signal(sig_a); + int mapped_b = map_signal(sig_b); + + if (cell->type == "$_AND_") + 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, 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, G(XOR), mapped_a, mapped_b); + else if (cell->type == "$_XNOR_") + map_signal(sig_y, G(XNOR), mapped_a, mapped_b); + else if (cell->type == "$_ANDNOT_") + map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b); + else if (cell->type == "$_ORNOT_") + map_signal(sig_y, G(ORNOT), mapped_a, mapped_b); + else + log_abort(); + + module->remove(cell); + return; + } + + if (cell->type == "$_MUX_") + { + 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); + assign_map.apply(sig_s); + assign_map.apply(sig_y); + + int mapped_a = map_signal(sig_a); + int mapped_b = map_signal(sig_b); + int mapped_s = map_signal(sig_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->remove(cell); + return; + } +} + +std::string remap_name(RTLIL::IdString abc_name) +{ + std::stringstream sstr; + sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1); + return sstr.str(); +} + +void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) +{ + if (f == NULL) + return; + + log("Dumping loop state graph to slide %d.\n", ++nr); + + fprintf(f, "digraph \"slide%d\" {\n", nr); + fprintf(f, " label=\"slide%d\";\n", nr); + fprintf(f, " rankdir=\"TD\";\n"); + + std::set nodes; + for (auto &e : edges) { + nodes.insert(e.first); + for (auto n : e.second) + nodes.insert(n); + } + + for (auto n : nodes) + 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) + for (auto n : e.second) + fprintf(f, " n%d -> n%d;\n", e.first, n); + + fprintf(f, "}\n"); +} + +void handle_loops() +{ + // http://en.wikipedia.org/wiki/Topological_sorting + // (Kahn, Arthur B. (1962), "Topological sorting of large networks") + + std::map> edges; + std::vector in_edges_count(signal_list.size()); + std::set workpool; + + FILE *dot_f = NULL; + int dot_nr = 0; + + // uncomment for troubleshooting the loop detection code + // dot_f = fopen("test.dot", "w"); + + for (auto &g : signal_list) { + if (g.type == G(NONE) || g.type == G(FF)) { + workpool.insert(g.id); + } else { + if (g.in1 >= 0) { + edges[g.in1].insert(g.id); + in_edges_count[g.id]++; + } + if (g.in2 >= 0 && g.in2 != g.in1) { + edges[g.in2].insert(g.id); + in_edges_count[g.id]++; + } + if (g.in3 >= 0 && g.in3 != g.in2 && g.in3 != g.in1) { + 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]++; + } + } + } + + dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); + + while (workpool.size() > 0) + { + int id = *workpool.begin(); + workpool.erase(id); + + // log("Removing non-loop node %d from graph: %s\n", id, log_signal(signal_list[id].bit)); + + for (int id2 : edges[id]) { + log_assert(in_edges_count[id2] > 0); + if (--in_edges_count[id2] == 0) + workpool.insert(id2); + } + edges.erase(id); + + dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); + + while (workpool.size() == 0) + { + if (edges.size() == 0) + break; + + int id1 = edges.begin()->first; + + for (auto &edge_it : edges) { + int id2 = edge_it.first; + 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] == '$') + continue; + else if (edges[id1].size() < edges[id2].size()) + id1 = id2; + else if (edges[id1].size() > edges[id2].size()) + continue; + else if (w2->name.str() < w1->name.str()) + id1 = id2; + } + + if (edges[id1].size() == 0) { + edges.erase(id1); + continue; + } + + log_assert(signal_list[id1].bit.wire != NULL); + + std::stringstream sstr; + 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].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].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; + log_assert(id3 == int(in_edges_count.size())); + in_edges_count.push_back(0); + workpool.insert(id3); + + for (int id2 : edges[id1]) { + if (signal_list[id2].in1 == id1) + signal_list[id2].in1 = id3; + if (signal_list[id2].in2 == id1) + 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->connect(RTLIL::SigSig(signal_list[id3].bit, signal_list[id1].bit)); + dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); + } + } + + if (dot_f != NULL) + fclose(dot_f); +} + +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++; + new_str += "echo + " + token + " " + token + " "; + token.clear(); + } + } + + if (!token.empty()) { + if (!new_str.empty()) + new_str += "echo + " + token + "; "; + new_str += token; + } + + return new_str; +} + +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; +} + +std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) +{ + if (show_tempdir) + return text; + + while (1) { + size_t pos = text.find(tempdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); + } + + std::string selfdir_name = proc_self_dirname(); + if (selfdir_name != "/") { + while (1) { + size_t pos = text.find(selfdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); + } + } + + return text; +} + +struct abc_output_filter +{ + bool got_cr; + int escape_seq_state; + std::string linebuf; + std::string tempdir_name; + bool show_tempdir; + + abc_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + int pi, po; + if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { + log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", + pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", + po, po_map.count(po) ? po_map.at(po).c_str() : "???"); + return; + } + + for (char ch : line) + next_char(ch); + } +}; + +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, vector 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 &cells, bool show_tempdir, bool sop_mode) +{ + module = current_module; + map_autoidx = autoidx++; + + signal_map.clear(); + signal_list.clear(); + pi_map.clear(); + po_map.clear(); + recover_init = false; + + if (clk_str != "$") + { + clk_polarity = true; + clk_sig = RTLIL::SigSpec(); + + en_polarity = true; + en_sig = RTLIL::SigSpec(); + } + + if (!clk_str.empty() && clk_str != "$") + { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } + 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)), 0)); + } + + if (dff_mode && clk_sig.empty()) + log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); + + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; + if (!cleanup) + tempdir_name[0] = tempdir_name[4] = '_'; + tempdir_name = make_temp_dir(tempdir_name); + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n", + module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); + + std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str()); + + if (!liberty_file.empty()) { + abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); + if (!constr_file.empty()) + abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); + } else + if (!lut_costs.empty()) + abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + else + abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); + + if (!script_file.empty()) { + if (script_file[0] == '+') { + for (size_t i = 1; i < script_file.size(); i++) + if (script_file[i] == '\'') + abc_script += "'\\''"; + else if (script_file[i] == ',') + abc_script += " "; + else + abc_script += script_file[i]; + } else + abc_script += stringf("source %s", script_file.c_str()); + } else if (!lut_costs.empty()) { + bool all_luts_cost_same = true; + for (int this_cost : lut_costs) + if (this_cost != lut_costs.front()) + all_luts_cost_same = false; + abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + if (all_luts_cost_same && !fast_mode) + abc_script += "; lutpack {S}"; + } else if (!liberty_file.empty()) + abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); + else if (sop_mode) + abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; + else + abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + + if (script_file.empty() && !delay_target.empty()) + for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) + abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + + for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) + abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); + + for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) + abc_script = abc_script.substr(0, pos) + sop_inputs + abc_script.substr(pos+3); + + for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) + abc_script = abc_script.substr(0, pos) + sop_products + abc_script.substr(pos+3); + + 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); + + abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str()); + abc_script = add_echos_to_abc_cmd(abc_script); + + for (size_t i = 0; i+1 < abc_script.size(); i++) + if (abc_script[i] == ';' && abc_script[i+1] == ' ') + abc_script[i+1] = '\n'; + + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); + fprintf(f, "%s\n", abc_script.c_str()); + fclose(f); + + if (dff_mode || !clk_str.empty()) + { + if (clk_sig.size() == 0) + log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); + else { + log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } + } + + for (auto c : cells) + extract_cell(c, keepff); + + 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()) + mark_port(port_it.second); + + if (clk_sig.size() != 0) + mark_port(clk_sig); + + if (en_sig.size() != 0) + mark_port(en_sig); + + handle_loops(); + + std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + + fprintf(f, ".model netlist\n"); + + int count_input = 0; + fprintf(f, ".inputs"); + for (auto &si : signal_list) { + if (!si.is_port || si.type != G(NONE)) + continue; + fprintf(f, " n%d", si.id); + pi_map[count_input++] = log_signal(si.bit); + } + 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 == G(NONE)) + continue; + fprintf(f, " n%d", si.id); + po_map[count_output++] = log_signal(si.bit); + } + fprintf(f, "\n"); + + for (auto &si : signal_list) + fprintf(f, "# n%-5d %s\n", si.id, log_signal(si.bit)); + + for (auto &si : signal_list) { + if (si.bit.wire == NULL) { + fprintf(f, ".names n%d\n", si.id); + if (si.bit == RTLIL::State::S1) + fprintf(f, "1\n"); + } + } + + int count_gates = 0; + for (auto &si : signal_list) { + if (si.type == G(BUF)) { + fprintf(f, ".names n%d n%d\n", si.in1, si.id); + fprintf(f, "1 1\n"); + } else 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 == 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 == 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 == 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 == 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(ANDNOT)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "10 1\n"); + } else if (si.type == G(ORNOT)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "1- 1\n"); + fprintf(f, "-0 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 == 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)) { + if (si.init == State::S0 || si.init == State::S1) { + fprintf(f, ".latch n%d n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0); + recover_init = true; + } else + fprintf(f, ".latch n%d n%d 2\n", si.in1, si.id); + } else if (si.type != G(NONE)) + log_abort(); + if (si.type != G(NONE)) + count_gates++; + } + + fprintf(f, ".end\n"); + fclose(f); + + 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); + log_push(); + + if (count_output > 0) + { + log_header(design, "Executing ABC.\n"); + + buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); + fprintf(f, "GATE ONE 1 Y=CONST1;\n"); + fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); + fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); + if (enabled_gates.empty() || enabled_gates.count("AND")) + fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_")); + if (enabled_gates.empty() || enabled_gates.count("NAND")) + fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); + if (enabled_gates.empty() || enabled_gates.count("OR")) + fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_")); + if (enabled_gates.empty() || enabled_gates.count("NOR")) + fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); + if (enabled_gates.empty() || enabled_gates.count("XOR")) + fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); + if (enabled_gates.empty() || enabled_gates.count("XNOR")) + fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); + if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) + fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_")); + if (enabled_gates.empty() || enabled_gates.count("ORNOT")) + fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_")); + if (enabled_gates.empty() || enabled_gates.count("AOI3")) + fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); + if (enabled_gates.empty() || enabled_gates.count("OAI3")) + fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); + if (enabled_gates.empty() || enabled_gates.count("AOI4")) + fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); + if (enabled_gates.empty() || enabled_gates.count("OAI4")) + fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); + if (enabled_gates.empty() || enabled_gates.count("MUX")) + 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_")); + if (map_mux4) + fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_")); + if (map_mux8) + fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_")); + if (map_mux16) + fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); + fclose(f); + + if (!lut_costs.empty()) { + buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); + f = fopen(buffer.c_str(), "wt"); + if (f == NULL) + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + for (int i = 0; i < GetSize(lut_costs); i++) + fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); + fclose(f); + } + + buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); + log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); + +#ifndef YOSYS_LINK_ABC + abc_output_filter filt(tempdir_name, show_tempdir); + int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); +#else + // These needs to be mutable, supposedly due to getopt + char *abc_argv[5]; + string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); + abc_argv[0] = strdup(exe_file.c_str()); + abc_argv[1] = strdup("-s"); + abc_argv[2] = strdup("-f"); + abc_argv[3] = strdup(tmp_script_name.c_str()); + abc_argv[4] = 0; + int ret = Abc_RealMain(4, abc_argv); + free(abc_argv[0]); + free(abc_argv[1]); + free(abc_argv[2]); + free(abc_argv[3]); +#endif + if (ret != 0) + 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.blif"); + std::ifstream ifs; + ifs.open(buffer); + if (ifs.fail()) + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); + + bool builtin_lib = liberty_file.empty(); + RTLIL::Design *mapped_design = new RTLIL::Design; + parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); + + ifs.close(); + + log_header(design, "Re-integrating ABC results.\n"); + 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_) { + RTLIL::Wire *w = it.second; + RTLIL::Wire *wire = module->addWire(remap_name(w->name)); + if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx; + design->select(module, wire); + } + + std::map cell_stats; + for (auto c : mapped_mod->cells()) + { + if (builtin_lib) + { + 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->getPort("\\Y").as_wire()->name)]); + conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1); + module->connect(conn); + continue; + } + if (c->type == "\\BUF") { + RTLIL::SigSig 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 == "\\NOT") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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" || c->type == "\\NAND" || c->type == "\\NOR" || + c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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 = module->addCell(remap_name(c->name), "$_MUX_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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 == "\\MUX4") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); + cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").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 == "\\MUX8") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); + cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); + cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); + cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); + cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); + cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); + cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").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 == "\\MUX16") { + RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); + cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); + cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); + cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); + cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)])); + cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)])); + cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)])); + cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)])); + cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)])); + cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)])); + cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)])); + cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)])); + cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); + cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); + cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); + cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").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) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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.size() == 1); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + log_assert(en_sig.size() == 1); + cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort("\\E", en_sig); + } + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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; + } + } + + 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.as_wire()->name)]); + conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1); + module->connect(conn); + continue; + } + + if (c->type == "\\_dff_") { + log_assert(clk_sig.size() == 1); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + log_assert(en_sig.size() == 1); + cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort("\\E", en_sig); + } + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + 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; + } + + if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { + SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; + SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; + module->connect(my_y, my_a); + continue; + } + + RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + cell->parameters = c->parameters; + for (auto &conn : c->connections()) { + RTLIL::SigSpec newsig; + for (auto &c : conn.second.chunks()) { + if (c.width == 0) + continue; + log_assert(c.width == 1); + newsig.append(module->wires_[remap_name(c.wire->name)]); + } + cell->setPort(conn.first, newsig); + } + design->select(module, cell); + } + + for (auto conn : mapped_mod->connections()) { + if (!conn.first.is_fully_const()) + 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.as_wire()->name)]); + module->connect(conn); + } + + if (recover_init) + for (auto wire : mapped_mod->wires()) { + if (wire->attributes.count("\\init")) { + Wire *w = module->wires_[remap_name(wire->name)]; + log_assert(w->attributes.count("\\init") == 0); + w->attributes["\\init"] = wire->attributes.at("\\init"); + } + } + + for (auto &it : cell_stats) + log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); + int in_wires = 0, out_wires = 0; + for (auto &si : signal_list) + if (si.is_port) { + char buffer[100]; + snprintf(buffer, 100, "\\n%d", si.id); + RTLIL::SigSig conn; + 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.bit; + in_wires++; + } + 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); + log("ABC RESULTS: output signals: %8d\n", out_wires); + + delete mapped_design; + } + else + { + log("Don't call ABC as there is nothing to map.\n"); + } + + if (cleanup) + { + log("Removing temp directory.\n"); + remove_directory(tempdir_name); + } + + log_pop(); +} + +struct AbcPass : public Pass { + AbcPass() : Pass("abc", "use ABC for technology mapping") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" abc [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("\n"); + log(" -exe \n"); +#ifdef ABCEXTERNAL + log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); +#else + log(" use the specified command instead of \"/yosys-abc\" to execute ABC.\n"); +#endif + log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n"); + log("\n"); + log(" -script \n"); + log(" use the specified ABC script file instead of the default script.\n"); + log("\n"); + log(" if starts with a plus sign (+), then the rest of the filename\n"); + log(" string is interpreted as the command string to be passed to ABC. The\n"); + log(" leading plus sign is removed and all commas (,) in the string are\n"); + log(" replaced with blanks before the string is passed to ABC.\n"); + log("\n"); + log(" if no -script parameter is given, the following scripts are used:\n"); + log("\n"); + log(" for -liberty without -constr:\n"); + 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/-luts (only one LUT size):\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack {S}").c_str()); + log("\n"); + log(" for -lut/-luts (different LUT sizes):\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str()); + log("\n"); + log(" for -sop:\n"); + log("%s\n", fold_abc_cmd(ABC_COMMAND_SOP).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", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str()); + log("\n"); + log(" for -lut/-luts:\n"); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str()); + log("\n"); + log(" for -sop:\n"); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_SOP).c_str()); + log("\n"); + log(" otherwise:\n"); + log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str()); + log("\n"); + log(" -liberty \n"); + log(" generate netlists for the specified cell library (using the liberty\n"); + log(" file format).\n"); + log("\n"); + log(" -constr \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 \n"); + log(" set_load \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 \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(" this also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); + log(" default scripts above.\n"); + log("\n"); + log(" -I \n"); + log(" maximum number of SOP inputs.\n"); + log(" (replaces {I} in the default scripts above)\n"); + log("\n"); + log(" -P \n"); + log(" maximum number of SOP products.\n"); + log(" (replaces {P} in the default scripts above)\n"); + log("\n"); + log(" -S \n"); + log(" maximum number of LUT inputs shared.\n"); + log(" (replaces {S} in the default scripts above, default: -S 1)\n"); + log("\n"); + log(" -lut \n"); + log(" generate netlist using luts of (max) the specified width.\n"); + log("\n"); + log(" -lut :\n"); + log(" generate netlist using luts of (max) the specified width . All\n"); + log(" luts with width <= have constant cost. for luts larger than \n"); + log(" the area cost doubles with each additional input bit. the delay cost\n"); + log(" is still constant for all lut widths.\n"); + log("\n"); + log(" -luts ,,,:,..\n"); + log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); + log(" 2, 3, .. inputs.\n"); + log("\n"); + log(" -sop\n"); + log(" map to sum-of-product cells and inverters\n"); + log("\n"); + // log(" -mux4, -mux8, -mux16\n"); + // log(" try to extract 4-input, 8-input, and/or 16-input muxes\n"); + // log(" (ignored when used with -liberty or -lut)\n"); + // log("\n"); + log(" -g type1,type2,...\n"); + log(" Map to the specified list of gate types. Supported gates types are:\n"); + log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n"); + log(" (The NOT gate is always added to this list automatically.)\n"); + log("\n"); + log(" The following aliases can be used to reference common sets of gate types:\n"); + log(" simple: AND OR XOR MUX\n"); + log(" cmos2: NAND NOR\n"); + log(" cmos3: NAND NOR AOI3 OAI3\n"); + log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n"); + log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); + log(" aig: AND NAND OR NOR ANDNOT ORNOT\n"); + log("\n"); + log(" Prefix a gate type with a '-' to remove it from the list. For example\n"); + log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\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 [!][,[!]]\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(" -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"); + 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("When neither -liberty nor -lut is used, the Yosys standard cell library is\n"); + log("loaded into ABC before the ABC script is executed.\n"); + log("\n"); + log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); + log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); + log("ABC on logic snippets extracted from your design. You will not get any useful\n"); + log("output when passing an ABC script that writes a file. Instead write your full\n"); + log("design as BLIF file with write_blif and the load that into ABC externally if\n"); + log("you want to use ABC to convert your design into another format.\n"); + log("\n"); + log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ABC pass (technology mapping using ABC).\n"); + log_push(); + + assign_map.clear(); + signal_list.clear(); + signal_map.clear(); + signal_init.clear(); + pi_map.clear(); + po_map.clear(); + +#ifdef ABCEXTERNAL + std::string exe_file = ABCEXTERNAL; +#else + std::string exe_file = proc_self_dirname() + "yosys-abc"; +#endif + std::string script_file, liberty_file, constr_file, clk_str; + std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; + bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; + bool show_tempdir = false, sop_mode = false; + vector lut_costs; + markgroups = false; + + map_mux4 = false; + map_mux8 = false; + map_mux16 = false; + enabled_gates.clear(); + +#ifdef _WIN32 +#ifndef ABCEXTERNAL + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; +#endif +#endif + + size_t argidx; + 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()) { + exe_file = args[++argidx]; + continue; + } + 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()) { + delay_target = "-D " + args[++argidx]; + continue; + } + if (arg == "-I" && argidx+1 < args.size()) { + sop_inputs = "-I " + args[++argidx]; + continue; + } + if (arg == "-P" && argidx+1 < args.size()) { + sop_products = "-P " + args[++argidx]; + continue; + } + if (arg == "-S" && argidx+1 < args.size()) { + lutin_shared = "-S " + args[++argidx]; + 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)); + 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) < atoi(parts.at(0).c_str())) + lut_costs.push_back(atoi(parts.at(1).c_str())); + else + log_cmd_error("Invalid -luts syntax.\n"); + } + continue; + } + if (arg == "-sop") { + sop_mode = true; + continue; + } + if (arg == "-mux4") { + map_mux4 = true; + continue; + } + if (arg == "-mux8") { + map_mux8 = true; + continue; + } + if (arg == "-mux16") { + map_mux16 = true; + continue; + } + if (arg == "-g" && argidx+1 < args.size()) { + for (auto g : split_tokens(args[++argidx], ",")) { + vector 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 == "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") { + gate_list.push_back("NAND"); + gate_list.push_back("NOR"); + goto ok_alias; + } + if (g == "cmos3") { + 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") { + 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 == "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; + } + 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); + } + } + continue; + } + if (arg == "-fast") { + fast_mode = true; + continue; + } + if (arg == "-dff") { + dff_mode = true; + continue; + } + if (arg == "-clk" && argidx+1 < args.size()) { + clk_str = args[++argidx]; + dff_mode = true; + continue; + } + if (arg == "-keepff") { + keepff = true; + continue; + } + if (arg == "-nocleanup") { + cleanup = false; + continue; + } + if (arg == "-showtmp") { + show_tempdir = true; + continue; + } + if (arg == "-markgroups") { + markgroups = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!lut_costs.empty() && !liberty_file.empty()) + log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); + if (!constr_file.empty() && liberty_file.empty()) + log_cmd_error("Got -constr but no -liberty!\n"); + + for (auto mod : design->selected_modules()) + { + if (mod->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(mod)); + continue; + } + + assign_map.set(mod); + signal_init.clear(); + + for (Wire *wire : mod->wires()) + if (wire->attributes.count("\\init")) { + SigSpec initsig = assign_map(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + switch (initval[i]) { + case State::S0: + signal_init[initsig[i]] = State::S0; + break; + case State::S1: + signal_init[initsig[i]] = State::S0; + break; + default: + break; + } + } + + if (!dff_mode || !clk_str.empty()) { + abc_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); + continue; + } + + CellTypes ct(design); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; + + typedef tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } + } + } + + if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") + { + key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); + } + else + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"; + bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"; + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); + + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + log_header(design, "Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + clk_polarity = std::get<0>(it.first); + clk_sig = assign_map(std::get<1>(it.first)); + en_polarity = std::get<2>(it.first); + en_sig = assign_map(std::get<3>(it.first)); + abc_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); + assign_map.set(mod); + } + } + + assign_map.clear(); + signal_list.clear(); + signal_map.clear(); + signal_init.clear(); + pi_map.clear(); + po_map.clear(); + + log_pop(); + } +} AbcPass; + +PRIVATE_NAMESPACE_END From edf7267019ec2e9a69be2fc5d5022a738acbe7b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:58:20 -0800 Subject: [PATCH 002/514] Refactor kernel/cost.h definition into cost.cc --- Makefile | 1 + kernel/cost.cc | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/cost.h | 51 ++-------------------------------- 3 files changed, 78 insertions(+), 49 deletions(-) create mode 100644 kernel/cost.cc diff --git a/Makefile b/Makefile index d83a71256..db4bf7a8f 100644 --- a/Makefile +++ b/Makefile @@ -430,6 +430,7 @@ $(eval $(call add_include_file,backends/ilang/ilang_backend.h)) OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o OBJS += kernel/cellaigs.o kernel/celledges.o +OBJS += kernel/cost.o kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' diff --git a/kernel/cost.cc b/kernel/cost.cc new file mode 100644 index 000000000..175f01e64 --- /dev/null +++ b/kernel/cost.cc @@ -0,0 +1,75 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/cost.h" + +YOSYS_NAMESPACE_BEGIN + +int get_cell_cost(RTLIL::IdString type, const dict ¶meters, + RTLIL::Design *design, dict *mod_cost_cache) +{ + static dict gate_cost = { + { "$_BUF_", 1 }, + { "$_NOT_", 2 }, + { "$_AND_", 4 }, + { "$_NAND_", 4 }, + { "$_OR_", 4 }, + { "$_NOR_", 4 }, + { "$_ANDNOT_", 4 }, + { "$_ORNOT_", 4 }, + { "$_XOR_", 8 }, + { "$_XNOR_", 8 }, + { "$_AOI3_", 6 }, + { "$_OAI3_", 6 }, + { "$_AOI4_", 8 }, + { "$_OAI4_", 8 }, + { "$_MUX_", 4 } + }; + + if (gate_cost.count(type)) + return gate_cost.at(type); + + if (parameters.empty() && design && design->module(type)) + { + RTLIL::Module *mod = design->module(type); + + if (mod->attributes.count("\\cost")) + return mod->attributes.at("\\cost").as_int(); + + dict local_mod_cost_cache; + if (mod_cost_cache == nullptr) + mod_cost_cache = &local_mod_cost_cache; + + if (mod_cost_cache->count(mod->name)) + return mod_cost_cache->at(mod->name); + + int module_cost = 1; + for (auto c : mod->cells()) + module_cost += get_cell_cost(c, mod_cost_cache); + + (*mod_cost_cache)[mod->name] = module_cost; + return module_cost; + } + + log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); + return 1; +} + +YOSYS_NAMESPACE_END diff --git a/kernel/cost.h b/kernel/cost.h index e795b571b..7d7822fa0 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -27,56 +27,9 @@ YOSYS_NAMESPACE_BEGIN int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); int get_cell_cost(RTLIL::IdString type, const dict ¶meters = dict(), - RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) -{ - static dict gate_cost = { - { "$_BUF_", 1 }, - { "$_NOT_", 2 }, - { "$_AND_", 4 }, - { "$_NAND_", 4 }, - { "$_OR_", 4 }, - { "$_NOR_", 4 }, - { "$_ANDNOT_", 4 }, - { "$_ORNOT_", 4 }, - { "$_XOR_", 8 }, - { "$_XNOR_", 8 }, - { "$_AOI3_", 6 }, - { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, - { "$_MUX_", 4 } - }; + RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr); - if (gate_cost.count(type)) - return gate_cost.at(type); - - if (parameters.empty() && design && design->module(type)) - { - RTLIL::Module *mod = design->module(type); - - if (mod->attributes.count("\\cost")) - return mod->attributes.at("\\cost").as_int(); - - dict local_mod_cost_cache; - if (mod_cost_cache == nullptr) - mod_cost_cache = &local_mod_cost_cache; - - if (mod_cost_cache->count(mod->name)) - return mod_cost_cache->at(mod->name); - - int module_cost = 1; - for (auto c : mod->cells()) - module_cost += get_cell_cost(c, mod_cost_cache); - - (*mod_cost_cache)[mod->name] = module_cost; - return module_cost; - } - - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); - return 1; -} - -int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache) +inline int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache) { return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); } From 5a0a5aae4f3b4ce1e69e2f4e46d65dbf31ac80de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:58:47 -0800 Subject: [PATCH 003/514] Compile abc9 --- passes/techmap/Makefile.inc | 1 + passes/techmap/abc9.cc | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cf9e198ad..c45571b01 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -7,6 +7,7 @@ OBJS += passes/techmap/libparse.o ifeq ($(ENABLE_ABC),1) OBJS += passes/techmap/abc.o +OBJS += passes/techmap/abc9.o ifneq ($(ABCEXTERNAL),) passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' endif diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d2d15a4a9..2719f260f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -621,7 +621,7 @@ struct abc_output_filter } }; -void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, +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 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 &cells, bool show_tempdir, bool sop_mode) @@ -1246,13 +1246,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log_pop(); } -struct AbcPass : public Pass { - AbcPass() : Pass("abc", "use ABC for technology mapping") { } +struct Abc9Pass : public Pass { + Abc9Pass() : Pass("abc9", "use ABC for technology mapping") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" abc [options] [selection]\n"); + 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"); @@ -1422,7 +1422,7 @@ struct AbcPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing ABC pass (technology mapping using ABC).\n"); + log_header(design, "Executing ABC9 pass (technology mapping using ABC).\n"); log_push(); assign_map.clear(); @@ -1703,7 +1703,7 @@ struct AbcPass : public Pass { } if (!dff_mode || !clk_str.empty()) { - abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, + 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); continue; } @@ -1848,7 +1848,7 @@ struct AbcPass : public Pass { clk_sig = assign_map(std::get<1>(it.first)); en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); - abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$", + 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); assign_map.set(mod); } @@ -1863,6 +1863,6 @@ struct AbcPass : public Pass { log_pop(); } -} AbcPass; +} Abc9Pass; PRIVATE_NAMESPACE_END From db08afe146b885777bb1bfa2260c090d9554afe3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 14:53:12 -0800 Subject: [PATCH 004/514] Copy backends/aiger/aiger.cc to xaiger.cc --- backends/aiger/xaiger.cc | 788 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 backends/aiger/xaiger.cc diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc new file mode 100644 index 000000000..dfe506c66 --- /dev/null +++ b/backends/aiger/xaiger.cc @@ -0,0 +1,788 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void aiger_encode(std::ostream &f, int x) +{ + log_assert(x >= 0); + + while (x & ~0x7f) { + f.put((x & 0x7f) | 0x80); + x = x >> 7; + } + + f.put(x); +} + +struct AigerWriter +{ + Module *module; + bool zinit_mode; + SigMap sigmap; + + dict init_map; + pool input_bits, output_bits; + dict not_map, ff_map, alias_map; + dict> and_map; + vector> asserts, assumes; + vector> liveness, fairness; + pool initstate_bits; + + vector> aig_gates; + vector aig_latchin, aig_latchinit, aig_outputs; + int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; + int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; + + dict aig_map; + dict ordered_outputs; + dict ordered_latches; + + dict init_inputs; + int initstate_ff = 0; + + int mkgate(int a0, int a1) + { + aig_m++, aig_a++; + aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0)); + return 2*aig_m; + } + + int bit2aig(SigBit bit) + { + if (aig_map.count(bit) == 0) + { + aig_map[bit] = -1; + + if (initstate_bits.count(bit)) { + log_assert(initstate_ff > 0); + aig_map[bit] = initstate_ff; + } else + if (not_map.count(bit)) { + int a = bit2aig(not_map.at(bit)) ^ 1; + aig_map[bit] = a; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + aig_map[bit] = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + aig_map[bit] = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) + log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + } + + log_assert(aig_map.at(bit) >= 0); + return aig_map.at(bit); + } + + AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + { + pool undriven_bits; + pool unused_bits; + + // promote public wires + for (auto wire : module->wires()) + if (wire->name[0] == '\\') + sigmap.add(wire); + + // promote input wires + for (auto wire : module->wires()) + if (wire->port_input) + sigmap.add(wire); + + // promote output wires + for (auto wire : module->wires()) + if (wire->port_output) + sigmap.add(wire); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_map[initsig[i]] = initval[i] == State::S1; + } + + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); + + if (bit.wire == nullptr) { + if (wire->port_output) { + aig_map[wirebit] = (bit == State::S1) ? 1 : 0; + output_bits.insert(wirebit); + } + continue; + } + + undriven_bits.insert(bit); + unused_bits.insert(bit); + + if (wire->port_input) + input_bits.insert(bit); + + if (wire->port_output) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + } + + for (auto bit : input_bits) + undriven_bits.erase(bit); + + for (auto bit : output_bits) + unused_bits.erase(bit); + + for (auto cell : module->cells()) + { + if (cell->type == "$_NOT_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + undriven_bits.erase(Y); + not_map[Y] = A; + continue; + } + + if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + { + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + unused_bits.erase(D); + undriven_bits.erase(Q); + ff_map[Q] = D; + continue; + } + + if (cell->type == "$_AND_") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit B = sigmap(cell->getPort("\\B").as_bit()); + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + unused_bits.erase(A); + unused_bits.erase(B); + undriven_bits.erase(Y); + and_map[Y] = make_pair(A, B); + continue; + } + + if (cell->type == "$initstate") + { + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + undriven_bits.erase(Y); + initstate_bits.insert(Y); + continue; + } + + if (cell->type == "$assert") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + asserts.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$assume") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + assumes.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$live") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + liveness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$fair") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + fairness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$anyconst") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + ff_map[bit] = bit; + } + continue; + } + + if (cell->type == "$anyseq") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + input_bits.insert(bit); + } + continue; + } + + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + } + + for (auto bit : unused_bits) + undriven_bits.erase(bit); + + if (!undriven_bits.empty()) { + undriven_bits.sort(); + for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + input_bits.insert(bit); + } + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + } + + init_map.sort(); + input_bits.sort(); + output_bits.sort(); + not_map.sort(); + ff_map.sort(); + and_map.sort(); + + aig_map[State::S0] = 0; + aig_map[State::S1] = 1; + + for (auto bit : input_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + if (imode && input_bits.empty()) { + aig_m++, aig_i++; + } + + if (zinit_mode) + { + for (auto it : ff_map) { + if (init_map.count(it.first)) + continue; + aig_m++, aig_i++; + init_inputs[it.first] = 2*aig_m; + } + } + + int fair_live_inputs_cnt = GetSize(liveness); + int fair_live_inputs_m = aig_m; + + aig_m += fair_live_inputs_cnt; + aig_i += fair_live_inputs_cnt; + + for (auto it : ff_map) { + aig_m++, aig_l++; + aig_map[it.first] = 2*aig_m; + ordered_latches[it.first] = aig_l-1; + if (init_map.count(it.first) == 0) + aig_latchinit.push_back(2); + else + aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) { + aig_m++, aig_l++; + initstate_ff = 2*aig_m+1; + aig_latchinit.push_back(0); + } + + int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); + int fair_live_latches_m = aig_m; + int fair_live_latches_l = aig_l; + + aig_m += fair_live_latches_cnt; + aig_l += fair_live_latches_cnt; + + for (int i = 0; i < fair_live_latches_cnt; i++) + aig_latchinit.push_back(0); + + if (zinit_mode) + { + for (auto it : ff_map) + { + int l = ordered_latches[it.first]; + + if (aig_latchinit.at(l) == 1) + aig_map[it.first] ^= 1; + + if (aig_latchinit.at(l) == 2) + { + int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + } + } + } + + for (auto it : ff_map) { + int a = bit2aig(it.second); + int l = ordered_latches[it.first]; + if (zinit_mode && aig_latchinit.at(l) == 1) + aig_latchin.push_back(a ^ 1); + else + aig_latchin.push_back(a); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) + aig_latchin.push_back(1); + + for (auto bit : output_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + + if (omode && output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + } + + for (auto it : asserts) { + aig_b++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)); + } + + if (bmode && asserts.empty()) { + aig_b++; + aig_outputs.push_back(0); + } + + for (auto it : assumes) { + aig_c++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); + } + + for (auto it : liveness) + { + int input_m = ++fair_live_inputs_m; + int latch_m1 = ++fair_live_latches_m; + int latch_m2 = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 2; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_s = 2*input_m; + int bit_q1 = 2*latch_m1; + int bit_q2 = 2*latch_m2; + + int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; + int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; + + aig_j++; + aig_latchin.push_back(bit_d1); + aig_latchin.push_back(bit_d2); + aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); + } + + for (auto it : fairness) + { + int latch_m = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 1; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_q = 2*latch_m; + + aig_f++; + aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); + aig_outputs.push_back(bit_q^1); + } + } + + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + { + int aig_obc = aig_o + aig_b + aig_c; + int aig_obcj = aig_obc + aig_j; + int aig_obcjf = aig_obcj + aig_f; + + log_assert(aig_m == aig_i + aig_l + aig_a); + log_assert(aig_l == GetSize(aig_latchin)); + log_assert(aig_l == GetSize(aig_latchinit)); + log_assert(aig_obcjf == GetSize(aig_outputs)); + + if (miter_mode) { + if (aig_b || aig_c || aig_j || aig_f) + log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); + f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); + } else { + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + if (aig_b || aig_c || aig_j || aig_f) + f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); + f << stringf("\n"); + } + + if (ascii_mode) + { + for (int i = 0; i < aig_i; i++) + f << stringf("%d\n", 2*i+2); + + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) + f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second); + } + else + { + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d 1\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) { + int lhs = 2*(aig_i+aig_l+i)+2; + int rhs0 = aig_gates.at(i).first; + int rhs1 = aig_gates.at(i).second; + int delta0 = lhs - rhs0; + int delta1 = rhs0 - rhs1; + aiger_encode(f, delta0); + aiger_encode(f, delta1); + } + } + + if (symbols_mode) + { + dict> symbols; + + for (auto wire : module->wires()) + { + if (wire->name[0] == '$') + continue; + + SigSpec sig = sigmap(wire); + + for (int i = 0; i < GetSize(wire); i++) + { + if (sig[i].wire == nullptr) { + if (wire->port_output) + sig[i] = SigBit(wire, i); + else + continue; + } + + if (wire->port_input) { + int a = aig_map.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); + } + + if (wire->port_output) { + int o = ordered_outputs.at(SigSpec(wire, i)); + if (GetSize(wire) != 1) + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; + if (GetSize(wire) != 1) + symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); + else + symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); + } + } + } + + symbols.sort(); + + for (auto &sym : symbols) { + f << sym.first; + std::sort(sym.second.begin(), sym.second.end()); + for (auto &s : sym.second) + f << " " << s; + f << std::endl; + } + } + + f << stringf("c\nGenerated by %s\n", yosys_version_str); + } + + void write_map(std::ostream &f, bool verbose_map) + { + dict input_lines; + dict init_lines; + dict output_lines; + dict latch_lines; + dict 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++) + { + if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + continue; + + int a = aig_map.at(sig[i]); + + if (verbose_map) + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); + + if (wire->port_input) { + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (wire->port_output) { + int o = ordered_outputs.at(sig[i]); + output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + if (zinit_mode && (aig_latchinit.at(l) == 1)) + latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); + else + latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + } + } + } + + input_lines.sort(); + for (auto &it : input_lines) + f << it.second; + + init_lines.sort(); + for (auto &it : init_lines) + f << it.second; + + output_lines.sort(); + for (auto &it : output_lines) + f << it.second; + + latch_lines.sort(); + for (auto &it : latch_lines) + f << it.second; + + wire_lines.sort(); + for (auto &it : wire_lines) + f << it.second; + } +}; + +struct AigerBackend : public Backend { + AigerBackend() : Backend("aiger", "write design to AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_aiger [options] [filename]\n"); + log("\n"); + log("Write the current design to an AIGER file. The design must be flattened and\n"); + log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); + log("$assert and $assume cells, and $initstate cells.\n"); + log("\n"); + log("$assert and $assume cells are converted to AIGER bad state properties and\n"); + log("invariant constraints.\n"); + log("\n"); + log(" -ascii\n"); + log(" write ASCII version of AGIER format\n"); + log("\n"); + log(" -zinit\n"); + log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); + log(" uninitialized FFs.\n"); + log("\n"); + log(" -miter\n"); + log(" design outputs are AIGER bad state properties\n"); + log("\n"); + log(" -symbols\n"); + log(" include a symbol table in the generated AIGER file\n"); + log("\n"); + log(" -map \n"); + log(" write an extra file with port and latch symbols\n"); + log("\n"); + log(" -vmap \n"); + log(" like -map, but more verbose\n"); + log("\n"); + log(" -I, -O, -B\n"); + log(" If the design contains no input/output/assert then create one\n"); + log(" dummy input/output/bad_state pin to make the tools reading the\n"); + log(" AIGER file happy.\n"); + log("\n"); + } + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + bool ascii_mode = false; + bool zinit_mode = false; + bool miter_mode = false; + bool symbols_mode = false; + bool verbose_map = false; + bool imode = false; + bool omode = false; + bool bmode = false; + std::string map_filename; + + log_header(design, "Executing AIGER backend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-ascii") { + ascii_mode = true; + continue; + } + if (args[argidx] == "-zinit") { + zinit_mode = true; + continue; + } + if (args[argidx] == "-miter") { + miter_mode = true; + continue; + } + if (args[argidx] == "-symbols") { + symbols_mode = true; + continue; + } + if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + continue; + } + if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + verbose_map = true; + continue; + } + if (args[argidx] == "-I") { + imode = true; + continue; + } + if (args[argidx] == "-O") { + omode = true; + continue; + } + if (args[argidx] == "-B") { + bmode = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + Module *top_module = design->top_module(); + + if (top_module == nullptr) + log_error("Can't find top module in current design!\n"); + + AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + + if (!map_filename.empty()) { + std::ofstream mapf; + 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); + } + } +} AigerBackend; + +PRIVATE_NAMESPACE_END From ecd24461323d4dc0cd369d3173a39912aa459618 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 15:18:42 -0800 Subject: [PATCH 005/514] Add write_xaiger --- backends/aiger/Makefile.inc | 1 + backends/aiger/xaiger.cc | 31 ++++++++++--------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/backends/aiger/Makefile.inc b/backends/aiger/Makefile.inc index 0fc37e95c..4a4cf30bd 100644 --- a/backends/aiger/Makefile.inc +++ b/backends/aiger/Makefile.inc @@ -1,3 +1,4 @@ OBJS += backends/aiger/aiger.o +OBJS += backends/aiger/xaiger.o diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dfe506c66..7fc61fa9a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -35,7 +35,7 @@ void aiger_encode(std::ostream &f, int x) f.put(x); } -struct AigerWriter +struct XAigerWriter { Module *module; bool zinit_mode; @@ -100,7 +100,7 @@ struct AigerWriter return aig_map.at(bit); } - AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -669,20 +669,16 @@ struct AigerWriter } }; -struct AigerBackend : public Backend { - AigerBackend() : Backend("aiger", "write design to AIGER file") { } +struct XAigerBackend : public Backend { + XAigerBackend() : Backend("xaiger", "write design to XAIGER file") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" write_aiger [options] [filename]\n"); + log(" write_xaiger [options] [filename]\n"); log("\n"); - log("Write the current design to an AIGER file. The design must be flattened and\n"); - log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); - log("$assert and $assume cells, and $initstate cells.\n"); - log("\n"); - log("$assert and $assume cells are converted to AIGER bad state properties and\n"); - log("invariant constraints.\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("\n"); log(" -ascii\n"); log(" write ASCII version of AGIER format\n"); @@ -691,9 +687,6 @@ struct AigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -miter\n"); - log(" design outputs are AIGER bad state properties\n"); - log("\n"); log(" -symbols\n"); log(" include a symbol table in the generated AIGER file\n"); log("\n"); @@ -721,7 +714,7 @@ struct AigerBackend : public Backend { bool bmode = false; std::string map_filename; - log_header(design, "Executing AIGER backend.\n"); + log_header(design, "Executing XAIGER backend.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -734,10 +727,6 @@ struct AigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-miter") { - miter_mode = true; - continue; - } if (args[argidx] == "-symbols") { symbols_mode = true; continue; @@ -772,7 +761,7 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { @@ -783,6 +772,6 @@ struct AigerBackend : public Backend { writer.write_map(mapf, verbose_map); } } -} AigerBackend; +} XAigerBackend; PRIVATE_NAMESPACE_END From 0124512f28e8bbd2c1865eac0ec00f955e2bf72a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 15:19:17 -0800 Subject: [PATCH 006/514] Add read_xaiger --- frontends/aiger/aigerparse.cc | 126 +++++++++++++++++++++++++++------- frontends/aiger/aigerparse.h | 5 +- 2 files changed, 106 insertions(+), 25 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c45de8531..4a39d9966 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -26,6 +26,8 @@ #include "kernel/sigtools.h" #include "aigerparse.h" +#include + YOSYS_NAMESPACE_BEGIN #define log_debug log @@ -68,9 +70,9 @@ void AigerReader::parse_aiger() line_count = 1; if (header == "aag") - parse_aiger_ascii(); + parse_aiger_ascii(true /* create_and */); else if (header == "aig") - parse_aiger_binary(); + parse_aiger_binary(true /* create_and */); else log_abort(); @@ -102,7 +104,6 @@ void AigerReader::parse_aiger() if (f.peek() == '\n') break; // Else constraint (TODO) - break; } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); @@ -113,6 +114,83 @@ void AigerReader::parse_aiger() design->add(module); } +void AigerReader::parse_xaiger() +{ + std::string header; + f >> header; + if (header != "aag" && header != "aig") + log_error("Unsupported AIGER file!\n"); + + // Parse rest of header + if (!(f >> M >> I >> L >> O >> A)) + log_error("Invalid AIGER header\n"); + + // Optional values + B = C = J = F = 0; + + std::string line; + std::getline(f, line); // Ignore up to start of next line, as standard + // says anything that follows could be used for + // optional sections + + log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A); + + line_count = 1; + + if (header == "aag") + parse_aiger_ascii(false /* create_and */); + else if (header == "aig") + parse_aiger_binary(false /* create_and */); + else + log_abort(); + + // Parse footer (symbol table, comments, etc.) + unsigned l1; + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek()) { + if (c == 'i' || c == 'l' || c == 'o') { + f.ignore(1); + if (!(f >> l1 >> s)) + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); + + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) + log_error("Line %u has invalid symbol position!\n", line_count); + + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else log_abort(); + + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + if (f.peek() == 'm') { + f.ignore(1); + boost::endian::big_uint32_buf_t dataSize, lutNum, lutSize; + if (f.readsome(reinterpret_cast(&dataSize), sizeof(dataSize)) != sizeof(dataSize)) + log_error("Line %u: unable to read dataSize!\n", line_count); + if (f.readsome(reinterpret_cast(&lutNum), sizeof(lutNum)) != sizeof(lutNum)) + log_error("Line %u: unable to read lutNum!\n", line_count); + if (f.readsome(reinterpret_cast(&lutSize), sizeof(lutSize)) != sizeof(lutSize)) + log_error("Line %u: unable to read lutSize!\n", line_count); + log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize.value(), lutNum.value(), lutSize.value()); + break; + } + } + else + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + std::getline(f, line); // Ignore up to start of next line + ++line_count; + } + + module->fixup_ports(); + design->add(module); +} + static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) { const unsigned variable = literal >> 1; @@ -141,7 +219,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } -void AigerReader::parse_aiger_ascii() +void AigerReader::parse_aiger_ascii(bool create_and) { std::string line; std::stringstream ss; @@ -232,15 +310,17 @@ void AigerReader::parse_aiger_ascii() log_error("Line %u cannot be interpreted as an AND!\n", line_count); log_debug("%d %d %d is an AND\n", l1, l2, l3); - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + if (create_and) { + log_assert(!(l1 & 1)); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } } std::getline(f, line); // Ignore up to start of next line } @@ -254,7 +334,7 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) return ref - (x | (ch << (7 * i))); } -void AigerReader::parse_aiger_binary() +void AigerReader::parse_aiger_binary(bool create_and) { unsigned l1, l2, l3; std::string line; @@ -340,18 +420,18 @@ void AigerReader::parse_aiger_binary() l3 = parse_next_delta_literal(f, l2); log_debug("%d %d %d is an AND\n", l1, l2, l3); - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + if (create_and) { + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } } - std::getline(f, line); // Ignore up to start of next line - } struct AigerFrontend : public Frontend { diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 39a77bd93..e50f96ef7 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -41,8 +41,9 @@ struct AigerReader AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); void parse_aiger(); - void parse_aiger_ascii(); - void parse_aiger_binary(); + void parse_xaiger(); + void parse_aiger_ascii(bool create_and); + void parse_aiger_binary(bool create_and); }; YOSYS_NAMESPACE_END From b3341b4abb4d775c94d61e502bad905b15004823 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 09:31:22 -0800 Subject: [PATCH 007/514] WIP for ABC with aiger --- passes/techmap/abc9.cc | 149 ++++++----------------------------------- 1 file changed, 19 insertions(+), 130 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2719f260f..1b4254a53 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -31,7 +31,7 @@ #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; &fraig; &scorr; &dc2; &retime; &dch -f; &if;"/*" &mfs"*/ #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" @@ -58,7 +58,7 @@ # include #endif -#include "frontends/blif/blifparse.h" +#include "frontends/aiger/aigerparse.h" #ifdef YOSYS_LINK_ABC extern "C" int Abc_RealMain(int argc, char *argv[]); @@ -672,10 +672,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); - log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n", + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str()); + std::string abc_script = stringf("&read %s/input.xaig; ", tempdir_name.c_str()); if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); @@ -704,8 +704,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (this_cost != lut_costs.front()) all_luts_cost_same = false; abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; - if (all_luts_cost_same && !fast_mode) - abc_script += "; lutpack {S}"; + //if (all_luts_cost_same && !fast_mode) + // abc_script += "; lutpack {S}"; } else if (!liberty_file.empty()) abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); else if (sop_mode) @@ -729,7 +729,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); - abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str()); + abc_script += stringf("; &write -v %s/output.xaig", tempdir_name.c_str()); abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) @@ -772,129 +772,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(); - std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); - f = fopen(buffer.c_str(), "wt"); - if (f == NULL) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); + Pass::call(design, stringf("aigmap; write_xaiger %s/input.xaig", tempdir_name.c_str())); - fprintf(f, ".model netlist\n"); - - int count_input = 0; - fprintf(f, ".inputs"); - for (auto &si : signal_list) { - if (!si.is_port || si.type != G(NONE)) - continue; - fprintf(f, " n%d", si.id); - pi_map[count_input++] = log_signal(si.bit); - } - 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 == G(NONE)) - continue; - fprintf(f, " n%d", si.id); - po_map[count_output++] = log_signal(si.bit); - } - fprintf(f, "\n"); - - for (auto &si : signal_list) - fprintf(f, "# n%-5d %s\n", si.id, log_signal(si.bit)); - - for (auto &si : signal_list) { - if (si.bit.wire == NULL) { - fprintf(f, ".names n%d\n", si.id); - if (si.bit == RTLIL::State::S1) - fprintf(f, "1\n"); - } - } - - int count_gates = 0; - for (auto &si : signal_list) { - if (si.type == G(BUF)) { - fprintf(f, ".names n%d n%d\n", si.in1, si.id); - fprintf(f, "1 1\n"); - } else 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 == 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 == 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 == 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 == 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(ANDNOT)) { - fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); - fprintf(f, "10 1\n"); - } else if (si.type == G(ORNOT)) { - fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); - fprintf(f, "1- 1\n"); - fprintf(f, "-0 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 == 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)) { - if (si.init == State::S0 || si.init == State::S1) { - fprintf(f, ".latch n%d n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0); - recover_init = true; - } else - fprintf(f, ".latch n%d n%d 2\n", si.in1, si.id); - } else if (si.type != G(NONE)) - log_abort(); - if (si.type != G(NONE)) - count_gates++; - } - - fprintf(f, ".end\n"); - fclose(f); - - 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); log_push(); - if (count_output > 0) + //if (count_output > 0) { log_header(design, "Executing ABC.\n"); - buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); + std::string buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); @@ -970,7 +856,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (ret != 0) 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.blif"); + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.xaig"); std::ifstream ifs; ifs.open(buffer); if (ifs.fail()) @@ -978,7 +864,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; - parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); + //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); + AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk"); + reader.parse_aiger(); ifs.close(); @@ -1232,10 +1120,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri delete mapped_design; } - 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) { @@ -1441,6 +1329,7 @@ struct Abc9Pass : public Pass { std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; + show_tempdir = true; cleanup = false; vector lut_costs; markgroups = false; From 77d362775338449aca7b3b8444386c7419447438 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 09:36:22 -0800 Subject: [PATCH 008/514] Parse 'm' in xaiger --- frontends/aiger/aigerparse.cc | 77 ++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4a39d9966..e6341412c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -27,6 +27,7 @@ #include "aigerparse.h" #include +#include YOSYS_NAMESPACE_BEGIN @@ -114,6 +115,14 @@ void AigerReader::parse_aiger() design->add(module); } +static uint32_t parse_xaiger_literal(std::istream &f) +{ + boost::endian::big_uint32_buf_t l; + if (f.readsome(reinterpret_cast(&l), sizeof(l)) != sizeof(l)) + log_error("Offset %ld: unable to read literal!\n", boost::lexical_cast(f.tellg())); + return l.value(); +} + void AigerReader::parse_xaiger() { std::string header; @@ -147,8 +156,52 @@ void AigerReader::parse_xaiger() // Parse footer (symbol table, comments, etc.) unsigned l1; std::string s; + bool comment_seen = false; for (int c = f.peek(); c != EOF; c = f.peek()) { - if (c == 'i' || c == 'l' || c == 'o') { + if (comment_seen || c == 'c') { + if (!comment_seen) { + f.ignore(1); + c = f.peek(); + if (c == '\n') + break; + f.ignore(1); + comment_seen = true; + } + // XAIGER extensions + if (c == 'm') { + uint32_t dataSize = parse_xaiger_literal(f); + uint32_t lutNum = parse_xaiger_literal(f); + uint32_t lutSize = parse_xaiger_literal(f); + log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); + for (unsigned i = 0; i < lutNum; ++i) { + uint32_t rootNodeID = parse_xaiger_literal(f); + uint32_t cutLeavesM = parse_xaiger_literal(f); + log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); + RTLIL::Wire *output_sig = module->wire(stringf("\\n%d", rootNodeID)); + log_assert(output_sig); + uint32_t nodeID; + RTLIL::SigSpec input_sig; + for (unsigned j = 0; j < cutLeavesM; ++j) { + nodeID = parse_xaiger_literal(f); + log_debug("\t%u\n", nodeID); + RTLIL::Wire *wire = module->wire(stringf("\\n%d", nodeID)); + log_assert(wire); + input_sig.append(wire); + } + RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); + cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); + cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); + cell->setPort("\\A", input_sig); + cell->setPort("\\Y", output_sig); + } + } + else if (c == 'n') { + // TODO: What is this? + uint32_t n = parse_xaiger_literal(f); + f.seekg(n); + } + } + else if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); if (!(f >> l1 >> s)) log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); @@ -163,28 +216,11 @@ void AigerReader::parse_xaiger() else log_abort(); module->rename(wire, stringf("\\%s", s.c_str())); - } - else if (c == 'c') { - f.ignore(1); - if (f.peek() == '\n') - break; - if (f.peek() == 'm') { - f.ignore(1); - boost::endian::big_uint32_buf_t dataSize, lutNum, lutSize; - if (f.readsome(reinterpret_cast(&dataSize), sizeof(dataSize)) != sizeof(dataSize)) - log_error("Line %u: unable to read dataSize!\n", line_count); - if (f.readsome(reinterpret_cast(&lutNum), sizeof(lutNum)) != sizeof(lutNum)) - log_error("Line %u: unable to read lutNum!\n", line_count); - if (f.readsome(reinterpret_cast(&lutSize), sizeof(lutSize)) != sizeof(lutSize)) - log_error("Line %u: unable to read lutSize!\n", line_count); - log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize.value(), lutNum.value(), lutSize.value()); - break; - } + std::getline(f, line); // Ignore up to start of next line + ++line_count; } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - std::getline(f, line); // Ignore up to start of next line - ++line_count; } module->fixup_ports(); @@ -341,6 +377,7 @@ void AigerReader::parse_aiger_binary(bool create_and) // Parse inputs for (unsigned i = 1; i <= I; ++i) { + log_debug("%d is an input\n", i); RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; inputs.push_back(wire); From 06ba81d41f7d1a8e7bae469f016b2e3e412cab7a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 12:16:37 -0800 Subject: [PATCH 009/514] Add support for read_aiger -map --- frontends/aiger/aigerparse.cc | 83 +++++++++++++++++++++++++++++++++-- frontends/aiger/aigerparse.h | 3 +- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e6341412c..9766e1aae 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -33,8 +33,8 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name) - : design(design), f(f), clk_name(clk_name) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename) + : design(design), f(f), clk_name(clk_name), map_filename(map_filename) { module = new RTLIL::Module; module->name = module_name; @@ -223,6 +223,75 @@ void AigerReader::parse_xaiger() log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); } + bool wideports = true; + dict wideports_cache; + + if (!map_filename.empty()) { + std::ifstream mf(map_filename); + std::string type, symbol; + int variable, index; + while (mf >> type >> variable >> index >> symbol) { + RTLIL::IdString escaped_symbol = RTLIL::escape_id(symbol); + if (type == "input") { + log_assert(static_cast(variable) < inputs.size()); + RTLIL::Wire* wire = inputs[variable]; + log_assert(wire); + log_assert(wire->port_input); + + if (index == 0) + module->rename(wire, RTLIL::escape_id(symbol)); + else if (index > 0) { + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + + } + } + else if (type == "output") { + log_assert(static_cast(variable) < outputs.size()); + RTLIL::Wire* wire = outputs[variable]; + log_assert(wire); + log_assert(wire->port_output); + if (index == 0) + module->rename(wire, RTLIL::escape_id(symbol)); + else if (index > 0) { + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + + } + } + else + log_error("Symbol type '%s' not recognised.\n", type.c_str()); + } + } + + for (auto &wp : wideports_cache) + { + auto name = wp.first; + int width = wp.second + 1; + + RTLIL::Wire *wire = module->wire(name); + if (wire) + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + wire = module->addWire(name, width); + + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + wire->port_input = other_wire->port_input; + wire->port_output = other_wire->port_output; + other_wire->port_input = false; + other_wire->port_output = false; + if (wire->port_input) + module->connect(other_wire, SigSpec(wire, i)); + else + module->connect(SigSpec(wire, i), other_wire); + } + } + } + module->fixup_ports(); design->add(module); } @@ -493,6 +562,9 @@ struct AigerFrontend : public Frontend { log(" -clk_name \n"); log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); log(" this name (default: clk)\n"); + log("\n"); + log(" -map \n"); + log(" read file with port and latch symbols\n"); log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -501,6 +573,7 @@ struct AigerFrontend : public Frontend { RTLIL::IdString clk_name = "\\clk"; RTLIL::IdString module_name; + std::string map_filename; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -513,6 +586,10 @@ struct AigerFrontend : public Frontend { clk_name = RTLIL::escape_id(args[++argidx]); continue; } + if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -525,7 +602,7 @@ struct AigerFrontend : public Frontend { #endif } - AigerReader reader(design, *f, module_name, clk_name); + AigerReader reader(design, *f, module_name, clk_name, map_filename); reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index e50f96ef7..79efe9111 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -30,6 +30,7 @@ struct AigerReader std::istream &f; RTLIL::IdString clk_name; RTLIL::Module *module; + std::string map_filename; unsigned M, I, L, O, A; unsigned B, C, J, F; // Optional in AIGER 1.9 @@ -39,7 +40,7 @@ struct AigerReader std::vector latches; std::vector outputs; - AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); + AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename); void parse_aiger(); void parse_xaiger(); void parse_aiger_ascii(bool create_and); From e9df9a466a79677633bbcd6b419f7ea8d8d3cf6d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 12:58:10 -0800 Subject: [PATCH 010/514] Add support for read_aiger -wideports --- frontends/aiger/aigerparse.cc | 18 +++++++++++++----- frontends/aiger/aigerparse.h | 3 ++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9766e1aae..cc4abe184 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -33,8 +33,8 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename) - : design(design), f(f), clk_name(clk_name), map_filename(map_filename) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) + : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports) { module = new RTLIL::Module; module->name = module_name; @@ -223,7 +223,6 @@ void AigerReader::parse_xaiger() log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); } - bool wideports = true; dict wideports_cache; if (!map_filename.empty()) { @@ -284,7 +283,7 @@ void AigerReader::parse_xaiger() wire->port_output = other_wire->port_output; other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) + if (wire->port_output) module->connect(other_wire, SigSpec(wire, i)); else module->connect(SigSpec(wire, i), other_wire); @@ -566,6 +565,10 @@ struct AigerFrontend : public Frontend { log(" -map \n"); log(" read file with port and latch symbols\n"); log("\n"); + log(" -wideports\n"); + log(" Merge ports that match the pattern 'name[int]' into a single\n"); + log(" multi-bit port 'name'.\n"); + log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -574,6 +577,7 @@ struct AigerFrontend : public Frontend { RTLIL::IdString clk_name = "\\clk"; RTLIL::IdString module_name; std::string map_filename; + bool wideports = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -590,6 +594,10 @@ struct AigerFrontend : public Frontend { map_filename = args[++argidx]; continue; } + if (arg == "-wideports") { + wideports = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -602,7 +610,7 @@ struct AigerFrontend : public Frontend { #endif } - AigerReader reader(design, *f, module_name, clk_name, map_filename); + AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports); reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 79efe9111..a1d2af9c9 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -31,6 +31,7 @@ struct AigerReader RTLIL::IdString clk_name; RTLIL::Module *module; std::string map_filename; + bool wideports; unsigned M, I, L, O, A; unsigned B, C, J, F; // Optional in AIGER 1.9 @@ -40,7 +41,7 @@ struct AigerReader std::vector latches; std::vector outputs; - AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename); + AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); void parse_xaiger(); void parse_aiger_ascii(bool create_and); From 045f7763ae6adf406c3350c095ed6c224d1972c7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 16:25:22 -0800 Subject: [PATCH 011/514] Rip out unused functions in abc9 --- passes/techmap/abc9.cc | 477 ++++++----------------------------------- 1 file changed, 61 insertions(+), 416 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1b4254a53..19b94641b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -117,216 +117,6 @@ bool clk_polarity, en_polarity; RTLIL::SigSpec clk_sig, en_sig; dict pi_map, po_map; -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) -{ - assign_map.apply(bit); - - if (signal_map.count(bit) == 0) { - gate_t gate; - gate.id = signal_list.size(); - gate.type = G(NONE); - gate.in1 = -1; - gate.in2 = -1; - gate.in3 = -1; - gate.in4 = -1; - gate.is_port = false; - gate.bit = bit; - if (signal_init.count(bit)) - gate.init = signal_init.at(bit); - else - gate.init = State::Sx; - signal_list.push_back(gate); - signal_map[bit] = gate.id; - } - - gate_t &gate = signal_list[signal_map[bit]]; - - if (gate_type != G(NONE)) - gate.type = gate_type; - if (in1 >= 0) - gate.in1 = in1; - if (in2 >= 0) - gate.in2 = in2; - if (in3 >= 0) - gate.in3 = in3; - if (in4 >= 0) - gate.in4 = in4; - - return gate.id; -} - -void mark_port(RTLIL::SigSpec sig) -{ - for (auto &bit : assign_map(sig)) - if (bit.wire != NULL && signal_map.count(bit) > 0) - signal_list[signal_map[bit]].is_port = true; -} - -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->getPort("\\C"))) - return; - if (GetSize(en_sig) != 0) - return; - goto matching_dff; - } - - if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") - { - if (clk_polarity != (cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")) - return; - if (en_polarity != (cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_")) - return; - if (clk_sig != assign_map(cell->getPort("\\C"))) - return; - if (en_sig != assign_map(cell->getPort("\\E"))) - return; - goto matching_dff; - } - - if (0) { - matching_dff: - 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, G(FF), map_signal(sig_d)); - - module->remove(cell); - return; - } - - if (cell->type.in("$_BUF_", "$_NOT_")) - { - 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, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a)); - - module->remove(cell); - return; - } - - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) - { - 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); - assign_map.apply(sig_y); - - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); - - if (cell->type == "$_AND_") - 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, 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, G(XOR), mapped_a, mapped_b); - else if (cell->type == "$_XNOR_") - map_signal(sig_y, G(XNOR), mapped_a, mapped_b); - else if (cell->type == "$_ANDNOT_") - map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b); - else if (cell->type == "$_ORNOT_") - map_signal(sig_y, G(ORNOT), mapped_a, mapped_b); - else - log_abort(); - - module->remove(cell); - return; - } - - if (cell->type == "$_MUX_") - { - 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); - assign_map.apply(sig_s); - assign_map.apply(sig_y); - - int mapped_a = map_signal(sig_a); - int mapped_b = map_signal(sig_b); - int mapped_s = map_signal(sig_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->remove(cell); - return; - } -} - std::string remap_name(RTLIL::IdString abc_name) { std::stringstream sstr; @@ -334,168 +124,6 @@ std::string remap_name(RTLIL::IdString abc_name) return sstr.str(); } -void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) -{ - if (f == NULL) - return; - - log("Dumping loop state graph to slide %d.\n", ++nr); - - fprintf(f, "digraph \"slide%d\" {\n", nr); - fprintf(f, " label=\"slide%d\";\n", nr); - fprintf(f, " rankdir=\"TD\";\n"); - - std::set nodes; - for (auto &e : edges) { - nodes.insert(e.first); - for (auto n : e.second) - nodes.insert(n); - } - - for (auto n : nodes) - 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) - for (auto n : e.second) - fprintf(f, " n%d -> n%d;\n", e.first, n); - - fprintf(f, "}\n"); -} - -void handle_loops() -{ - // http://en.wikipedia.org/wiki/Topological_sorting - // (Kahn, Arthur B. (1962), "Topological sorting of large networks") - - std::map> edges; - std::vector in_edges_count(signal_list.size()); - std::set workpool; - - FILE *dot_f = NULL; - int dot_nr = 0; - - // uncomment for troubleshooting the loop detection code - // dot_f = fopen("test.dot", "w"); - - for (auto &g : signal_list) { - if (g.type == G(NONE) || g.type == G(FF)) { - workpool.insert(g.id); - } else { - if (g.in1 >= 0) { - edges[g.in1].insert(g.id); - in_edges_count[g.id]++; - } - if (g.in2 >= 0 && g.in2 != g.in1) { - edges[g.in2].insert(g.id); - in_edges_count[g.id]++; - } - if (g.in3 >= 0 && g.in3 != g.in2 && g.in3 != g.in1) { - 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]++; - } - } - } - - dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); - - while (workpool.size() > 0) - { - int id = *workpool.begin(); - workpool.erase(id); - - // log("Removing non-loop node %d from graph: %s\n", id, log_signal(signal_list[id].bit)); - - for (int id2 : edges[id]) { - log_assert(in_edges_count[id2] > 0); - if (--in_edges_count[id2] == 0) - workpool.insert(id2); - } - edges.erase(id); - - dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); - - while (workpool.size() == 0) - { - if (edges.size() == 0) - break; - - int id1 = edges.begin()->first; - - for (auto &edge_it : edges) { - int id2 = edge_it.first; - 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] == '$') - continue; - else if (edges[id1].size() < edges[id2].size()) - id1 = id2; - else if (edges[id1].size() > edges[id2].size()) - continue; - else if (w2->name.str() < w1->name.str()) - id1 = id2; - } - - if (edges[id1].size() == 0) { - edges.erase(id1); - continue; - } - - log_assert(signal_list[id1].bit.wire != NULL); - - std::stringstream sstr; - 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].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].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; - log_assert(id3 == int(in_edges_count.size())); - in_edges_count.push_back(0); - workpool.insert(id3); - - for (int id2 : edges[id1]) { - if (signal_list[id2].in1 == id1) - signal_list[id2].in1 = id3; - if (signal_list[id2].in2 == id1) - 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->connect(RTLIL::SigSig(signal_list[id3].bit, signal_list[id1].bit)); - dump_loop_graph(dot_f, dot_nr, edges, workpool, in_edges_count); - } - } - - if (dot_f != NULL) - fclose(dot_f); -} - std::string add_echos_to_abc_cmd(std::string str) { std::string new_str, token; @@ -675,7 +303,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("&read %s/input.xaig; ", tempdir_name.c_str()); + std::string abc_script = stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); @@ -729,7 +357,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); - abc_script += stringf("; &write -v %s/output.xaig", tempdir_name.c_str()); + abc_script += stringf("; &ps; &write -v %s/output.xaig", tempdir_name.c_str()); abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) @@ -752,27 +380,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto c : cells) - extract_cell(c, keepff); - - 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()) - mark_port(port_it.second); - - if (clk_sig.size() != 0) - mark_port(clk_sig); - - if (en_sig.size() != 0) - mark_port(en_sig); - - handle_loops(); - - Pass::call(design, stringf("aigmap; write_xaiger %s/input.xaig", tempdir_name.c_str())); + Pass::call(design, stringf("aigmap; write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); log_push(); @@ -865,8 +473,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk"); - reader.parse_aiger(); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.symbols"); + AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", buffer, true /* wideports */); + reader.parse_xaiger(); ifs.close(); @@ -876,7 +485,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_error("ABC output file does not contain a module `netlist'.\n"); for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; - RTLIL::Wire *wire = module->addWire(remap_name(w->name)); + RTLIL::Wire *wire = module->addWire(remap_name(w->name), GetSize(w)); if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx; design->select(module, wire); } @@ -1079,10 +688,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } for (auto conn : mapped_mod->connections()) { - if (!conn.first.is_fully_const()) - 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.as_wire()->name)]); + if (!conn.first.is_fully_const()) { + auto chunks = conn.first.chunks(); + for (auto &c : chunks) + c.wire = module->wires_[remap_name(c.wire->name)]; + conn.first = std::move(chunks); + } + if (!conn.second.is_fully_const() && conn.second.is_wire()) { + auto chunks = conn.second.chunks(); + for (auto &c : chunks) + c.wire = module->wires_[remap_name(c.wire->name)]; + conn.second = std::move(chunks); + } module->connect(conn); } @@ -1098,23 +715,51 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto &it : cell_stats) log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); int in_wires = 0, out_wires = 0; - for (auto &si : signal_list) - if (si.is_port) { - char buffer[100]; - snprintf(buffer, 100, "\\n%d", si.id); + //for (auto &si : signal_list) + // if (si.is_port) { + // char buffer[100]; + // snprintf(buffer, 100, "\\n%d", si.id); + // RTLIL::SigSig conn; + // 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.bit; + // in_wires++; + // } + // module->connect(conn); + // } + + // FIXME: + module->connections_.clear(); + + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; + if (!w->port_input && !w->port_output) + continue; + RTLIL::Wire *wire = module->wire(remap_name(w->name)); + if (w->port_input) { RTLIL::SigSig conn; - 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.bit; - in_wires++; - } + conn.first = wire; + conn.second = module->wire(w->name); + if (conn.second.empty()) + log_error("Input port %s not found in original module.\n", w->name.c_str()); + in_wires++; module->connect(conn); } - log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); + else if (w->port_output) { + RTLIL::SigSig conn; + conn.first = module->wire(w->name); + if (conn.first.empty()) + log_error("Output port %s not found in original module.\n", w->name.c_str()); + conn.second = wire; + out_wires++; + 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); log("ABC RESULTS: output signals: %8d\n", out_wires); From 87f059adf7c075cc5dfe2e01b674fffa567db425 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Feb 2019 10:44:52 -0800 Subject: [PATCH 012/514] Rip out some more stuff --- passes/techmap/abc9.cc | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 19b94641b..65eafffd9 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -67,38 +67,6 @@ extern "C" int Abc_RealMain(int argc, char *argv[]); USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -enum class gate_type_t { - G_NONE, - G_FF, - G_BUF, - G_NOT, - G_AND, - G_NAND, - G_OR, - G_NOR, - G_XOR, - G_XNOR, - G_ANDNOT, - G_ORNOT, - G_MUX, - G_AOI3, - G_OAI3, - G_AOI4, - G_OAI4 -}; - -#define G(_name) gate_type_t::G_ ## _name - -struct gate_t -{ - int id; - gate_type_t type; - int in1, in2, in3, in4; - bool is_port; - RTLIL::SigBit bit; - RTLIL::State init; -}; - bool map_mux4; bool map_mux8; bool map_mux16; @@ -107,7 +75,6 @@ bool markgroups; int map_autoidx; SigMap assign_map; RTLIL::Module *module; -std::vector signal_list; std::map signal_map; std::map signal_init; pool enabled_gates; @@ -258,7 +225,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri map_autoidx = autoidx++; signal_map.clear(); - signal_list.clear(); pi_map.clear(); po_map.clear(); recover_init = false; @@ -959,7 +925,6 @@ struct Abc9Pass : public Pass { log_push(); assign_map.clear(); - signal_list.clear(); signal_map.clear(); signal_init.clear(); pi_map.clear(); @@ -1389,7 +1354,6 @@ struct Abc9Pass : public Pass { } assign_map.clear(); - signal_list.clear(); signal_map.clear(); signal_init.clear(); pi_map.clear(); From 13bf036bd6f78f57d6431171aca49984898a2bdd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Feb 2019 17:00:00 -0800 Subject: [PATCH 013/514] Use ConstEval to compute LUT masks --- frontends/aiger/aigerparse.cc | 128 ++++++++++++++++++---------------- frontends/aiger/aigerparse.h | 4 +- 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 56bffcf38..62354498c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -24,6 +24,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/consteval.h" #include "aigerparse.h" #include @@ -71,9 +72,9 @@ void AigerReader::parse_aiger() line_count = 1; if (header == "aag") - parse_aiger_ascii(true /* create_and */); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(true /* create_and */); + parse_aiger_binary(); else log_abort(); @@ -123,6 +124,32 @@ static uint32_t parse_xaiger_literal(std::istream &f) return l.value(); } +static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) +{ + const unsigned variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? + + return wire; +} + void AigerReader::parse_xaiger() { std::string header; @@ -147,9 +174,9 @@ void AigerReader::parse_xaiger() line_count = 1; if (header == "aag") - parse_aiger_ascii(false /* create_and */); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(false /* create_and */); + parse_aiger_binary(); else log_abort(); @@ -162,11 +189,11 @@ void AigerReader::parse_xaiger() if (!comment_seen) { f.ignore(1); c = f.peek(); - if (c == '\n') - break; - f.ignore(1); comment_seen = true; } + if (c == '\n') + break; + f.ignore(1); // XAIGER extensions if (c == 'm') { uint32_t dataSize = parse_xaiger_literal(f); @@ -178,7 +205,6 @@ void AigerReader::parse_xaiger() uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); RTLIL::Wire *output_sig = module->wire(stringf("\\n%d", rootNodeID)); - log_assert(output_sig); uint32_t nodeID; RTLIL::SigSpec input_sig; for (unsigned j = 0; j < cutLeavesM; ++j) { @@ -188,17 +214,30 @@ void AigerReader::parse_xaiger() log_assert(wire); input_sig.append(wire); } + RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); + ConstEval ce(module); + for (int j = 0; j < (1 << cutLeavesM); ++j) { + ce.push(); + ce.set(input_sig, RTLIL::Const{j, static_cast(cutLeavesM)}); + RTLIL::SigSpec o(output_sig); + ce.eval(o); + lut_mask[j] = o.as_const()[0]; + ce.pop(); + } + RTLIL::Cell *output_cell = module->cell(stringf("\\n%d_and", rootNodeID)); + log_assert(output_cell); + module->remove(output_cell); RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); - cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); + cell->parameters["\\LUT"] = std::move(lut_mask); cell->setPort("\\A", input_sig); cell->setPort("\\Y", output_sig); } } else if (c == 'n') { - // TODO: What is this? - uint32_t n = parse_xaiger_literal(f); - f.seekg(n); + parse_xaiger_literal(f); + f >> s; + log_debug("n: '%s'\n", s.c_str()); } } else if (c == 'i' || c == 'l' || c == 'o') { @@ -265,8 +304,7 @@ void AigerReader::parse_xaiger() } } - for (auto &wp : wideports_cache) - { + for (auto &wp : wideports_cache) { auto name = wp.first; int width = wp.second + 1; @@ -283,8 +321,10 @@ void AigerReader::parse_xaiger() wire->port_output = other_wire->port_output; other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_output) + if (wire->port_input) { + log_debug("assign %s = %s [%d];\n", other_wire->name.c_str(), wire->name.c_str(), i); module->connect(other_wire, SigSpec(wire, i)); + } else module->connect(SigSpec(wire, i), other_wire); } @@ -295,33 +335,7 @@ void AigerReader::parse_xaiger() design->add(module); } -static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) -{ - const unsigned variable = literal >> 1; - const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); - wire = module->addWire(wire_name); - if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); - RTLIL::Wire *wire_inv = module->wire(wire_inv_name); - if (wire_inv) { - if (module->cell(wire_inv_name)) return wire; - } - else { - log_debug("Creating %s\n", wire_inv_name.c_str()); - wire_inv = module->addWire(wire_inv_name); - } - - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? - - return wire; -} - -void AigerReader::parse_aiger_ascii(bool create_and) +void AigerReader::parse_aiger_ascii() { std::string line; std::stringstream ss; @@ -412,13 +426,11 @@ void AigerReader::parse_aiger_ascii(bool create_and) log_error("Line %u cannot be interpreted as an AND!\n", line_count); log_debug("%d %d %d is an AND\n", l1, l2, l3); - if (create_and) { - log_assert(!(l1 & 1)); - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); - } + log_assert(!(l1 & 1)); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); } } @@ -431,7 +443,7 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) return ref - (x | (ch << (7 * i))); } -void AigerReader::parse_aiger_binary(bool create_and) +void AigerReader::parse_aiger_binary() { unsigned l1, l2, l3; std::string line; @@ -518,17 +530,11 @@ void AigerReader::parse_aiger_binary(bool create_and) l3 = parse_next_delta_literal(f, l2); log_debug("%d %d %d is an AND\n", l1, l2, l3); - if (create_and) { - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); - } + log_assert(!(l1 & 1)); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); } } diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index a1d2af9c9..42c87a298 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -44,8 +44,8 @@ struct AigerReader AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); void parse_xaiger(); - void parse_aiger_ascii(bool create_and); - void parse_aiger_binary(bool create_and); + void parse_aiger_ascii(); + void parse_aiger_binary(); }; YOSYS_NAMESPACE_END From 206f11dca3210931c542fb010f525949f1246540 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Feb 2019 17:04:23 -0800 Subject: [PATCH 014/514] Fix stitching --- passes/techmap/abc9.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 65eafffd9..278251320 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -653,6 +653,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri design->select(module, cell); } + // FIXME: Better way to clean out module contents? + module->connections_.clear(); + for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) { auto chunks = conn.first.chunks(); @@ -660,7 +663,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri c.wire = module->wires_[remap_name(c.wire->name)]; conn.first = std::move(chunks); } - if (!conn.second.is_fully_const() && conn.second.is_wire()) { + if (!conn.second.is_fully_const()) { auto chunks = conn.second.chunks(); for (auto &c : chunks) c.wire = module->wires_[remap_name(c.wire->name)]; @@ -698,9 +701,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - // FIXME: - module->connections_.clear(); - for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; if (!w->port_input && !w->port_output) From 396da54b5297e644087c63cd7bfb244e7ae81e3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Feb 2019 17:08:32 -0800 Subject: [PATCH 015/514] Use module->addLut() --- frontends/aiger/aigerparse.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 62354498c..931d2fd36 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -227,11 +227,7 @@ void AigerReader::parse_xaiger() RTLIL::Cell *output_cell = module->cell(stringf("\\n%d_and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); - cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); - cell->parameters["\\LUT"] = std::move(lut_mask); - cell->setPort("\\A", input_sig); - cell->setPort("\\Y", output_sig); + module->addLut(NEW_ID, input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'n') { From c7ef3863f3181c0298d166562858dec4a7faa759 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Feb 2019 17:19:30 -0800 Subject: [PATCH 016/514] Leave FIXME for clean --- frontends/aiger/aigerparse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 931d2fd36..92700bca7 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -317,10 +317,8 @@ void AigerReader::parse_xaiger() wire->port_output = other_wire->port_output; other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) { - log_debug("assign %s = %s [%d];\n", other_wire->name.c_str(), wire->name.c_str(), i); + if (wire->port_input) module->connect(other_wire, SigSpec(wire, i)); - } else module->connect(SigSpec(wire, i), other_wire); } @@ -329,6 +327,8 @@ void AigerReader::parse_xaiger() module->fixup_ports(); design->add(module); + // FIXME: 'clean'-ing causes assertion fail in abc9.cc, and checks to fail... + //Pass::call(design, "clean"); } void AigerReader::parse_aiger_ascii() From 323dd0e608b38116db1e2bcda1ebc4ba98823990 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 13:19:27 -0800 Subject: [PATCH 017/514] synth_ice40 to have new -abc9 arg --- techlibs/ice40/synth_ice40.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index f900453e8..f77ea7f80 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -89,13 +89,16 @@ struct SynthIce40Pass : public ScriptPass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); + log(" -abc9\n"); + log(" use abc9 instead of abc\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } - string top_opt, blif_file, edif_file, json_file; + string top_opt, blif_file, edif_file, json_file, abc; bool nocarry, nodffe, nobram, flatten, retime, relut, noabc, abc2, vpr; int min_ce_use; @@ -115,6 +118,7 @@ struct SynthIce40Pass : public ScriptPass noabc = false; abc2 = false; vpr = false; + abc = "abc"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -193,6 +197,10 @@ struct SynthIce40Pass : public ScriptPass vpr = true; continue; } + if (args[argidx] == "-abc9") { + abc = "abc9"; + continue; + } break; } extra_args(args, argidx, design); @@ -249,7 +257,7 @@ struct SynthIce40Pass : public ScriptPass else run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); if (retime || help_mode) - run("abc -dff", "(only if -retime)"); + run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); } @@ -273,7 +281,7 @@ struct SynthIce40Pass : public ScriptPass if (check_label("map_luts")) { if (abc2 || help_mode) { - run("abc", " (only if -abc2)"); + run(abc, " (only if -abc2)"); run("ice40_opt", "(only if -abc2)"); } run("techmap -map +/ice40/latches_map.v"); @@ -282,7 +290,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); } if (!noabc) { - run("abc -lut 4", "(skip if -noabc)"); + run(abc + " -lut 4", "(skip if -noabc)"); } run("clean"); if (relut || help_mode) { From afa4389445adc8e53871af78ab1c38c98e03a6fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 13:27:26 -0800 Subject: [PATCH 018/514] Get rid of formal stuff from xaiger backend --- backends/aiger/xaiger.cc | 58 ---------------------------------------- 1 file changed, 58 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7fc61fa9a..c5cede3b1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -205,64 +205,6 @@ struct XAigerWriter continue; } - if (cell->type == "$assert") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - asserts.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$assume") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - assumes.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$live") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - liveness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$fair") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - fairness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$anyconst") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - ff_map[bit] = bit; - } - continue; - } - - if (cell->type == "$anyseq") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - input_bits.insert(bit); - } - continue; - } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } From 732877558475788992ad822f28a99fd16336e05a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:48:38 -0800 Subject: [PATCH 019/514] More cleanup of write_xaiger --- backends/aiger/xaiger.cc | 74 +--------------------------------------- 1 file changed, 1 insertion(+), 73 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c5cede3b1..758513cd4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -45,8 +45,6 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - vector> asserts, assumes; - vector> liveness, fairness; pool initstate_bits; vector> aig_gates; @@ -249,12 +247,6 @@ struct XAigerWriter } } - int fair_live_inputs_cnt = GetSize(liveness); - int fair_live_inputs_m = aig_m; - - aig_m += fair_live_inputs_cnt; - aig_i += fair_live_inputs_cnt; - for (auto it : ff_map) { aig_m++, aig_l++; aig_map[it.first] = 2*aig_m; @@ -271,16 +263,6 @@ struct XAigerWriter aig_latchinit.push_back(0); } - int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); - int fair_live_latches_m = aig_m; - int fair_live_latches_l = aig_l; - - aig_m += fair_live_latches_cnt; - aig_l += fair_live_latches_cnt; - - for (int i = 0; i < fair_live_latches_cnt; i++) - aig_latchinit.push_back(0); - if (zinit_mode) { for (auto it : ff_map) @@ -322,64 +304,10 @@ struct XAigerWriter aig_outputs.push_back(0); } - for (auto it : asserts) { - aig_b++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)); - } - - if (bmode && asserts.empty()) { + if (bmode) { aig_b++; aig_outputs.push_back(0); } - - for (auto it : assumes) { - aig_c++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); - } - - for (auto it : liveness) - { - int input_m = ++fair_live_inputs_m; - int latch_m1 = ++fair_live_latches_m; - int latch_m2 = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 2; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_s = 2*input_m; - int bit_q1 = 2*latch_m1; - int bit_q2 = 2*latch_m2; - - int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; - int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; - - aig_j++; - aig_latchin.push_back(bit_d1); - aig_latchin.push_back(bit_d2); - aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); - } - - for (auto it : fairness) - { - int latch_m = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 1; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_q = 2*latch_m; - - aig_f++; - aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); - aig_outputs.push_back(bit_q^1); - } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) From c69fba8de5056e5892014b143856993d404e7c84 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:52:47 -0800 Subject: [PATCH 020/514] More cleanup --- backends/aiger/xaiger.cc | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 758513cd4..4155c5281 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; dict aig_map; dict ordered_outputs; @@ -305,32 +304,24 @@ struct XAigerWriter } if (bmode) { - aig_b++; + //aig_b++; aig_outputs.push_back(0); } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) { - int aig_obc = aig_o + aig_b + aig_c; - int aig_obcj = aig_obc + aig_j; - int aig_obcjf = aig_obcj + aig_f; + int aig_obc = aig_o; + int aig_obcj = aig_obc; + int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); log_assert(aig_l == GetSize(aig_latchin)); log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); - if (miter_mode) { - if (aig_b || aig_c || aig_j || aig_f) - log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); - f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); - } else { - f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); - if (aig_b || aig_c || aig_j || aig_f) - f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); - f << stringf("\n"); - } + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + f << stringf("\n"); if (ascii_mode) { From 3ac5b651973debe76d4d41aef86a9d6376bdae46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 11:51:21 -0800 Subject: [PATCH 021/514] write_xaiger to cope with unknown cells by transforming them to CI/CO --- backends/aiger/xaiger.cc | 50 +++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4155c5281..433f1cdd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -46,6 +46,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; + pool ci_bits, co_bits; + dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -149,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } } } @@ -166,6 +168,8 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -187,6 +191,8 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -202,7 +208,27 @@ struct XAigerWriter continue; } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + unused_bits.erase(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + if (!w->port_output) + ci_bits.insert(O); + undriven_bits.erase(O); + } + else log_abort(); + if (!type_map.count(cell->type)) + type_map[cell->type] = type_map.size()+1; + } + //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : unused_bits) @@ -227,6 +253,12 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; + for (auto bit : ci_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + co_bits.erase(bit); + } + for (auto bit : input_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; @@ -292,6 +324,12 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); + for (auto bit : co_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + for (auto bit : output_bits) { aig_o++; ordered_outputs[bit] = aig_o-1; @@ -467,8 +505,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (!verbose_map && wire->name[0] == '$') - continue; + //if (!verbose_map && wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -482,12 +520,12 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input) { + if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output) { + if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } From 8d757224ee677cf2b6fc74b036f25c7ec95e88c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 11:52:05 -0800 Subject: [PATCH 022/514] read_aiger with more asserts, and call clean --- frontends/aiger/aigerparse.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 92700bca7..a962ff6af 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -133,6 +133,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera if (wire) return wire; log_debug("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); + wire->port_input = wire->port_output = false; if (!invert) return wire; RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); RTLIL::Wire *wire_inv = module->wire(wire_inv_name); @@ -142,6 +143,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera else { log_debug("Creating %s\n", wire_inv_name.c_str()); wire_inv = module->addWire(wire_inv_name); + wire_inv->port_input = wire_inv->port_output = false; } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); @@ -278,7 +280,6 @@ void AigerReader::parse_xaiger() module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); - } } else if (type == "output") { @@ -286,13 +287,13 @@ void AigerReader::parse_xaiger() RTLIL::Wire* wire = outputs[variable]; log_assert(wire); log_assert(wire->port_output); + if (index == 0) module->rename(wire, RTLIL::escape_id(symbol)); else if (index > 0) { module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); - } } else @@ -308,11 +309,13 @@ void AigerReader::parse_xaiger() if (wire) module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); wire = module->addWire(name, width); + wire->port_input = wire->port_output = false; for (int i = 0; i < width; i++) { RTLIL::IdString other_name = name.str() + stringf("[%d]", i); RTLIL::Wire *other_wire = module->wire(other_name); if (other_wire) { + log_assert((other_wire->port_input && !other_wire->port_output) || (other_wire->port_output && !other_wire->port_input)); wire->port_input = other_wire->port_input; wire->port_output = other_wire->port_output; other_wire->port_input = false; @@ -327,8 +330,8 @@ void AigerReader::parse_xaiger() module->fixup_ports(); design->add(module); - // FIXME: 'clean'-ing causes assertion fail in abc9.cc, and checks to fail... - //Pass::call(design, "clean"); + + Pass::call(design, "clean"); } void AigerReader::parse_aiger_ascii() @@ -357,6 +360,7 @@ void AigerReader::parse_aiger_ascii() log_debug("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; + clk_wire->port_output = false; } for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) @@ -449,6 +453,7 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an input\n", i); RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; + log_assert(!wire->port_output); inputs.push_back(wire); } @@ -460,6 +465,7 @@ void AigerReader::parse_aiger_binary() log_debug("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; + clk_wire->port_output = false; } l1 = (I+1) * 2; for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { @@ -499,6 +505,7 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; + log_assert(!wire->port_input); outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line From 956ee545c56aad5fba17109cdd2c02f3ddbfcbea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 11:52:34 -0800 Subject: [PATCH 023/514] abc9 to stitch results with CI/CO properly --- passes/techmap/abc9.cc | 48 ++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 278251320..d3416c1d3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -645,7 +645,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto &c : conn.second.chunks()) { if (c.width == 0) continue; - log_assert(c.width == 1); + //log_assert(c.width == 1); newsig.append(module->wires_[remap_name(c.wire->name)]); } cell->setPort(conn.first, newsig); @@ -653,9 +653,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri design->select(module, cell); } - // FIXME: Better way to clean out module contents? - module->connections_.clear(); - + // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) { auto chunks = conn.first.chunks(); @@ -701,30 +699,46 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } + pool output_bits; + std::vector connections; + // Stitch in mapped_mod's inputs/outputs into module for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; if (!w->port_input && !w->port_output) continue; - RTLIL::Wire *wire = module->wire(remap_name(w->name)); + RTLIL::Wire *wire = module->wire(w->name); + RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); if (w->port_input) { RTLIL::SigSig conn; - conn.first = wire; - conn.second = module->wire(w->name); - if (conn.second.empty()) - log_error("Input port %s not found in original module.\n", w->name.c_str()); + log_assert(GetSize(wire) >= GetSize(remap_wire)); + conn.first = remap_wire; + conn.second = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); in_wires++; - module->connect(conn); + connections.emplace_back(std::move(conn)); + printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), w->name.c_str()); } else if (w->port_output) { RTLIL::SigSig conn; - conn.first = module->wire(w->name); - if (conn.first.empty()) - log_error("Output port %s not found in original module.\n", w->name.c_str()); - conn.second = wire; - out_wires++; - module->connect(conn); + log_assert(GetSize(wire) >= GetSize(remap_wire)); + conn.first = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + conn.second = remap_wire; + for (int i = 0; i < GetSize(remap_wire); i++) + output_bits.insert({wire, i}); + printf("OUTPUT: assign %s = %s\n", w->name.c_str(), remap_wire->name.c_str()); + connections.emplace_back(std::move(conn)); } + else log_abort(); } + auto f = [&output_bits](RTLIL::SigSpec &s) { + if (!s.is_bit()) return; + RTLIL::SigBit b = s.as_bit(); + if (output_bits.count(b)) + s = RTLIL::State::Sx; + }; + module->rewrite_sigspecs(f); + for (const auto &c : connections) + module->connect(c); + //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); log("ABC RESULTS: output signals: %8d\n", out_wires); @@ -736,6 +750,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // log("Don't call ABC as there is nothing to map.\n"); //} + Pass::call(design, "clean"); + if (cleanup) { log("Removing temp directory.\n"); From 914546efd91697966d2d7b3a51c6fb7ffb786a9b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 12:55:52 -0800 Subject: [PATCH 024/514] Cope with width != 1 when re-mapping cells --- passes/techmap/abc9.cc | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d3416c1d3..285851ea4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -642,11 +642,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->parameters = c->parameters; 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; //log_assert(c.width == 1); - newsig.append(module->wires_[remap_name(c.wire->name)]); + c.wire = module->wires_[remap_name(c.wire->name)]; + newsig.append(c); } cell->setPort(conn.first, newsig); } @@ -715,7 +716,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri conn.second = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); in_wires++; connections.emplace_back(std::move(conn)); - printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), w->name.c_str()); + printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), wire->name.c_str()); } else if (w->port_output) { RTLIL::SigSig conn; @@ -724,18 +725,31 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri conn.second = remap_wire; for (int i = 0; i < GetSize(remap_wire); i++) output_bits.insert({wire, i}); - printf("OUTPUT: assign %s = %s\n", w->name.c_str(), remap_wire->name.c_str()); + printf("OUTPUT: assign %s = %s\n", wire->name.c_str(), remap_wire->name.c_str()); connections.emplace_back(std::move(conn)); } else log_abort(); } - auto f = [&output_bits](RTLIL::SigSpec &s) { - if (!s.is_bit()) return; - RTLIL::SigBit b = s.as_bit(); - if (output_bits.count(b)) - s = RTLIL::State::Sx; - }; - module->rewrite_sigspecs(f); + // Go through all cell output connections, + // and for those output ports driving wires + // also driven by mapped_mod, disconnect them + for (auto cell : module->cells()) { + for (auto &it : cell->connections_) { + auto port_name = it.first; + if (!cell->output(port_name)) continue; + auto &signal = it.second; + if (!signal.is_bit()) continue; + if (output_bits.count(signal.as_bit())) + signal = RTLIL::State::Sx; + } + } + // Do the same for module connections + for (auto &it : module->connections_) { + auto &signal = it.first; + if (!signal.is_bit()) continue; + if (output_bits.count(signal.as_bit())) + signal = RTLIL::State::Sx; + } for (const auto &c : connections) module->connect(c); From a786ac4d5351e4e8eae0e6abf7577cd330b2a232 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 13:00:13 -0800 Subject: [PATCH 025/514] Refactor --- passes/techmap/abc9.cc | 73 ++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 285851ea4..b32facc48 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -449,11 +449,17 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); + pool output_bits; for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; - RTLIL::Wire *wire = module->addWire(remap_name(w->name), GetSize(w)); - if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx; - design->select(module, wire); + RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); + if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx; + design->select(module, remap_wire); + RTLIL::Wire *wire = module->wire(w->name); + if (w->port_output) { + for (int i = 0; i < GetSize(remap_wire); i++) + output_bits.insert({wire, i}); + } } std::map cell_stats; @@ -700,36 +706,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - pool output_bits; - std::vector connections; - // Stitch in mapped_mod's inputs/outputs into module - for (auto &it : mapped_mod->wires_) { - RTLIL::Wire *w = it.second; - if (!w->port_input && !w->port_output) - continue; - RTLIL::Wire *wire = module->wire(w->name); - RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); - if (w->port_input) { - RTLIL::SigSig conn; - log_assert(GetSize(wire) >= GetSize(remap_wire)); - conn.first = remap_wire; - conn.second = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); - in_wires++; - connections.emplace_back(std::move(conn)); - printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), wire->name.c_str()); - } - else if (w->port_output) { - RTLIL::SigSig conn; - log_assert(GetSize(wire) >= GetSize(remap_wire)); - conn.first = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); - conn.second = remap_wire; - for (int i = 0; i < GetSize(remap_wire); i++) - output_bits.insert({wire, i}); - printf("OUTPUT: assign %s = %s\n", wire->name.c_str(), remap_wire->name.c_str()); - connections.emplace_back(std::move(conn)); - } - else log_abort(); - } // Go through all cell output connections, // and for those output ports driving wires // also driven by mapped_mod, disconnect them @@ -750,8 +726,35 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (output_bits.count(signal.as_bit())) signal = RTLIL::State::Sx; } - for (const auto &c : connections) - module->connect(c); + + // Stitch in mapped_mod's inputs/outputs into module + for (auto &it : mapped_mod->wires_) { + RTLIL::Wire *w = it.second; + if (!w->port_input && !w->port_output) + continue; + RTLIL::Wire *wire = module->wire(w->name); + RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); + if (w->port_input) { + RTLIL::SigSig conn; + log_assert(GetSize(wire) >= GetSize(remap_wire)); + conn.first = remap_wire; + conn.second = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + in_wires++; + module->connect(conn); + printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), wire->name.c_str()); + } + else if (w->port_output) { + RTLIL::SigSig conn; + log_assert(GetSize(wire) >= GetSize(remap_wire)); + conn.first = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + conn.second = remap_wire; + for (int i = 0; i < GetSize(remap_wire); i++) + output_bits.insert({wire, i}); + printf("OUTPUT: assign %s = %s\n", wire->name.c_str(), remap_wire->name.c_str()); + module->connect(conn); + } + else log_abort(); + } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); From 486a2704156c51e1331e69cd5160965a1ef73506 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 15:22:18 -0800 Subject: [PATCH 026/514] Fixes needed for DFF circuits --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 433f1cdd6..27e156a98 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } continue; } @@ -220,8 +220,7 @@ struct XAigerWriter } else if (cell->output(c.first)) { SigBit O = sigmap(b); - if (!w->port_output) - ci_bits.insert(O); + ci_bits.insert(O); undriven_bits.erase(O); } else log_abort(); @@ -525,7 +524,7 @@ struct XAigerWriter input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { + if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } From f8d01345980a212a340087b6d9c0a8992f5b169c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 15:23:26 -0800 Subject: [PATCH 027/514] Move lookup inside if --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b32facc48..492911177 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -455,9 +455,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx; design->select(module, remap_wire); - RTLIL::Wire *wire = module->wire(w->name); if (w->port_output) { - for (int i = 0; i < GetSize(remap_wire); i++) + RTLIL::Wire *wire = module->wire(w->name); + for (int i = 0; i < GetSize(wire); i++) output_bits.insert({wire, i}); } } From 7523c8778041a2f2109b3c7f2b00f69b23b186ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:44:11 -0800 Subject: [PATCH 028/514] read_aiger() to cope with constant outputs, mixed wideports, do cleaning --- frontends/aiger/aigerparse.cc | 138 ++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a962ff6af..ce421a9be 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -112,8 +112,91 @@ void AigerReader::parse_aiger() std::getline(f, line); // Ignore up to start of next line } + dict wideports_cache; + + if (!map_filename.empty()) { + std::ifstream mf(map_filename); + std::string type, symbol; + int variable, index; + while (mf >> type >> variable >> index >> symbol) { + RTLIL::IdString escaped_symbol = RTLIL::escape_id(symbol); + if (type == "input") { + log_assert(static_cast(variable) < inputs.size()); + RTLIL::Wire* wire = inputs[variable]; + log_assert(wire); + log_assert(wire->port_input); + + if (index == 0) + module->rename(wire, RTLIL::escape_id(symbol)); + else if (index > 0) { + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + } + else if (type == "output") { + log_assert(static_cast(variable) < outputs.size()); + RTLIL::Wire* wire = outputs[variable]; + log_assert(wire); + log_assert(wire->port_output); + + if (index == 0) + module->rename(wire, RTLIL::escape_id(symbol)); + else if (index > 0) { + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + } + else + log_error("Symbol type '%s' not recognised.\n", type.c_str()); + } + } + + for (auto &wp : wideports_cache) { + auto name = wp.first; + int width = wp.second + 1; + + RTLIL::Wire *wire = module->wire(name); + if (wire) + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + + // Do not make ports with a mix of input/output into + // wide ports + bool port_input = false, port_output = false; + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + port_input = port_input || other_wire->port_input; + port_output = port_output || other_wire->port_output; + } + } + if ((port_input && port_output) || (!port_input && !port_output)) + continue; + + wire = module->addWire(name, width); + wire->port_input = port_input; + wire->port_output = port_output; + + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + other_wire->port_input = false; + other_wire->port_output = false; + if (wire->port_input) + module->connect(other_wire, SigSpec(wire, i)); + else + module->connect(SigSpec(wire, i), other_wire); + } + } + } + module->fixup_ports(); design->add(module); + + Pass::call(design, "clean"); } static uint32_t parse_xaiger_literal(std::istream &f) @@ -308,16 +391,29 @@ void AigerReader::parse_xaiger() RTLIL::Wire *wire = module->wire(name); if (wire) module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + + // Do not make ports with a mix of input/output into + // wide ports + bool port_input = false, port_output = false; + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + port_input = port_input || other_wire->port_input; + port_output = port_output || other_wire->port_output; + } + } + if ((port_input && port_output) || (!port_input && !port_output)) + continue; + wire = module->addWire(name, width); - wire->port_input = wire->port_output = false; + wire->port_input = port_input; + wire->port_output = port_output; for (int i = 0; i < width; i++) { RTLIL::IdString other_name = name.str() + stringf("[%d]", i); RTLIL::Wire *other_wire = module->wire(other_name); if (other_wire) { - log_assert((other_wire->port_input && !other_wire->port_output) || (other_wire->port_output && !other_wire->port_input)); - wire->port_input = other_wire->port_input; - wire->port_output = other_wire->port_output; other_wire->port_input = false; other_wire->port_output = false; if (wire->port_input) @@ -397,9 +493,22 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); + RTLIL::Wire *wire; + if (l1 == 0 || l1 == 1) { + wire = module->addWire(stringf("\\o%zu", outputs.size())); + if (l1 == 0) + module->connect(wire, RTLIL::State::S0); + else if (l1 == 1) + module->connect(wire, RTLIL::State::S1); + else + log_abort(); + } + else { + log_debug("%d is an output\n", l1); + wire = createWireIfNotExists(module, l1); + } wire->port_output = true; + log_assert(!wire->port_input); outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line @@ -432,6 +541,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); } + std::getline(f, line); } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) @@ -502,8 +612,20 @@ void AigerReader::parse_aiger_binary() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); + RTLIL::Wire *wire; + if (l1 == 0 || l1 == 1) { + wire = module->addWire(stringf("\\o%zu", outputs.size())); + if (l1 == 0) + module->connect(wire, RTLIL::State::S0); + else if (l1 == 1) + module->connect(wire, RTLIL::State::S1); + else + log_abort(); + } + else { + log_debug("%d is an output\n", l1); + wire = createWireIfNotExists(module, l1); + } wire->port_output = true; log_assert(!wire->port_input); outputs.push_back(wire); From 2c1655ae9440c470a62ab7e493024a94f5d054ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:46:25 -0800 Subject: [PATCH 029/514] write_aiger() to perform CI/CO post-processing and fix symbols --- backends/aiger/xaiger.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 27e156a98..3d0968cad 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -216,12 +216,10 @@ struct XAigerWriter SigBit I = sigmap(b); if (!w->port_input) co_bits.insert(I); - unused_bits.erase(I); } else if (cell->output(c.first)) { SigBit O = sigmap(b); ci_bits.insert(O); - undriven_bits.erase(O); } else log_abort(); if (!type_map.count(cell->type)) @@ -230,6 +228,19 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + // Do some CI/CO post-processing: + // Erase all COs that are undriven + for (auto bit : undriven_bits) + co_bits.erase(bit); + // Erase all CIs that are also COs or POs + for (auto bit : co_bits) + ci_bits.erase(bit); + for (auto bit : output_bits) + ci_bits.erase(bit); + // CIs cannot be undriven + for (auto bit : ci_bits) + undriven_bits.erase(bit); + for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -255,7 +266,6 @@ struct XAigerWriter for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; - co_bits.erase(bit); } for (auto bit : input_bits) { @@ -429,8 +439,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->name[0] == '$') - continue; + //if (wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -443,7 +453,7 @@ struct XAigerWriter continue; } - if (wire->port_input) { + if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -452,7 +462,7 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (wire->port_output) { + if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { int o = ordered_outputs.at(SigSpec(wire, i)); if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); From 0c409e6d8cd51360b3099a725fdad6174a2dbb66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:48:33 -0800 Subject: [PATCH 030/514] Tidy up write_xaiger --- backends/aiger/xaiger.cc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d0968cad..c0bd9e921 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } @@ -151,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } } } @@ -168,8 +168,6 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -191,8 +189,6 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -229,9 +225,11 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all COs that are undriven - for (auto bit : undriven_bits) + // Erase all POs and COs that are undriven + for (auto bit : undriven_bits) { co_bits.erase(bit); + output_bits.erase(bit); + } // Erase all CIs that are also COs or POs for (auto bit : co_bits) ci_bits.erase(bit); From d4545d415bf02f098607ef70f0e84fe5685a4139 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:53:06 -0800 Subject: [PATCH 031/514] abc9 to cope with non-wideports, count cells properly --- passes/techmap/abc9.cc | 65 +++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 492911177..5af1f1110 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -216,6 +216,29 @@ struct abc_output_filter } }; +static std::pair 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::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1)); + +failed: + return std::pair(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 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, @@ -323,7 +346,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); - abc_script += stringf("; &ps; &write -v %s/output.xaig", tempdir_name.c_str()); + abc_script += stringf("; &ps; &write %s/output.xaig", tempdir_name.c_str()); abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) @@ -346,7 +369,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - Pass::call(design, stringf("aigmap; write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("aigmap; clean; write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); log_push(); @@ -457,8 +480,17 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri design->select(module, remap_wire); if (w->port_output) { RTLIL::Wire *wire = module->wire(w->name); - for (int i = 0; i < GetSize(wire); i++) + if (wire) { + for (int i = 0; i < GetSize(wire); i++) + output_bits.insert({wire, i}); + } + else { + auto r = wideports_split(w->name.str()); + wire = module->wire(r.first); + log_assert(wire); + int i = r.second; output_bits.insert({wire, i}); + } } } @@ -607,8 +639,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; } } - - cell_stats[RTLIL::unescape_id(c->type)]++; + else + cell_stats[RTLIL::unescape_id(c->type)]++; if (c->type == "\\_const0_" || c->type == "\\_const1_") { RTLIL::SigSig conn; @@ -734,23 +766,34 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; RTLIL::Wire *wire = module->wire(w->name); RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); + RTLIL::SigSpec signal; + if (wire) { + signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + } + else { + auto r = wideports_split(w->name.str()); + wire = module->wire(r.first); + log_assert(wire); + int i = r.second; + printf("%s %s %d\n", w->name.c_str(), wire->name.c_str(), i); + signal = RTLIL::SigSpec(wire, i); + } + log_assert(GetSize(signal) >= GetSize(remap_wire)); + if (w->port_input) { RTLIL::SigSig conn; - log_assert(GetSize(wire) >= GetSize(remap_wire)); conn.first = remap_wire; - conn.second = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + conn.second = signal; in_wires++; module->connect(conn); printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), wire->name.c_str()); } else if (w->port_output) { RTLIL::SigSig conn; - log_assert(GetSize(wire) >= GetSize(remap_wire)); - conn.first = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); + conn.first = signal; conn.second = remap_wire; - for (int i = 0; i < GetSize(remap_wire); i++) - output_bits.insert({wire, i}); printf("OUTPUT: assign %s = %s\n", wire->name.c_str(), remap_wire->name.c_str()); + out_wires++; module->connect(conn); } else log_abort(); From 8f36013fac34e7cf7b79456f7f8bec8ad6292c99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:58:25 -0800 Subject: [PATCH 032/514] read_xaiger() to use f.read() not readsome() --- frontends/aiger/aigerparse.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ce421a9be..8493264f5 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -202,7 +202,8 @@ void AigerReader::parse_aiger() static uint32_t parse_xaiger_literal(std::istream &f) { boost::endian::big_uint32_buf_t l; - if (f.readsome(reinterpret_cast(&l), sizeof(l)) != sizeof(l)) + f.read(reinterpret_cast(&l), sizeof(l)); + if (f.gcount() != sizeof(l)) log_error("Offset %ld: unable to read literal!\n", boost::lexical_cast(f.tellg())); return l.value(); } From e7c7ab8fc06b3accc7f6d98313ec09e54a605124 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 13:45:17 -0800 Subject: [PATCH 033/514] expose command to not skip 'internal' wires beginning with '$' --- passes/sat/expose.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 809345486..3add9a9eb 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -42,7 +42,7 @@ struct dff_map_bit_info_t { bool consider_wire(RTLIL::Wire *wire, std::map &dff_dq_map) { - if (wire->name[0] == '$' || dff_dq_map.count(wire->name)) + if (/*wire->name[0] == '$' ||*/ dff_dq_map.count(wire->name)) return false; if (wire->port_input) return false; From 1a25ec4baa705c6e809f6e8616d54da14f51bc22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 13:45:51 -0800 Subject: [PATCH 034/514] read_aiger to disable log_debug --- frontends/aiger/aigerparse.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8493264f5..84fe74f56 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -33,6 +33,7 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log +#define log_debug(...) ; AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports) @@ -627,8 +628,8 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); wire = createWireIfNotExists(module, l1); } - wire->port_output = true; log_assert(!wire->port_input); + wire->port_output = true; outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line From d8c4d4e6c77ebce04c3e0ea43a74d37389fab103 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 13:47:38 -0800 Subject: [PATCH 035/514] abc9 to handle comb loops, cope with constant outputs, disconnect using new wire --- passes/techmap/abc9.cc | 71 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5af1f1110..2cc79fa95 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -91,6 +91,44 @@ std::string remap_name(RTLIL::IdString abc_name) return sstr.str(); } +void handle_loops(RTLIL::Design *design, RTLIL::Module *module) +{ + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + Pass::call(design, "scc -set_attr abc_scc_id {}"); + + sel = RTLIL::Selection(false); + + // For every unique SCC found, (arbitrarily) find the first + // cell in the component, and select (and mark) all its output + // wires + pool ids_seen; + for (auto cell : module->cells()) { + auto it = cell->attributes.find("\\abc_scc_id"); + if (it != cell->attributes.end()) { + auto r = ids_seen.insert(it->second); + if (r.second) { + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + if (cell->output(c.first)) { + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + w->set_bool_attribute("\\abc_scc_break"); + sel.select(module, w); + } + } + } + cell->attributes.erase(it); + } + } + + // Then cut those selected wires to expose them as new PO/PI + Pass::call(design, "expose -cut -sep .abc"); + + design->selection_stack.pop_back(); +} + std::string add_echos_to_abc_cmd(std::string str) { std::string new_str, token; @@ -369,7 +407,31 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - Pass::call(design, stringf("aigmap; clean; write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, "aigmap; clean;"); + + handle_loops(design, module); + + Pass::call(design, "write_verilog -norename -noexpr input.v"); + Pass::call(design, stringf("write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -ascii -symbols %s/input.xaag; read_aiger -wideports -map %s/input.symbols %s/input.xaag; write_verilog -norename -noexpr input.v", tempdir_name.c_str(), 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); + } + } + module->fixup_ports(); log_push(); @@ -703,7 +765,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!conn.second.is_fully_const()) { auto chunks = conn.second.chunks(); for (auto &c : chunks) - c.wire = module->wires_[remap_name(c.wire->name)]; + if (c.wire) + c.wire = module->wires_[remap_name(c.wire->name)]; conn.second = std::move(chunks); } module->connect(conn); @@ -748,7 +811,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri auto &signal = it.second; if (!signal.is_bit()) continue; if (output_bits.count(signal.as_bit())) - signal = RTLIL::State::Sx; + signal = module->addWire(NEW_ID); } } // Do the same for module connections @@ -756,7 +819,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri auto &signal = it.first; if (!signal.is_bit()) continue; if (output_bits.count(signal.as_bit())) - signal = RTLIL::State::Sx; + signal = module->addWire(NEW_ID); } // Stitch in mapped_mod's inputs/outputs into module From b9a305b85d17ce61880ee057e19e5ceafd7a6c05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 20:08:59 -0800 Subject: [PATCH 036/514] write_aiger -O to write dummy output as __dummy_o__ --- backends/aiger/xaiger.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c0bd9e921..25e03fa5f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -502,7 +502,7 @@ struct XAigerWriter f << stringf("c\nGenerated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map) + void write_map(std::ostream &f, bool verbose_map, bool omode) { dict input_lines; dict init_lines; @@ -564,6 +564,9 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + if (omode && output_bits.empty()) { + f << "output 0 0 __dummy_o__\n"; + } latch_lines.sort(); for (auto &it : latch_lines) @@ -675,7 +678,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, verbose_map, omode); } } } XAigerBackend; From f853b2f3c15f629ea22a9427e5524bdeebddfb8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 20:09:40 -0800 Subject: [PATCH 037/514] abc9 to write_aiger with -O option, and ignore dummy outputs --- passes/techmap/abc9.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2cc79fa95..f684ad8de 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -412,8 +412,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design, module); Pass::call(design, "write_verilog -norename -noexpr input.v"); - Pass::call(design, stringf("write_xaiger -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); - Pass::call(design, stringf("write_xaiger -ascii -symbols %s/input.xaag; read_aiger -wideports -map %s/input.symbols %s/input.xaag; write_verilog -norename -noexpr input.v", tempdir_name.c_str(), tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -ascii -symbols %s/input.xaag; read_aiger -wideports %s/input.xaag; write_verilog -norename -noexpr input.v", tempdir_name.c_str(), tempdir_name.c_str())); // Now 'unexpose' those wires by undoing // the expose operation -- remove them from PO/PI @@ -547,6 +547,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri output_bits.insert({wire, i}); } else { + if (w->name.str() == "\\__dummy_o__") { + log("Don't call ABC as there is nothing to map.\n"); + goto cleanup; + } + auto r = wideports_split(w->name.str()); wire = module->wire(r.first); log_assert(wire); @@ -875,6 +880,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri Pass::call(design, "clean"); +cleanup: if (cleanup) { log("Removing temp directory.\n"); From 6a57de90137df146529d84a04f70269382df8795 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:00:39 -0800 Subject: [PATCH 038/514] write_xaiger to support non-bit cell connections, and cope with COs for -O --- backends/aiger/xaiger.cc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25e03fa5f..456f3f899 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -206,18 +206,20 @@ struct XAigerWriter for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + ci_bits.insert(O); + } + else log_abort(); } - else if (cell->output(c.first)) { - SigBit O = sigmap(b); - ci_bits.insert(O); - } - else log_abort(); if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } @@ -343,7 +345,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -564,7 +566,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { f << "output 0 0 __dummy_o__\n"; } From 76c35f80f4d2ad3b2e686186c9febc2872f5c9ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:09:48 -0800 Subject: [PATCH 039/514] Cleanup --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 456f3f899..ae296d395 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -566,9 +566,8 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; - } latch_lines.sort(); for (auto &it : latch_lines) From f60cd4ff9b158a5d8ec51bd52b14f117214c087e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:53:03 -0800 Subject: [PATCH 040/514] read_aiger to ignore output = input of same wire; also create new output for different wire --- frontends/aiger/aigerparse.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 84fe74f56..dffbd3590 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -139,6 +139,9 @@ void AigerReader::parse_aiger() log_assert(static_cast(variable) < outputs.size()); RTLIL::Wire* wire = outputs[variable]; log_assert(wire); + // Ignore direct output -> input connections + if (!wire->port_output) + continue; log_assert(wire->port_output); if (index == 0) @@ -371,6 +374,9 @@ void AigerReader::parse_xaiger() log_assert(static_cast(variable) < outputs.size()); RTLIL::Wire* wire = outputs[variable]; log_assert(wire); + // Ignore direct output -> input connections + if (!wire->port_output) + continue; log_assert(wire->port_output); if (index == 0) @@ -509,8 +515,12 @@ void AigerReader::parse_aiger_ascii() log_debug("%d is an output\n", l1); wire = createWireIfNotExists(module, l1); } + if (wire->port_input) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; + } wire->port_output = true; - log_assert(!wire->port_input); outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line @@ -628,7 +638,11 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); wire = createWireIfNotExists(module, l1); } - log_assert(!wire->port_input); + if (wire->port_input) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; + } wire->port_output = true; outputs.push_back(wire); } From 30f1204721ed592256ddde04f22dd40888b9e27c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 22:22:17 -0800 Subject: [PATCH 041/514] Cleanup --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae296d395..d4686736d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -521,7 +521,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) continue; int a = aig_map.at(sig[i]); @@ -529,13 +529,14 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { + RTLIL::SigBit b(wire, i); + if (wire->port_input || ci_bits.count(b)) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { - int o = ordered_outputs.at(sig[i]); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } From 82459c16c482ad9115c742d726fd1f46527a3bab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 22:22:29 -0800 Subject: [PATCH 042/514] In read_xaiger, do not construct ConstEval for every LUT --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index dffbd3590..8014dd303 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -290,6 +290,7 @@ void AigerReader::parse_xaiger() uint32_t lutNum = parse_xaiger_literal(f); uint32_t lutSize = parse_xaiger_literal(f); log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); + ConstEval ce(module); for (unsigned i = 0; i < lutNum; ++i) { uint32_t rootNodeID = parse_xaiger_literal(f); uint32_t cutLeavesM = parse_xaiger_literal(f); @@ -305,7 +306,6 @@ void AigerReader::parse_xaiger() input_sig.append(wire); } RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); - ConstEval ce(module); for (int j = 0; j < (1 << cutLeavesM); ++j) { ce.push(); ce.set(input_sig, RTLIL::Const{j, static_cast(cutLeavesM)}); From 45d49d5d14b64cce77e667e99c2579237638bedf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 22:25:22 -0800 Subject: [PATCH 043/514] Get rid of debugging stuff in abc9 --- passes/techmap/abc9.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f684ad8de..5c10278a9 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -411,9 +411,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design, module); - Pass::call(design, "write_verilog -norename -noexpr input.v"); Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); - Pass::call(design, stringf("write_xaiger -ascii -symbols %s/input.xaag; read_aiger -wideports %s/input.xaag; write_verilog -norename -noexpr input.v", tempdir_name.c_str(), tempdir_name.c_str())); // Now 'unexpose' those wires by undoing // the expose operation -- remove them from PO/PI @@ -843,7 +841,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri wire = module->wire(r.first); log_assert(wire); int i = r.second; - printf("%s %s %d\n", w->name.c_str(), wire->name.c_str(), i); signal = RTLIL::SigSpec(wire, i); } log_assert(GetSize(signal) >= GetSize(remap_wire)); @@ -854,13 +851,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri conn.second = signal; in_wires++; module->connect(conn); - printf("INPUT: assign %s = %s\n", remap_wire->name.c_str(), wire->name.c_str()); } else if (w->port_output) { RTLIL::SigSig conn; conn.first = signal; conn.second = remap_wire; - printf("OUTPUT: assign %s = %s\n", wire->name.c_str(), remap_wire->name.c_str()); out_wires++; module->connect(conn); } @@ -1084,7 +1079,7 @@ struct Abc9Pass : public Pass { std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; - show_tempdir = true; cleanup = false; + show_tempdir = true; cleanup = true; vector lut_costs; markgroups = false; From 54f719f4463a12e24efeda5b45319b9ccf98ef03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 10:19:53 -0800 Subject: [PATCH 044/514] Get rid of boost dep, fix the FIXMEs for Win32? --- frontends/aiger/aigerparse.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8014dd303..ef25b318c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,14 +22,14 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf +#ifdef _WIN32 +#include +#endif #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/consteval.h" #include "aigerparse.h" -#include -#include - YOSYS_NAMESPACE_BEGIN #define log_debug log @@ -205,11 +205,15 @@ void AigerReader::parse_aiger() static uint32_t parse_xaiger_literal(std::istream &f) { - boost::endian::big_uint32_buf_t l; + uint32_t l; f.read(reinterpret_cast(&l), sizeof(l)); if (f.gcount() != sizeof(l)) - log_error("Offset %ld: unable to read literal!\n", boost::lexical_cast(f.tellg())); - return l.value(); + log_error("Offset %ld: unable to read literal!\n", static_cast(f.tellg())); +#ifdef _WIN32 + return _byteswap_ulong(l); +#else + return __builtin_bswap32(l); +#endif } static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) @@ -690,13 +694,7 @@ struct AigerFrontend : public Frontend { log("Load module from an AIGER file into the current design.\n"); log("\n"); log(" -module_name \n"); - log(" Name of module to be created (default: )" -#ifdef _WIN32 - "top" // FIXME -#else - "" -#endif - ")\n"); + log(" Name of module to be created (default: )\n"); log("\n"); log(" -clk_name \n"); log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); @@ -744,7 +742,9 @@ struct AigerFrontend : public Frontend { if (module_name.empty()) { #ifdef _WIN32 - module_name = "top"; // FIXME: basename equivalent on Win32? + char fname[_MAX_FNAME]; + _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */) + module_name = fname; #else module_name = RTLIL::escape_id(basename(filename.c_str())); #endif From 0b1fc46ae380302f8082f49d1517645008b041df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 10:24:55 -0800 Subject: [PATCH 045/514] Add comment --- frontends/aiger/aigerparse.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ef25b318c..a9c763339 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -32,7 +32,7 @@ YOSYS_NAMESPACE_BEGIN -#define log_debug log +//#define log_debug log #define log_debug(...) ; AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) @@ -209,6 +209,7 @@ static uint32_t parse_xaiger_literal(std::istream &f) f.read(reinterpret_cast(&l), sizeof(l)); if (f.gcount() != sizeof(l)) log_error("Offset %ld: unable to read literal!\n", static_cast(f.tellg())); + // TODO: Don't assume we're on little endian #ifdef _WIN32 return _byteswap_ulong(l); #else From e79df5e70e8f0a34c29c21e28a80413d01f4e1c9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 12:27:50 -0800 Subject: [PATCH 046/514] read_aiger to create sane $lut names, and rename when renaming driving wire --- frontends/aiger/aigerparse.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a9c763339..a1bdcbfff 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -322,7 +322,7 @@ void AigerReader::parse_xaiger() RTLIL::Cell *output_cell = module->cell(stringf("\\n%d_and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - module->addLut(NEW_ID, input_sig, output_sig, std::move(lut_mask)); + module->addLut(stringf("\\n%d_lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'n') { @@ -346,6 +346,10 @@ void AigerReader::parse_xaiger() else log_abort(); module->rename(wire, stringf("\\%s", s.c_str())); + + RTLIL::Cell* driver = module->cell(stringf("%s_lut", wire->name.c_str())); + module->rename(driver, stringf("%s_lut", wire->name.c_str())); + std::getline(f, line); // Ignore up to start of next line ++line_count; } @@ -384,6 +388,8 @@ void AigerReader::parse_xaiger() continue; log_assert(wire->port_output); + RTLIL::Cell* driver = module->cell(stringf("%s_lut", wire->name.c_str())); + if (index == 0) module->rename(wire, RTLIL::escape_id(symbol)); else if (index > 0) { @@ -391,6 +397,9 @@ void AigerReader::parse_xaiger() if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); } + + if (driver) + module->rename(driver, stringf("%s_lut", wire->name.c_str())); } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); @@ -440,7 +449,7 @@ void AigerReader::parse_xaiger() module->fixup_ports(); design->add(module); - Pass::call(design, "clean"); + Pass::call(design, "clean -purge"); } void AigerReader::parse_aiger_ascii() From 8158bc3f9930634462166aac72da96d9c9c1a5e0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 12:30:20 -0800 Subject: [PATCH 047/514] abc9 to replace $_NOT_ with $lut --- passes/techmap/abc9.cc | 43 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5c10278a9..f63b69acd 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -579,11 +579,46 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->connect(conn); continue; } - if (c->type == "\\NOT") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_"); + if (c->type == "$_NOT_") { + RTLIL::Cell *cell; + RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); + RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); + if (!lut_costs.empty()) { + // ABC can return NOT gates that drive POs + if (a_bit.wire->port_input) { + // If it's a NOT gate that comes from a primary input directly + // then implement it using a LUT + cell = module->addLut(remap_name(stringf("%s_lut", c->name.c_str())), + RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + 1); + } + else { + // Otherwise, clone the driving LUT to guarantee that we + // won't increase the max logic depth + // (TODO: Optimise by not cloning unless will increase depth) + RTLIL::Cell* driver = mapped_mod->cell(stringf("%s_lut", a_bit.wire->name.c_str())); + log_assert(driver); + auto driver_a = driver->getPort("\\A").chunks(); + for (auto &chunk : driver_a) + chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + RTLIL::Const driver_lut = driver->getParam("\\LUT"); + for (auto &b : driver_lut.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + cell = module->addLut(remap_name(stringf("%s_lut", c->name.c_str())), + driver_a, + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + driver_lut); + } + } + else { + cell = module->addCell(remap_name(c->name), "$_NOT_"); + cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); + cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); + } if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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; } From d304882cba32cc9eb9be163fe6f24211bd39594a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 15:14:08 -0800 Subject: [PATCH 048/514] read_aiger to cope with non-unique POs --- frontends/aiger/aigerparse.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a1bdcbfff..941899316 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -650,12 +650,19 @@ void AigerReader::parse_aiger_binary() } else { log_debug("%d is an output\n", l1); - wire = createWireIfNotExists(module, l1); - } - if (wire->port_input) { - RTLIL::Wire *new_wire = module->addWire(NEW_ID); - module->connect(new_wire, wire); - wire = new_wire; + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else { + if ((wire->port_input || wire->port_output)) { + RTLIL::Wire *new_wire = module->addWire(stringf("\\o%zu", outputs.size())); + module->connect(new_wire, wire); + wire = new_wire; + } + } } wire->port_output = true; outputs.push_back(wire); From 7b026c4bc316a44f2722cd4ddc96b4da1d1458b6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 15:15:50 -0800 Subject: [PATCH 049/514] Same for ascii AIGERs too --- frontends/aiger/aigerparse.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 941899316..2219eedb1 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -527,12 +527,19 @@ void AigerReader::parse_aiger_ascii() } else { log_debug("%d is an output\n", l1); - wire = createWireIfNotExists(module, l1); - } - if (wire->port_input) { - RTLIL::Wire *new_wire = module->addWire(NEW_ID); - module->connect(new_wire, wire); - wire = new_wire; + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else { + if ((wire->port_input || wire->port_output)) { + RTLIL::Wire *new_wire = module->addWire(stringf("\\o%zu", outputs.size())); + module->connect(new_wire, wire); + wire = new_wire; + } + } } wire->port_output = true; outputs.push_back(wire); From ef1a1402bcecd5cf3edc41b9842ab5500e52a95e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 15:25:03 -0800 Subject: [PATCH 050/514] Add a quick abc9 test --- tests/techmap/abc9/abc9.v | 6 ++++++ tests/techmap/abc9/abc9_runtest.sh | 5 +++++ tests/techmap/abc9/run-test.sh | 10 ++++++++++ tests/techmap/run-test.sh | 8 ++++++++ 4 files changed, 29 insertions(+) create mode 100644 tests/techmap/abc9/abc9.v create mode 100644 tests/techmap/abc9/abc9_runtest.sh create mode 100755 tests/techmap/abc9/run-test.sh diff --git a/tests/techmap/abc9/abc9.v b/tests/techmap/abc9/abc9.v new file mode 100644 index 000000000..2d9aea366 --- /dev/null +++ b/tests/techmap/abc9/abc9.v @@ -0,0 +1,6 @@ +module top(input [1:0] a, output [1:0] b, output c, output d, output e); +assign b = a; +assign c = ^a; +assign d = ~c; +assign e = d; +endmodule diff --git a/tests/techmap/abc9/abc9_runtest.sh b/tests/techmap/abc9/abc9_runtest.sh new file mode 100644 index 000000000..2deaad719 --- /dev/null +++ b/tests/techmap/abc9/abc9_runtest.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -ev + +../../../yosys -p 'abc9 -lut 4; check; select -assert-count 2 t:$lut; select -assert-none c:* t:$lut %n %i' abc9.v diff --git a/tests/techmap/abc9/run-test.sh b/tests/techmap/abc9/run-test.sh new file mode 100755 index 000000000..e2fc11e52 --- /dev/null +++ b/tests/techmap/abc9/run-test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e +for x in *_runtest.sh; do + echo "Running $x.." + if ! bash $x &> ${x%.sh}.log; then + tail ${x%.sh}.log + echo ERROR + exit 1 + fi +done diff --git a/tests/techmap/run-test.sh b/tests/techmap/run-test.sh index e2fc11e52..129451e08 100755 --- a/tests/techmap/run-test.sh +++ b/tests/techmap/run-test.sh @@ -8,3 +8,11 @@ for x in *_runtest.sh; do exit 1 fi done + +for d in */; do + if [ -x $d/run-test.sh ]; then + cd $d + bash run-test.sh + cd .. + fi +done From 62e5ff9ba8ce9711317f97efdb9810491aaa4f06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 16:06:03 -0800 Subject: [PATCH 051/514] abc9 to cope with indexed wires when creating $lut from $_NOT_ --- passes/techmap/abc9.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f63b69acd..e85cf48e1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -597,7 +597,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // Otherwise, clone the driving LUT to guarantee that we // won't increase the max logic depth // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::Cell* driver = mapped_mod->cell(stringf("%s_lut", a_bit.wire->name.c_str())); + RTLIL::IdString driver_name; + if (GetSize(a_bit.wire) == 1) + driver_name = stringf("%s_lut", a_bit.wire->name.c_str()); + else + driver_name = stringf("%s[%d]_lut", a_bit.wire->name.c_str(), a_bit.offset); + RTLIL::Cell* driver = mapped_mod->cell(driver_name); log_assert(driver); auto driver_a = driver->getPort("\\A").chunks(); for (auto &chunk : driver_a) From 45ddd9066e03ce7b076bcc634c6231c6b3a5ed3d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 11:08:49 -0800 Subject: [PATCH 052/514] synth to take -abc9 argument --- techlibs/common/synth.cc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index ccfa76e02..349605f8c 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -75,13 +75,16 @@ struct SynthPass : public ScriptPass log(" from label is synonymous to 'begin', and empty to label is\n"); log(" synonymous to the end of the command list.\n"); log("\n"); + log(" -abc9\n"); + log(" use abc9 instead of abc\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } - string top_module, fsm_opts, memory_opts; + string top_module, fsm_opts, memory_opts, abc; bool autotop, flatten, noalumacc, nofsm, noabc, noshare; int lut; @@ -98,6 +101,7 @@ struct SynthPass : public ScriptPass nofsm = false; noabc = false; noshare = false; + abc = "abc"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -159,6 +163,10 @@ struct SynthPass : public ScriptPass noshare = true; continue; } + if (args[argidx] == "-abc9") { + abc = "abc9"; + continue; + } break; } extra_args(args, argidx, design); @@ -239,15 +247,15 @@ struct SynthPass : public ScriptPass #ifdef YOSYS_ENABLE_ABC if (help_mode) { - run("abc -fast", " (unless -noabc, unless -lut)"); - run("abc -fast -lut k", "(unless -noabc, if -lut)"); + run(abc + " -fast", " (unless -noabc, unless -lut)"); + run(abc + " -fast -lut k", "(unless -noabc, if -lut)"); } else { if (lut) - run(stringf("abc -fast -lut %d", lut)); + run(stringf("%s -fast -lut %d", abc.c_str(), lut)); else - run("abc -fast"); + run(abc + " -fast"); } run("opt -fast", " (unless -noabc)"); #endif From ef60ca171743292e88457684d53d632c680210e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 11:09:13 -0800 Subject: [PATCH 053/514] write_xaiger to not write latches, CO/PO fixes --- backends/aiger/xaiger.cc | 43 ++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d4686736d..d125335f9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -174,15 +174,15 @@ struct XAigerWriter continue; } - if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - { - SigBit D = sigmap(cell->getPort("\\D").as_bit()); - SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - ff_map[Q] = D; - continue; - } + //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + //{ + // SigBit D = sigmap(cell->getPort("\\D").as_bit()); + // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + // unused_bits.erase(D); + // undriven_bits.erase(Q); + // ff_map[Q] = D; + // continue; + //} if (cell->type == "$_AND_") { @@ -240,6 +240,9 @@ struct XAigerWriter // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); + // POs override COs + for (auto bit : output_bits) + co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -521,29 +524,25 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) - continue; - - int a = aig_map.at(sig[i]); - - if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - RTLIL::SigBit b(wire, i); if (wire->port_input || ci_bits.count(b)) { + int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + continue; } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (ordered_latches.count(sig[i])) { @@ -552,6 +551,15 @@ struct XAigerWriter latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); else latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + 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)); } } } @@ -567,6 +575,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; From 83b66861e9c669f643e096030d0b165ca45ab38c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 11:22:56 -0800 Subject: [PATCH 054/514] read_aiger to name wires with internal name, less likely to clash --- frontends/aiger/aigerparse.cc | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 2219eedb1..4611d9fc1 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -221,14 +221,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera { const unsigned variable = literal >> 1; const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; log_debug("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); wire->port_input = wire->port_output = false; if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::IdString wire_inv_name(stringf("\\__%d__", variable)); RTLIL::Wire *wire_inv = module->wire(wire_inv_name); if (wire_inv) { if (module->cell(wire_inv_name)) return wire; @@ -240,7 +240,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? + module->addNotGate(stringf("\\__%d__not", variable), wire_inv, wire); // FIXME: is "not" the right suffix? return wire; } @@ -300,13 +300,13 @@ void AigerReader::parse_xaiger() uint32_t rootNodeID = parse_xaiger_literal(f); uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); - RTLIL::Wire *output_sig = module->wire(stringf("\\n%d", rootNodeID)); + RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); uint32_t nodeID; RTLIL::SigSpec input_sig; for (unsigned j = 0; j < cutLeavesM; ++j) { nodeID = parse_xaiger_literal(f); log_debug("\t%u\n", nodeID); - RTLIL::Wire *wire = module->wire(stringf("\\n%d", nodeID)); + RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); log_assert(wire); input_sig.append(wire); } @@ -319,10 +319,10 @@ void AigerReader::parse_xaiger() lut_mask[j] = o.as_const()[0]; ce.pop(); } - RTLIL::Cell *output_cell = module->cell(stringf("\\n%d_and", rootNodeID)); + RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - module->addLut(stringf("\\n%d_lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); + module->addLut(stringf("\\__%d__lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'n') { @@ -383,9 +383,6 @@ void AigerReader::parse_xaiger() log_assert(static_cast(variable) < outputs.size()); RTLIL::Wire* wire = outputs[variable]; log_assert(wire); - // Ignore direct output -> input connections - if (!wire->port_output) - continue; log_assert(wire->port_output); RTLIL::Cell* driver = module->cell(stringf("%s_lut", wire->name.c_str())); @@ -517,7 +514,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *wire; if (l1 == 0 || l1 == 1) { - wire = module->addWire(stringf("\\o%zu", outputs.size())); + wire = module->addWire(NEW_ID); if (l1 == 0) module->connect(wire, RTLIL::State::S0); else if (l1 == 1) @@ -529,13 +526,13 @@ void AigerReader::parse_aiger_ascii() log_debug("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? wire = module->wire(wire_name); if (!wire) wire = createWireIfNotExists(module, l1); else { if ((wire->port_input || wire->port_output)) { - RTLIL::Wire *new_wire = module->addWire(stringf("\\o%zu", outputs.size())); + RTLIL::Wire *new_wire = module->addWire(NEW_ID); module->connect(new_wire, wire); wire = new_wire; } @@ -572,7 +569,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "and", i1_wire, i2_wire, o_wire); } std::getline(f, line); } @@ -647,7 +644,7 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *wire; if (l1 == 0 || l1 == 1) { - wire = module->addWire(stringf("\\o%zu", outputs.size())); + wire = module->addWire(NEW_ID); if (l1 == 0) module->connect(wire, RTLIL::State::S0); else if (l1 == 1) @@ -659,13 +656,13 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "_b" : "")); // FIXME: is "_inv" the right suffix? wire = module->wire(wire_name); if (!wire) wire = createWireIfNotExists(module, l1); else { if ((wire->port_input || wire->port_output)) { - RTLIL::Wire *new_wire = module->addWire(stringf("\\o%zu", outputs.size())); + RTLIL::Wire *new_wire = module->addWire(NEW_ID); module->connect(new_wire, wire); wire = new_wire; } @@ -703,7 +700,7 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "and", i1_wire, i2_wire, o_wire); } } From f9702a8abef5a9df94dfbfe16f2aa686c08c6b00 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 12:39:51 -0800 Subject: [PATCH 055/514] read_aiger: new naming fixes --- frontends/aiger/aigerparse.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4611d9fc1..5c862b8f0 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -347,8 +347,8 @@ void AigerReader::parse_xaiger() module->rename(wire, stringf("\\%s", s.c_str())); - RTLIL::Cell* driver = module->cell(stringf("%s_lut", wire->name.c_str())); - module->rename(driver, stringf("%s_lut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + module->rename(driver, stringf("%slut", wire->name.c_str())); std::getline(f, line); // Ignore up to start of next line ++line_count; @@ -385,7 +385,7 @@ void AigerReader::parse_xaiger() log_assert(wire); log_assert(wire->port_output); - RTLIL::Cell* driver = module->cell(stringf("%s_lut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); if (index == 0) module->rename(wire, RTLIL::escape_id(symbol)); @@ -396,7 +396,7 @@ void AigerReader::parse_xaiger() } if (driver) - module->rename(driver, stringf("%s_lut", wire->name.c_str())); + module->rename(driver, stringf("%slut", wire->name.c_str())); } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); @@ -656,7 +656,7 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "_b" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_inv" the right suffix? wire = module->wire(wire_name); if (!wire) wire = createWireIfNotExists(module, l1); From d6b317b349894d0837018dde28eb46eff55c4ce8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 12:40:17 -0800 Subject: [PATCH 056/514] abc9 to use & syntax for -fast, and name fixes --- passes/techmap/abc9.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e85cf48e1..94fbffeaf 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -37,7 +37,7 @@ #define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" #define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "strash; dretime; if" +#define ABC_FAST_COMMAND_LUT "&st; &retime; &if" #define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" #define ABC_FAST_COMMAND_DFL "strash; dretime; map" @@ -588,7 +588,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (a_bit.wire->port_input) { // If it's a NOT gate that comes from a primary input directly // then implement it using a LUT - cell = module->addLut(remap_name(stringf("%s_lut", c->name.c_str())), + cell = module->addLut(remap_name(stringf("%slut", c->name.c_str())), RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), 1); @@ -599,9 +599,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // (TODO: Optimise by not cloning unless will increase depth) RTLIL::IdString driver_name; if (GetSize(a_bit.wire) == 1) - driver_name = stringf("%s_lut", a_bit.wire->name.c_str()); + driver_name = stringf("%slut", a_bit.wire->name.c_str()); else - driver_name = stringf("%s[%d]_lut", a_bit.wire->name.c_str(), a_bit.offset); + driver_name = stringf("%s[%d]lut", a_bit.wire->name.c_str(), a_bit.offset); RTLIL::Cell* driver = mapped_mod->cell(driver_name); log_assert(driver); auto driver_a = driver->getPort("\\A").chunks(); @@ -612,7 +612,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - cell = module->addLut(remap_name(stringf("%s_lut", c->name.c_str())), + cell = module->addLut(remap_name(stringf("%slut", c->name.c_str())), driver_a, RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); From 2ca83005fbff008cf4c9e00c1b2b294312f89dc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 12:56:15 -0800 Subject: [PATCH 057/514] abc9 to cope with multiple modules --- passes/techmap/abc9.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 94fbffeaf..cc906bae7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -91,14 +91,12 @@ std::string remap_name(RTLIL::IdString abc_name) return sstr.str(); } -void handle_loops(RTLIL::Design *design, RTLIL::Module *module) +void handle_loops(RTLIL::Design *design) { - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(module); Pass::call(design, "scc -set_attr abc_scc_id {}"); - sel = RTLIL::Selection(false); + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output @@ -407,12 +405,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + Pass::call(design, "aigmap; clean;"); - handle_loops(design, module); + handle_loops(design); Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + 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 @@ -435,7 +439,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //if (count_output > 0) { - log_header(design, "Executing ABC.\n"); + log_header(design, "Executing ABC9.\n"); std::string buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); From 945bbcc2989c6b6cad2ef3b9aae253f23d6a2697 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 15:31:35 -0800 Subject: [PATCH 058/514] Add tests/simple_abc9 --- tests/simple_abc9/run-test.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100755 tests/simple_abc9/run-test.sh diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh new file mode 100755 index 000000000..5c51e44f9 --- /dev/null +++ b/tests/simple_abc9/run-test.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +OPTIND=1 +seed="" # default to no seed specified +while getopts "S:" opt +do + case "$opt" in + S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space + seed="SEED=$arg" ;; + esac +done +shift "$((OPTIND-1))" + +# check for Icarus Verilog +if ! which iverilog > /dev/null ; then + echo "$0: Error: Icarus Verilog 'iverilog' not found." + exit 1 +fi + +cp ../simple/*.v . +rm dff_different_styles.v # FIXME: dffsr1 fails because opt_rmdff does something fishy (#816) +rm partsel.v # FIXME: Contains 1'hx, thus write_xaiger fails +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p \"synth -abc9 -lut 4\"" From 43d5471570bd208ec87e2994f53a835c1e8ef3b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 15:34:59 -0800 Subject: [PATCH 059/514] Move tests/techmap/abc9 to simple_abc9 --- tests/{techmap/abc9 => simple_abc9}/abc9.v | 0 tests/techmap/abc9/abc9_runtest.sh | 5 ----- tests/techmap/abc9/run-test.sh | 10 ---------- tests/techmap/run-test.sh | 8 -------- 4 files changed, 23 deletions(-) rename tests/{techmap/abc9 => simple_abc9}/abc9.v (100%) delete mode 100644 tests/techmap/abc9/abc9_runtest.sh delete mode 100755 tests/techmap/abc9/run-test.sh diff --git a/tests/techmap/abc9/abc9.v b/tests/simple_abc9/abc9.v similarity index 100% rename from tests/techmap/abc9/abc9.v rename to tests/simple_abc9/abc9.v diff --git a/tests/techmap/abc9/abc9_runtest.sh b/tests/techmap/abc9/abc9_runtest.sh deleted file mode 100644 index 2deaad719..000000000 --- a/tests/techmap/abc9/abc9_runtest.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -ev - -../../../yosys -p 'abc9 -lut 4; check; select -assert-count 2 t:$lut; select -assert-none c:* t:$lut %n %i' abc9.v diff --git a/tests/techmap/abc9/run-test.sh b/tests/techmap/abc9/run-test.sh deleted file mode 100755 index e2fc11e52..000000000 --- a/tests/techmap/abc9/run-test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -e -for x in *_runtest.sh; do - echo "Running $x.." - if ! bash $x &> ${x%.sh}.log; then - tail ${x%.sh}.log - echo ERROR - exit 1 - fi -done diff --git a/tests/techmap/run-test.sh b/tests/techmap/run-test.sh index 129451e08..e2fc11e52 100755 --- a/tests/techmap/run-test.sh +++ b/tests/techmap/run-test.sh @@ -8,11 +8,3 @@ for x in *_runtest.sh; do exit 1 fi done - -for d in */; do - if [ -x $d/run-test.sh ]; then - cd $d - bash run-test.sh - cd .. - fi -done From f89b112fbf19a751070406449ab78f07b2c5e639 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 15:35:32 -0800 Subject: [PATCH 060/514] write_aiger: fix CI/CO and symbols --- backends/aiger/.xaiger.cc.swo | Bin 0 -> 36864 bytes backends/aiger/xaiger.cc | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 backends/aiger/.xaiger.cc.swo diff --git a/backends/aiger/.xaiger.cc.swo b/backends/aiger/.xaiger.cc.swo new file mode 100644 index 0000000000000000000000000000000000000000..a1272983532268e20e66d4f82b5be9c8144f680d GIT binary patch literal 36864 zcmeI53zTG6S*VKyCw4Fd@ve(;EpShho~fScuI?ViB$H&M`Z1FtJ>8S;o=lpaNvFE% zRL>#RRh2r`Gt)Ce9vDy}l7KI`2Eq71@RHy)x*`Etc!>}(f(i<{5+y!J5JW|JC>X#0 z-}}@#r>eSVdXjb5x>}ulQ+3YXXFvY^{Qtf8siooTbNkKZnc)}= z>X|}e{V=*NT?uq0a1Ih!ZIlKtzbN$syGFFBzr1&=`JNXaJcod~k8~x_l|WYlT?uq0 z(3L<}0$mAoCD4_?|F05g)GkQfM&i$N8MxhjKCk8TJKXhQ_jyN)`}5uPF8BGTE$-jx zuHWoFFLn`x@oaJTPrA={w76g3?ytGem$(Fn&!6w^t8&Blds^I`bN8bwfvyC)66i{x zD}k;Ax)SJ0peuo{1iBLFN}wx&|CSQS7gH(G*{4KbX8r$mCxvfcoJxHL{uq85-U<`& zZ!b)x9)w?qB78sm$wjHukHH@J=kH3T9)SN1zY6b$pMV-vVIH#ZO8B4fKj4`cq*DI@ zPs3yIVfY|C4DW~g;eGIS_*r-ZG@u9tn1GkTmoDU4_yxEFj=*8K0?vnz^`uh22k(V9 zz!Kyk3p=16E`kf;YZxr2!1?gE7+W5NkHh_N7nI?8I0#q4 z_rfz6MV^MI;1A)wa1We>H8=>@!8SM#K1m(;age&OU+TlA|9a%lFPXGo@f*kT+*2J_~vRed?g=OnSEYk)<5Z`kNb76-)!5K zxamUc$Lr3WHjJ@qB_IHs0)mm}2KVF}jk>?I+VFx*zLD-dd{{j6_Ft*d&ic!3m3f0w0EU;5sX61q}g zH)Lf4(xJNF@apOPT2^Lt18EUNP*8TBIIIl_e`$Tg%nu#e5KW^+vkI)$F0o;D^U0h@Kwt z>ecJjdb)SqBbtgSR4a|VUkS|i6Wa}KZTrdXMr4#R2LsP+4~Vr=^h(l2TXp%HFD`z@+0v`>&rnV@W@#)?q#^u zOUbVXR`xwT+NSe7h^Ks|7*Dd)GwuAs`%}6tv&~X#d zNFAmW8{T56WMhogrnsZoqczE8C~`sgK_(fYDYL8i7E99@(Rgp@MLrDT8DtmJR@7HfIG9+tc`!|2`! zwPCnl%UT26xsw|NnBTdRuw80g)zPA$`q)|{36gJ-BuXX9X_&`~exc#I9re9OJuPZ~ zNZ-@RL$zM?>hwKK9+fmow(Vt<9QTw+TOPG}w*hDYHM5>8&NB2?mIvsRr4#as zdrV`k=1I*a>xr(p;A^KmKz9@N&I$KO{!$ZL1*d7TwP?WD&po8bHq%zm&fU0XG+;_4 zNfFr$`=ZvwX_310SviDhOcb9C7p@X$4pTiuwLf2T9X+A83@F^$pBQqkOr1&vjrwY# zVd4W*Dn*+pQSlq;6I5c`L{3nMCk)xVj9{E=`h?kLhEH5p>NltPyj%u_p5sUTvS-xk zR_k_(AY$#GQ0(||Ds`;t7o{qA^+m5zU_46)jpFXzRTAapSIoAOZ5JnK76)c>*JtM@ z7N@fNCuR?1$0im>C-&v0QU_;qQ~MU@r)TG9BezuQ<$k45UM+g2_hzqN@ybJizuZ7z zLFQ<0yQ6Lu7MGOSF$DZ?%=C=OO_{Ojsi}#vx!m-WIh32b#>`zaVGhnti0grgnZ469 z`?FJHT<*msH*036_s$*4&P-%9h^&1OM}nD~;c~!CP3)V@?VHetX3R9<&6v6A8Dcm% zYwQC9COeape3|Kka|Eqn9l9nvH#F*~W)DuziTmD}>HTJMdUjS4K(YqRcy=zU ziJO_;o12>*Fo&+0&^X9TcFLw|YTnEqm>A1tC-I+~A$tR4HT*`-NbT&zbq6P==I}$1 z`?LEdh+>8i=EF-3YX8K{*frUyx$J0eGB-Dm`?w+6sfpRyj7V>4+K}R@IWv1rc5+gM zmpwRl4IzzAn8{prbaKKVLz_Vn@65!$?94a^-2MZTxruRuq-Tgd zCyBFClHv)=z)&6sW~Q&tjpMa9JIi&ircgY&WQ^x#$0oD6{fM4$qwq+PCaO@at=0YI zqYY`lKC={BIWrYMFg35f;s=3Wtu&o#H7{SMTc&B3=~-$%!-s}aTdmh*a&z2o9F^&i zeA2Q_$@2_B9i^9ES~JUa<~?36%wDv-1@a9gwrxRc5-Wp&cpF{|}-YkDxz` z{vWQN{{_1K@4|!d033!ZU?*&YKSu9=0DczU2zP=9voHa#gspHfJP*EwZQybE1bhe{ zg8SjUa0lEDvoHg%fNx?K_y#-(4G3Tku7>mBE2Q^sxCsu!JX{0&K=LvS-M_8`x)SJ0 zpeuo{1iBLFN}wx&t^}U71lsl8iK%fkbEm0~+7qql+hV^`o9A)0DrfXVEDUKtfj;Kd zm(V?|%|Q*w&IlQ^+K%Nb+Z(1TbN7;H?>F@Y+f`AJz%Z%oHhlr+Sd@%>ZBcxPRXtN! zM8!ypWf^r{&A_%Sr_HJH3`@ByAl7679ca)&JeQF-=qoHnr9+ z;9MjbYF8Aq-_}G>-b$^pMr^E*5Me?jYG+9AKqUE~;QP+Tz9Oc0_dQr!S;9o1R~l{H zDq?J4X^tL?2W;(eQ#*zVZgML$(aRNKNUqxiUGhbVtk&FWjcAO8)q35-@W5L6iAFuYC^qFZG6+i%X>dpX^^0Qe zakXg)3(U=Op5E%w#Rn`xl#son23P`GAT+|!^_Jej(caL4E&=rq~x3v5^o@JS#>Ub=UZhj`v13kQmM~l0}%Z`+`s=c zI{sh7@4($~7yKX$!w|dxoe8&M>y=gijN- zYW|{NvbI-2Q&0EKp}2|8Zt|#@jeOZuOQx^Lo(Q`cO}4!RqH*>GrtIJBnM+v=47^)p zyVXE*4`k?DHy)tjOALN7++(H%;`G8;O4;uvyTxQ*jnxu6rz;FwQbH;+9TSp_&?Z1M z<9u1ew-H1e6(y+M%{n6#bFgCr{l$_l$v^D9Nv>miO>DBXr*UVdc%*}0ps+n)< zVYeAYEF^5J9Loi!kgrgG&63y55^g=tUuNT^xE(Dnv`f$6}o_FS*CAnl$w%Y?*gwzUFiUG1ESo|xyBM6`-Js&F<`(imk@QY$O; z?U_B0Yi4%+xUf*zda|*I6V+y;RFImc$is(hDUVl8P+dWyxuLOX!{&g-Aglfbj|~Nw z+oU&9X$=iYLvVX54_1QJn(WnOXF$PYi-GKJ64RVX_XYjheqFN>S1dp{M{QT`In$g5 z-P03pj#`Mk%U;RwwzEs@v^xRSp0~B>W;fYI4_f=4>l1opyQKCR>|3xMo#_8xWl#BS z>`fQ_KRn<6`{?(Nz(?Wj@KbOc4#FI~0$u`7qThcQ9)kD4FT#EBBTxd_6L2kLU=Use zUq{#fGx$w-0AvrqufQ+EkHTxfhgZQ6WI*f#Ti^@W0iFaoUm$jY!ysn~2H<6I34Aa7 zC3b+%!n@!oOhN`OfgU&yo(EzlcpTmhx4@OK6)u3k$2RaNJPf}DzX@-JpMXPfCA<_a z201g(1Aoq0fcL?V!7cD=xB^}Z=fl&;`AK*f-U)92k^QZ(1bMg$E`slb|HGMp`{8}? zMmP*|PM{Yqfb-!`DZk%>pMyK$c9?@JpckG8Uwl62G~k2q5ZnuQKoJTs4%=ZHY=JLx z9^g?p3X`x8{)jUHkHH_nZ^JLao8dIv4D)aU=-H1oDPKjPj}c=3G6m!Iqcd| ztK+!v9FLD@Ij(MMfS28742t1+(j9$uj`d$-^pz!*aK!B?B(LoL=8T(?t6StX={W6X z>pil6c$A6sG?M`4+GrZ-rO-`BbTRYWA>U4+(uIsYv*1>FqSQ1eQZ50xFdRFLI6k;X z&m8GoPFDs=p^H7&A@(R@eWE>H@v!xHznmV4ty1+I;uMtGahwpBGIAoyswJ@*B}zlV z9nHv~L&%9Kt2Ssln@)bPSYq96ZISQ;#*~(bG(dGSdTwJ|LBiEJ7*{GMj#sQgqaRzO^w?D(V7jj72RS2gf9g$dN zUMH)Iy_YuA(c3RGjgDz``uf7WOc$eb57_}TdKT%89hq`d{phKt7Uf*BF1&NfV_2g` zH;@b~lr548pUQ6VRJQG@b>+Fpmgq$%%b_7RsZXwi4h=a|$ij6Z&~YswZgwj4>#RW3 zwN+T-O*bd5>o&;3b!}N7O!wUQ2G5Omcuq4vG?c7PRN-{*rHgy_E@D^U%Q)YrV&4xS zmG!HbHQ&^170aqbI?5w#1nrgTIjK6&RVA33o|8(@dT3J`svI5Cb^O6Sa@jnz*`6bs zua}H?>ZyA37~D7JAq#Nmm+%M;Fo4Jjt@)T%;P~!4{i# zGhCUi_Kd7NDLsqcmj~QnU?YoOW7nfVxb4kf0ob_Rs z=VaI195~NL6mm8yUyBQ(_3YwEKPSjWD0Vs3wV@nBMNSa zY}-U{L;nxozxOG0`}^P&Tnm@N-=MqyCCIw}Z^N75$6*ong6#Xh1iplx{`VmJ{O^Ig zL3H|kuoeCd{rqwGFx&^Phuh&aoPuR2z;3t#QK%k2U@{wmDO$|);GB0o*Y3t9jbKU$1M!I$fG%)WeIf*a#t);RvCJ0rf41@A}tb<9LbWMiMBMf!?L}W3x+L* z{1!;rb-sGD*Ys)>_Fg3YZ2_`p8&i0CTS~V_v!F{bkxORDTV}o^dm)>?GsF^3w_O%+ zQ-w+6iAS@xVk466hv5k5wof(JEF^N95&LhmFYa+Z7n&j}_Z69RmHUsxPA@kd`+~jz zS5BZhYq3GGtw!M} zC+T+7XkW3H7|7;1eHno}In1y~=TPpKadCvk{==qsYcGQA?RAB#$Cc$!a(K$worG@d zQ?yfQ^<;Y%*Y|{_5|%+H;rJ@{bY70hj`Rp=OF)0Md8XK9?d2SLLPH3 zfFMiT$dSld&-jvgiqZAc+9ha*tgk$A@^U306ScU9P0O^ephAtd=~Bwum$p;N+pF8z zZrfSL=PKTFjqTY)R@jI{uJP%pm1~=C9Tc7Iavd+vUBy0E zp`Try?hBrskk7U{uQ%=JJnwL|y?yc#7KQVmQxP3LqHa4eNuWU`I$oXeP$vjy6tj)= z(al-AG`^$)WUGR+q=}o2wv*N%P4|?hWHa-AF%4`u>1mtwa3e}&`!vUSw9&8vEX?@TwG3 z6MLR**vX*R4|ya!DUp1omrK*xhO&vgJN-C{KwbwX&B;y5S~Jexo2Fddv_)ngK2ybJ z@kznCj=gDTmk1Km9AAguU9OF{MI(aX6i4)wjpZzZ4QF4i!EP9+G_~jrQ_=;-qPKH1 zn`qv_Bl`^!rc4UEo0$UI{zk1@H~@{IA24@KN}6xF3EE-V3jT-LMs229KcsKLl@p zH8Ai9y8lD)3*f_Hn1HXK_kSE7hWlUvrXT}fMAv^DJ_v7u+n@+9h7Y6Lza8ELZ-noL z7s6N33Wvl4bM^~?}n$Nl6PauHn~f>xxrLVz_mHX=HRW*C5kQ?WTGHKC#0-~ z0Z#?e^4gyr^4_1gAfmHsdbc?PK$CaV06j=GV4R)Dy@YOum3zP8)j-p{H)nPgC##PTEyspO~TaJT*<3h zWL-?(-J-7@;w^XiqU_4##V8#k&Xv@&O|q_I>ihF5)nqhQArr5h8I+x#ynnIM9^znb zzzj~qXd<%2MVMvX1v-e)8q*8!q*KuS+QN{8Z7Ra>#ZP$`q-o@rIMOPG!i#j4o0g-fq}$_k%^=~B zxCnE%S`p>eX946S#;Cn}qqi0&>I?lG5^abFsTwD}dUdenLB?)=23NN2@*(TR?A*0V zwH(B4i+oU9T;g`(B21tae|B~(my<%(*A=lLIJ+-L??b>V`9|AwgW6;hw-Xogb|YS~ zme`9JV0`2@J62s@5eL)Rs;LF5UQu#OTd{jHYk{}Qop6$w2>OtmVb+359*7mGQHNZw zDb+7y<|t0rTvk>w84-7hy40YAd8t@Mrd>Mw>D<_@Nm70t*sGg`YE75ukC=t9Y9HzN zIGat4IXyTycnqGiPkkq#_J>EkaxLA`VcA2-?!Y&WyG{7L*CwBNU#~4^Ck})alavf> z=C#Qey}1ww%e~z+yusqzYZ+^FGOLq8=5hAbl`;a^fl*#JyG>UfMQO9fUYV9gR|%Wt znS;?DAPOgT*&a}@tv6c>OK$()-u@Fpga7O(+ zHjfrNwaQ(xzy2zblnj5#*`?MEQBW9A+yara%~-RhJ|y)gHa}|G#$3`{LhOmv)P-^~ zFY2T@X=bLpZf0VZpACZaE5|k!s$?cMG27U9Ze=D?JsW$uwzK5hMUyf;gXE&h+gb<2 zB`LOa)1JPr{9?5p-)*Mqu&!vVb|h+B0gxQU-8&nqJJ*AFn_j3U>w$Gk=BT=EMkJ-{ zSc1c?cq)2*SGVnsY(kgp`e(w_yA&B6JEuF=g4>IM)|^cBvnmJC|6h(0cwBTr^#3!4zLFEFb@6D2eLol8Fc?I!r#H)!k@q=;Wywd@H!~NJ{W~P za5eP8Met>81CPKv;Wju9SHflRL-1|v0Z+jvK=%KKzc299e18iZhdNvfuYxqZ04{{5 zunRm1avop-8f4Tb&5a76J!GlBbURI@sdM~!`4J22v!y>n5sE!x7plTdL=vzxj1EfB0zP$IKcdlV z^PvflB`w*e>TY`<&RwPTFo+hHebqs{q-+N5znV|f(kKSPb-xcGvx*`=qd|e+$nQ$n zOA)AFxpAcbMz{K`X^y)^0mPJ=D0~!qR!TPGvG}4eL|lpVC7&lDDiXJ^K*YU{ zfLXp23A1IqHAHixthA`(2G6rjX}z3P5uFmhQOk*!1TNy5tQk?wOC~@12@u!W#D#~H z-0z0ClhT^C@FzdYQJ=EeW?)-aTSK6pMd{JP6@!K>DZA>~++J=ArBgFWgyEK+MHJ28 ztWp_;$VehTq=NY>sq{xR3NfhAVqI6F#zbP$LhdA_&LtHSgO!CQ(rWRE=wrX$;_6pe z2+Z?s&1x|TZIorr?Yb#CbM0AaiCp87mqO|D1QS>LS0qB?le;6R&?mlmGw# literal 0 HcmV?d00001 diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d125335f9..56d361fff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -232,17 +232,22 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs or POs - for (auto bit : co_bits) + // Erase all POs and CIs that are also PIs + for (auto bit : input_bits) { + output_bits.erase(bit); ci_bits.erase(bit); - for (auto bit : output_bits) + } + for (auto bit : output_bits) { + ci_bits.erase(bit); + // POs override COs + co_bits.erase(bit); + } + // Erase all CIs that are also COs + for (auto bit : co_bits) ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); - // POs override COs - for (auto bit : output_bits) - co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -525,7 +530,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (wire->port_input || ci_bits.count(b)) { + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); @@ -567,6 +572,7 @@ struct XAigerWriter input_lines.sort(); for (auto &it : input_lines) f << it.second; + log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); init_lines.sort(); for (auto &it : init_lines) From 01f8d50ba239e98de1e6a75aec314caeae297bc8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 16:17:01 -0800 Subject: [PATCH 061/514] Remove swap file --- backends/aiger/.xaiger.cc.swo | Bin 36864 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backends/aiger/.xaiger.cc.swo diff --git a/backends/aiger/.xaiger.cc.swo b/backends/aiger/.xaiger.cc.swo deleted file mode 100644 index a1272983532268e20e66d4f82b5be9c8144f680d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36864 zcmeI53zTG6S*VKyCw4Fd@ve(;EpShho~fScuI?ViB$H&M`Z1FtJ>8S;o=lpaNvFE% zRL>#RRh2r`Gt)Ce9vDy}l7KI`2Eq71@RHy)x*`Etc!>}(f(i<{5+y!J5JW|JC>X#0 z-}}@#r>eSVdXjb5x>}ulQ+3YXXFvY^{Qtf8siooTbNkKZnc)}= z>X|}e{V=*NT?uq0a1Ih!ZIlKtzbN$syGFFBzr1&=`JNXaJcod~k8~x_l|WYlT?uq0 z(3L<}0$mAoCD4_?|F05g)GkQfM&i$N8MxhjKCk8TJKXhQ_jyN)`}5uPF8BGTE$-jx zuHWoFFLn`x@oaJTPrA={w76g3?ytGem$(Fn&!6w^t8&Blds^I`bN8bwfvyC)66i{x zD}k;Ax)SJ0peuo{1iBLFN}wx&|CSQS7gH(G*{4KbX8r$mCxvfcoJxHL{uq85-U<`& zZ!b)x9)w?qB78sm$wjHukHH@J=kH3T9)SN1zY6b$pMV-vVIH#ZO8B4fKj4`cq*DI@ zPs3yIVfY|C4DW~g;eGIS_*r-ZG@u9tn1GkTmoDU4_yxEFj=*8K0?vnz^`uh22k(V9 zz!Kyk3p=16E`kf;YZxr2!1?gE7+W5NkHh_N7nI?8I0#q4 z_rfz6MV^MI;1A)wa1We>H8=>@!8SM#K1m(;age&OU+TlA|9a%lFPXGo@f*kT+*2J_~vRed?g=OnSEYk)<5Z`kNb76-)!5K zxamUc$Lr3WHjJ@qB_IHs0)mm}2KVF}jk>?I+VFx*zLD-dd{{j6_Ft*d&ic!3m3f0w0EU;5sX61q}g zH)Lf4(xJNF@apOPT2^Lt18EUNP*8TBIIIl_e`$Tg%nu#e5KW^+vkI)$F0o;D^U0h@Kwt z>ecJjdb)SqBbtgSR4a|VUkS|i6Wa}KZTrdXMr4#R2LsP+4~Vr=^h(l2TXp%HFD`z@+0v`>&rnV@W@#)?q#^u zOUbVXR`xwT+NSe7h^Ks|7*Dd)GwuAs`%}6tv&~X#d zNFAmW8{T56WMhogrnsZoqczE8C~`sgK_(fYDYL8i7E99@(Rgp@MLrDT8DtmJR@7HfIG9+tc`!|2`! zwPCnl%UT26xsw|NnBTdRuw80g)zPA$`q)|{36gJ-BuXX9X_&`~exc#I9re9OJuPZ~ zNZ-@RL$zM?>hwKK9+fmow(Vt<9QTw+TOPG}w*hDYHM5>8&NB2?mIvsRr4#as zdrV`k=1I*a>xr(p;A^KmKz9@N&I$KO{!$ZL1*d7TwP?WD&po8bHq%zm&fU0XG+;_4 zNfFr$`=ZvwX_310SviDhOcb9C7p@X$4pTiuwLf2T9X+A83@F^$pBQqkOr1&vjrwY# zVd4W*Dn*+pQSlq;6I5c`L{3nMCk)xVj9{E=`h?kLhEH5p>NltPyj%u_p5sUTvS-xk zR_k_(AY$#GQ0(||Ds`;t7o{qA^+m5zU_46)jpFXzRTAapSIoAOZ5JnK76)c>*JtM@ z7N@fNCuR?1$0im>C-&v0QU_;qQ~MU@r)TG9BezuQ<$k45UM+g2_hzqN@ybJizuZ7z zLFQ<0yQ6Lu7MGOSF$DZ?%=C=OO_{Ojsi}#vx!m-WIh32b#>`zaVGhnti0grgnZ469 z`?FJHT<*msH*036_s$*4&P-%9h^&1OM}nD~;c~!CP3)V@?VHetX3R9<&6v6A8Dcm% zYwQC9COeape3|Kka|Eqn9l9nvH#F*~W)DuziTmD}>HTJMdUjS4K(YqRcy=zU ziJO_;o12>*Fo&+0&^X9TcFLw|YTnEqm>A1tC-I+~A$tR4HT*`-NbT&zbq6P==I}$1 z`?LEdh+>8i=EF-3YX8K{*frUyx$J0eGB-Dm`?w+6sfpRyj7V>4+K}R@IWv1rc5+gM zmpwRl4IzzAn8{prbaKKVLz_Vn@65!$?94a^-2MZTxruRuq-Tgd zCyBFClHv)=z)&6sW~Q&tjpMa9JIi&ircgY&WQ^x#$0oD6{fM4$qwq+PCaO@at=0YI zqYY`lKC={BIWrYMFg35f;s=3Wtu&o#H7{SMTc&B3=~-$%!-s}aTdmh*a&z2o9F^&i zeA2Q_$@2_B9i^9ES~JUa<~?36%wDv-1@a9gwrxRc5-Wp&cpF{|}-YkDxz` z{vWQN{{_1K@4|!d033!ZU?*&YKSu9=0DczU2zP=9voHa#gspHfJP*EwZQybE1bhe{ zg8SjUa0lEDvoHg%fNx?K_y#-(4G3Tku7>mBE2Q^sxCsu!JX{0&K=LvS-M_8`x)SJ0 zpeuo{1iBLFN}wx&t^}U71lsl8iK%fkbEm0~+7qql+hV^`o9A)0DrfXVEDUKtfj;Kd zm(V?|%|Q*w&IlQ^+K%Nb+Z(1TbN7;H?>F@Y+f`AJz%Z%oHhlr+Sd@%>ZBcxPRXtN! zM8!ypWf^r{&A_%Sr_HJH3`@ByAl7679ca)&JeQF-=qoHnr9+ z;9MjbYF8Aq-_}G>-b$^pMr^E*5Me?jYG+9AKqUE~;QP+Tz9Oc0_dQr!S;9o1R~l{H zDq?J4X^tL?2W;(eQ#*zVZgML$(aRNKNUqxiUGhbVtk&FWjcAO8)q35-@W5L6iAFuYC^qFZG6+i%X>dpX^^0Qe zakXg)3(U=Op5E%w#Rn`xl#son23P`GAT+|!^_Jej(caL4E&=rq~x3v5^o@JS#>Ub=UZhj`v13kQmM~l0}%Z`+`s=c zI{sh7@4($~7yKX$!w|dxoe8&M>y=gijN- zYW|{NvbI-2Q&0EKp}2|8Zt|#@jeOZuOQx^Lo(Q`cO}4!RqH*>GrtIJBnM+v=47^)p zyVXE*4`k?DHy)tjOALN7++(H%;`G8;O4;uvyTxQ*jnxu6rz;FwQbH;+9TSp_&?Z1M z<9u1ew-H1e6(y+M%{n6#bFgCr{l$_l$v^D9Nv>miO>DBXr*UVdc%*}0ps+n)< zVYeAYEF^5J9Loi!kgrgG&63y55^g=tUuNT^xE(Dnv`f$6}o_FS*CAnl$w%Y?*gwzUFiUG1ESo|xyBM6`-Js&F<`(imk@QY$O; z?U_B0Yi4%+xUf*zda|*I6V+y;RFImc$is(hDUVl8P+dWyxuLOX!{&g-Aglfbj|~Nw z+oU&9X$=iYLvVX54_1QJn(WnOXF$PYi-GKJ64RVX_XYjheqFN>S1dp{M{QT`In$g5 z-P03pj#`Mk%U;RwwzEs@v^xRSp0~B>W;fYI4_f=4>l1opyQKCR>|3xMo#_8xWl#BS z>`fQ_KRn<6`{?(Nz(?Wj@KbOc4#FI~0$u`7qThcQ9)kD4FT#EBBTxd_6L2kLU=Use zUq{#fGx$w-0AvrqufQ+EkHTxfhgZQ6WI*f#Ti^@W0iFaoUm$jY!ysn~2H<6I34Aa7 zC3b+%!n@!oOhN`OfgU&yo(EzlcpTmhx4@OK6)u3k$2RaNJPf}DzX@-JpMXPfCA<_a z201g(1Aoq0fcL?V!7cD=xB^}Z=fl&;`AK*f-U)92k^QZ(1bMg$E`slb|HGMp`{8}? zMmP*|PM{Yqfb-!`DZk%>pMyK$c9?@JpckG8Uwl62G~k2q5ZnuQKoJTs4%=ZHY=JLx z9^g?p3X`x8{)jUHkHH_nZ^JLao8dIv4D)aU=-H1oDPKjPj}c=3G6m!Iqcd| ztK+!v9FLD@Ij(MMfS28742t1+(j9$uj`d$-^pz!*aK!B?B(LoL=8T(?t6StX={W6X z>pil6c$A6sG?M`4+GrZ-rO-`BbTRYWA>U4+(uIsYv*1>FqSQ1eQZ50xFdRFLI6k;X z&m8GoPFDs=p^H7&A@(R@eWE>H@v!xHznmV4ty1+I;uMtGahwpBGIAoyswJ@*B}zlV z9nHv~L&%9Kt2Ssln@)bPSYq96ZISQ;#*~(bG(dGSdTwJ|LBiEJ7*{GMj#sQgqaRzO^w?D(V7jj72RS2gf9g$dN zUMH)Iy_YuA(c3RGjgDz``uf7WOc$eb57_}TdKT%89hq`d{phKt7Uf*BF1&NfV_2g` zH;@b~lr548pUQ6VRJQG@b>+Fpmgq$%%b_7RsZXwi4h=a|$ij6Z&~YswZgwj4>#RW3 zwN+T-O*bd5>o&;3b!}N7O!wUQ2G5Omcuq4vG?c7PRN-{*rHgy_E@D^U%Q)YrV&4xS zmG!HbHQ&^170aqbI?5w#1nrgTIjK6&RVA33o|8(@dT3J`svI5Cb^O6Sa@jnz*`6bs zua}H?>ZyA37~D7JAq#Nmm+%M;Fo4Jjt@)T%;P~!4{i# zGhCUi_Kd7NDLsqcmj~QnU?YoOW7nfVxb4kf0ob_Rs z=VaI195~NL6mm8yUyBQ(_3YwEKPSjWD0Vs3wV@nBMNSa zY}-U{L;nxozxOG0`}^P&Tnm@N-=MqyCCIw}Z^N75$6*ong6#Xh1iplx{`VmJ{O^Ig zL3H|kuoeCd{rqwGFx&^Phuh&aoPuR2z;3t#QK%k2U@{wmDO$|);GB0o*Y3t9jbKU$1M!I$fG%)WeIf*a#t);RvCJ0rf41@A}tb<9LbWMiMBMf!?L}W3x+L* z{1!;rb-sGD*Ys)>_Fg3YZ2_`p8&i0CTS~V_v!F{bkxORDTV}o^dm)>?GsF^3w_O%+ zQ-w+6iAS@xVk466hv5k5wof(JEF^N95&LhmFYa+Z7n&j}_Z69RmHUsxPA@kd`+~jz zS5BZhYq3GGtw!M} zC+T+7XkW3H7|7;1eHno}In1y~=TPpKadCvk{==qsYcGQA?RAB#$Cc$!a(K$worG@d zQ?yfQ^<;Y%*Y|{_5|%+H;rJ@{bY70hj`Rp=OF)0Md8XK9?d2SLLPH3 zfFMiT$dSld&-jvgiqZAc+9ha*tgk$A@^U306ScU9P0O^ephAtd=~Bwum$p;N+pF8z zZrfSL=PKTFjqTY)R@jI{uJP%pm1~=C9Tc7Iavd+vUBy0E zp`Try?hBrskk7U{uQ%=JJnwL|y?yc#7KQVmQxP3LqHa4eNuWU`I$oXeP$vjy6tj)= z(al-AG`^$)WUGR+q=}o2wv*N%P4|?hWHa-AF%4`u>1mtwa3e}&`!vUSw9&8vEX?@TwG3 z6MLR**vX*R4|ya!DUp1omrK*xhO&vgJN-C{KwbwX&B;y5S~Jexo2Fddv_)ngK2ybJ z@kznCj=gDTmk1Km9AAguU9OF{MI(aX6i4)wjpZzZ4QF4i!EP9+G_~jrQ_=;-qPKH1 zn`qv_Bl`^!rc4UEo0$UI{zk1@H~@{IA24@KN}6xF3EE-V3jT-LMs229KcsKLl@p zH8Ai9y8lD)3*f_Hn1HXK_kSE7hWlUvrXT}fMAv^DJ_v7u+n@+9h7Y6Lza8ELZ-noL z7s6N33Wvl4bM^~?}n$Nl6PauHn~f>xxrLVz_mHX=HRW*C5kQ?WTGHKC#0-~ z0Z#?e^4gyr^4_1gAfmHsdbc?PK$CaV06j=GV4R)Dy@YOum3zP8)j-p{H)nPgC##PTEyspO~TaJT*<3h zWL-?(-J-7@;w^XiqU_4##V8#k&Xv@&O|q_I>ihF5)nqhQArr5h8I+x#ynnIM9^znb zzzj~qXd<%2MVMvX1v-e)8q*8!q*KuS+QN{8Z7Ra>#ZP$`q-o@rIMOPG!i#j4o0g-fq}$_k%^=~B zxCnE%S`p>eX946S#;Cn}qqi0&>I?lG5^abFsTwD}dUdenLB?)=23NN2@*(TR?A*0V zwH(B4i+oU9T;g`(B21tae|B~(my<%(*A=lLIJ+-L??b>V`9|AwgW6;hw-Xogb|YS~ zme`9JV0`2@J62s@5eL)Rs;LF5UQu#OTd{jHYk{}Qop6$w2>OtmVb+359*7mGQHNZw zDb+7y<|t0rTvk>w84-7hy40YAd8t@Mrd>Mw>D<_@Nm70t*sGg`YE75ukC=t9Y9HzN zIGat4IXyTycnqGiPkkq#_J>EkaxLA`VcA2-?!Y&WyG{7L*CwBNU#~4^Ck})alavf> z=C#Qey}1ww%e~z+yusqzYZ+^FGOLq8=5hAbl`;a^fl*#JyG>UfMQO9fUYV9gR|%Wt znS;?DAPOgT*&a}@tv6c>OK$()-u@Fpga7O(+ zHjfrNwaQ(xzy2zblnj5#*`?MEQBW9A+yara%~-RhJ|y)gHa}|G#$3`{LhOmv)P-^~ zFY2T@X=bLpZf0VZpACZaE5|k!s$?cMG27U9Ze=D?JsW$uwzK5hMUyf;gXE&h+gb<2 zB`LOa)1JPr{9?5p-)*Mqu&!vVb|h+B0gxQU-8&nqJJ*AFn_j3U>w$Gk=BT=EMkJ-{ zSc1c?cq)2*SGVnsY(kgp`e(w_yA&B6JEuF=g4>IM)|^cBvnmJC|6h(0cwBTr^#3!4zLFEFb@6D2eLol8Fc?I!r#H)!k@q=;Wywd@H!~NJ{W~P za5eP8Met>81CPKv;Wju9SHflRL-1|v0Z+jvK=%KKzc299e18iZhdNvfuYxqZ04{{5 zunRm1avop-8f4Tb&5a76J!GlBbURI@sdM~!`4J22v!y>n5sE!x7plTdL=vzxj1EfB0zP$IKcdlV z^PvflB`w*e>TY`<&RwPTFo+hHebqs{q-+N5znV|f(kKSPb-xcGvx*`=qd|e+$nQ$n zOA)AFxpAcbMz{K`X^y)^0mPJ=D0~!qR!TPGvG}4eL|lpVC7&lDDiXJ^K*YU{ zfLXp23A1IqHAHixthA`(2G6rjX}z3P5uFmhQOk*!1TNy5tQk?wOC~@12@u!W#D#~H z-0z0ClhT^C@FzdYQJ=EeW?)-aTSK6pMd{JP6@!K>DZA>~++J=ArBgFWgyEK+MHJ28 ztWp_;$VehTq=NY>sq{xR3NfhAVqI6F#zbP$LhdA_&LtHSgO!CQ(rWRE=wrX$;_6pe z2+Z?s&1x|TZIorr?Yb#CbM0AaiCp87mqO|D1QS>LS0qB?le;6R&?mlmGw# From abc1c2672e2b2d2ff80b4ccf42027fd629c1ac8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 16:17:22 -0800 Subject: [PATCH 062/514] read_aiger to also rename 0 index lut when wideports --- frontends/aiger/aigerparse.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 5c862b8f0..426e88e53 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -162,9 +162,15 @@ void AigerReader::parse_aiger() int width = wp.second + 1; RTLIL::Wire *wire = module->wire(name); - if (wire) + if (wire) { + RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + if (driver) + module->rename(driver, stringf("%slut", wire->name.c_str())); + } + // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; @@ -408,9 +414,15 @@ void AigerReader::parse_xaiger() int width = wp.second + 1; RTLIL::Wire *wire = module->wire(name); - if (wire) + if (wire) { + RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + if (driver) + module->rename(driver, stringf("%slut", wire->name.c_str())); + } + // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; From 869343b040d60ffa9bfdda81660c2ecd88848e79 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 16:19:01 -0800 Subject: [PATCH 063/514] simple_abc9 tests to now preserve memories --- tests/simple_abc9/run-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 5c51e44f9..1baf31244 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -20,4 +20,4 @@ fi cp ../simple/*.v . rm dff_different_styles.v # FIXME: dffsr1 fails because opt_rmdff does something fishy (#816) rm partsel.v # FIXME: Contains 1'hx, thus write_xaiger fails -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p \"synth -abc9 -lut 4\"" +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p \"hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4\"" From 32853b1f8d8cefff36bf5852a04cdaef1bcb2035 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 16:30:30 -0800 Subject: [PATCH 064/514] lut/not/and suffix to be ${lut,not,and} --- frontends/aiger/aigerparse.cc | 26 +++++++++++++------------- passes/techmap/abc9.cc | 8 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 426e88e53..28f91d6b9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -163,12 +163,12 @@ void AigerReader::parse_aiger() RTLIL::Wire *wire = module->wire(name); if (wire) { - RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); if (driver) - module->rename(driver, stringf("%slut", wire->name.c_str())); + module->rename(driver, stringf("%s$lut", wire->name.c_str())); } // Do not make ports with a mix of input/output into @@ -246,7 +246,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\__%d__not", variable), wire_inv, wire); // FIXME: is "not" the right suffix? + module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); // FIXME: is "$not" the right suffix? return wire; } @@ -325,10 +325,10 @@ void AigerReader::parse_xaiger() lut_mask[j] = o.as_const()[0]; ce.pop(); } - RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__and", rootNodeID)); + RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - module->addLut(stringf("\\__%d__lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); + module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'n') { @@ -353,8 +353,8 @@ void AigerReader::parse_xaiger() module->rename(wire, stringf("\\%s", s.c_str())); - RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); - module->rename(driver, stringf("%slut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); + module->rename(driver, stringf("%s$lut", wire->name.c_str())); std::getline(f, line); // Ignore up to start of next line ++line_count; @@ -391,7 +391,7 @@ void AigerReader::parse_xaiger() log_assert(wire); log_assert(wire->port_output); - RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); if (index == 0) module->rename(wire, RTLIL::escape_id(symbol)); @@ -402,7 +402,7 @@ void AigerReader::parse_xaiger() } if (driver) - module->rename(driver, stringf("%slut", wire->name.c_str())); + module->rename(driver, stringf("%s$lut", wire->name.c_str())); } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); @@ -415,12 +415,12 @@ void AigerReader::parse_xaiger() RTLIL::Wire *wire = module->wire(name); if (wire) { - RTLIL::Cell* driver = module->cell(stringf("%slut", wire->name.c_str())); + RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); if (driver) - module->rename(driver, stringf("%slut", wire->name.c_str())); + module->rename(driver, stringf("%s$lut", wire->name.c_str())); } // Do not make ports with a mix of input/output into @@ -581,7 +581,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(o_wire->name.str() + "and", i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); } std::getline(f, line); } @@ -712,7 +712,7 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(o_wire->name.str() + "and", i1_wire, i2_wire, o_wire); + module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); } } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index cc906bae7..96f55d5d3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -592,7 +592,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (a_bit.wire->port_input) { // If it's a NOT gate that comes from a primary input directly // then implement it using a LUT - cell = module->addLut(remap_name(stringf("%slut", c->name.c_str())), + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), 1); @@ -603,9 +603,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // (TODO: Optimise by not cloning unless will increase depth) RTLIL::IdString driver_name; if (GetSize(a_bit.wire) == 1) - driver_name = stringf("%slut", a_bit.wire->name.c_str()); + driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); else - driver_name = stringf("%s[%d]lut", a_bit.wire->name.c_str(), a_bit.offset); + driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); RTLIL::Cell* driver = mapped_mod->cell(driver_name); log_assert(driver); auto driver_a = driver->getPort("\\A").chunks(); @@ -616,7 +616,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - cell = module->addLut(remap_name(stringf("%slut", c->name.c_str())), + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), driver_a, RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); From 9e299a090878bec9c5dcfe824610098c073a3364 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 17:33:04 -0800 Subject: [PATCH 065/514] read_aiger to not do -purge for clean --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 28f91d6b9..6fa77282e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -458,7 +458,7 @@ void AigerReader::parse_xaiger() module->fixup_ports(); design->add(module); - Pass::call(design, "clean -purge"); + Pass::call(design, "clean"); } void AigerReader::parse_aiger_ascii() From e5b8bb9faa466adac10e81799e338aa53210adbc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 17:33:35 -0800 Subject: [PATCH 066/514] abc9 to disconnect mapped_mods POs correctly, and do not count $_NOT_ --- passes/techmap/abc9.cc | 50 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 96f55d5d3..3f0072d24 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -568,21 +568,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri { if (builtin_lib) { - 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->getPort("\\Y").as_wire()->name)]); - conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1); - module->connect(conn); - continue; - } - if (c->type == "\\BUF") { - RTLIL::SigSig 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 == "$_NOT_") { RTLIL::Cell *cell; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); @@ -621,16 +606,35 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); } + cell_stats["$lut"]++; } else { cell = module->addCell(remap_name(c->name), "$_NOT_"); cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); + cell_stats[RTLIL::unescape_id(c->type)]++; } if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; design->select(module, cell); continue; } + + 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->getPort("\\Y").as_wire()->name)]); + conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1); + module->connect(conn); + continue; + } + if (c->type == "\\BUF") { + RTLIL::SigSig 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 == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); @@ -856,17 +860,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri auto port_name = it.first; if (!cell->output(port_name)) continue; auto &signal = it.second; - if (!signal.is_bit()) continue; - if (output_bits.count(signal.as_bit())) - signal = module->addWire(NEW_ID); + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); } } // Do the same for module connections for (auto &it : module->connections_) { auto &signal = it.first; - if (!signal.is_bit()) continue; - if (output_bits.count(signal.as_bit())) - signal = module->addWire(NEW_ID); + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); } // Stitch in mapped_mod's inputs/outputs into module From 7f26043caf6f9810d8541caaa57151ec8fb539a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 17:36:57 -0800 Subject: [PATCH 067/514] ABC -> ABC9 --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3f0072d24..4b045cbea 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -532,7 +532,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri ifs.close(); - log_header(design, "Re-integrating ABC results.\n"); + log_header(design, "Re-integrating ABC9 results.\n"); RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); From c6fd057eda5dba371ff9c1142019b801bee81111 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 10:37:45 -0800 Subject: [PATCH 068/514] Add abc9.v testcase to simple_abc9 --- tests/simple_abc9/abc9.v | 52 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 2d9aea366..d387b99eb 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -1,6 +1,48 @@ -module top(input [1:0] a, output [1:0] b, output c, output d, output e); -assign b = a; -assign c = ^a; -assign d = ~c; -assign e = d; +module abc9_test001(input a, output o); +assign o = a; +endmodule + +module abc9_test002(input [1:0] a, output o); +assign o = a[1]; +endmodule + +module abc9_test003(input [1:0] a, output [1:0] o); +assign o = a; +endmodule + +module abc9_test004(input [1:0] a, output o); +assign o = ^a; +endmodule + +module abc9_test005(input [1:0] a, output o, output p); +assign o = ^a; +assign p = ~o; +endmodule + +module abc9_test006(input [1:0] a, output [2:0] o); +assign o[0] = ^a; +assign o[1] = ~o[0]; +assign o[2] = o[1]; +endmodule + +module abc9_test007(input a, output o); +wire b, c; +assign c = ~a; +assign b = c; +abc9_test007_sub s(b, o); +endmodule + +module abc9_test007_sub(input a, output b); +assign b = a; +endmodule + +module abc9_test008(input a, output o); +wire b, c; +assign b = ~a; +assign c = b; +abc9_test008_sub s(b, o); +endmodule + +module abc9_test008_sub(input a, output b); +assign b = ~a; endmodule From 2f96a0ed32799eba95837d0b64953b889e607c22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:15:25 -0800 Subject: [PATCH 069/514] write_xaiger to use original bit for co, not sigmap()-ed bit --- backends/aiger/xaiger.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 56d361fff..b0602dbd8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -210,9 +210,12 @@ struct XAigerWriter Wire *w = b.wire; if (!w) continue; if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.insert(b); + } } else if (cell->output(c.first)) { SigBit O = sigmap(b); From 6b96df41bcc25b3ba71fdb83e5b7b0a46c3936dd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:15:47 -0800 Subject: [PATCH 070/514] abc9 to only disconnect output ports of AND and NOT gates --- passes/techmap/abc9.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 4b045cbea..44e1a422f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -536,6 +536,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); + pool output_bits; for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; @@ -852,10 +853,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - // Go through all cell output connections, + // Go through all AND and NOT output connections, // and for those output ports driving wires // also driven by mapped_mod, disconnect them for (auto cell : module->cells()) { + if (!cell->type.in("$_AND_", "$_NOT_")) + continue; for (auto &it : cell->connections_) { auto port_name = it.first; if (!cell->output(port_name)) continue; @@ -1131,7 +1134,6 @@ struct Abc9Pass : public Pass { std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; - show_tempdir = true; cleanup = true; vector lut_costs; markgroups = false; From 107da3becff01cdedf6572ece3af9a74463a3e93 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:16:25 -0800 Subject: [PATCH 071/514] Working simple_abc9 tests --- tests/simple_abc9/run-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 1baf31244..bf48d007d 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -18,6 +18,6 @@ if ! which iverilog > /dev/null ; then fi cp ../simple/*.v . -rm dff_different_styles.v # FIXME: dffsr1 fails because opt_rmdff does something fishy (#816) rm partsel.v # FIXME: Contains 1'hx, thus write_xaiger fails -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p \"hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4\"" +DOLLAR='?' +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_'" From 5994382a20a0b7e890d22d032eecb39b61e0b3ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:16:57 -0800 Subject: [PATCH 072/514] tests/simple to also do LUT synth --- tests/tools/autotest.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 65fd4cb1f..34007b689 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -180,6 +180,7 @@ do else test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v + test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -lut 4" ${bn}_ref.v if [ -n "$firrtl2verilog" ]; then if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v From ca870688c33f7a71eea78709d85a069957966ba6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 13:15:45 -0800 Subject: [PATCH 073/514] Revert "tests/simple to also do LUT synth" This reverts commit 5994382a20a0b7e890d22d032eecb39b61e0b3ce. --- tests/tools/autotest.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 2b8e60200..13c25432f 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -178,7 +178,6 @@ do else test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v - test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -lut 4" ${bn}_ref.v if [ -n "$firrtl2verilog" ]; then if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v From 7f8f36273a5b70dfcd16c1b497f4b98efe67eaea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 13:16:24 -0800 Subject: [PATCH 074/514] abc9 to use &mfs --- passes/techmap/abc9.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 44e1a422f..abf0167b5 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -31,7 +31,8 @@ #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 "&st; &fraig; &scorr; &dc2; &retime; &dch -f; &if;"/*" &mfs"*/ +//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2" +#define ABC_COMMAND_LUT "&st; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs" #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" From 04429f8152ae64de050580ec20db60ac6dc1c0e1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:28:36 -0800 Subject: [PATCH 075/514] abc9 to write_xaiger -symbols, not -map --- passes/techmap/abc9.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index abf0167b5..3eaaa5368 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -414,7 +414,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -symbols %s/input.xaig; ", tempdir_name.c_str())); design->selection_stack.pop_back(); @@ -527,8 +527,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.symbols"); - AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", buffer, true /* wideports */); + AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", "", true /* wideports */); reader.parse_xaiger(); ifs.close(); From 875a02a6f24dfd4e8ce12653462770c10733f323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:38:52 -0800 Subject: [PATCH 076/514] abc9 to not select anything extra, and pop selection after final clean --- passes/techmap/abc9.cc | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3eaaa5368..9ea2a7014 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -416,8 +416,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri Pass::call(design, stringf("write_xaiger -O -symbols %s/input.xaig; ", tempdir_name.c_str())); - 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 @@ -542,7 +540,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Wire *w = it.second; RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx; - design->select(module, remap_wire); if (w->port_output) { RTLIL::Wire *wire = module->wire(w->name); if (wire) { @@ -616,7 +613,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell_stats[RTLIL::unescape_id(c->type)]++; } if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - design->select(module, cell); continue; } @@ -643,7 +639,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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") { @@ -653,7 +648,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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 == "\\MUX4") { @@ -666,7 +660,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").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 == "\\MUX8") { @@ -684,7 +677,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").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 == "\\MUX16") { @@ -711,7 +703,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").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") { @@ -721,7 +712,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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") { @@ -732,7 +722,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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") { @@ -749,7 +738,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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; } } @@ -778,7 +766,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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; } @@ -803,7 +790,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell->setPort(conn.first, newsig); } - design->select(module, cell); } // Copy connections (and rename) from mapped_mod to module @@ -937,6 +923,8 @@ cleanup: remove_directory(tempdir_name); } + design->selection_stack.pop_back(); + log_pop(); } From 085ed9f4878e5a376bed6b7c59dc99db46140b41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:40:13 -0800 Subject: [PATCH 077/514] Add attribution --- backends/aiger/xaiger.cc | 1 + frontends/aiger/aigerparse.cc | 2 +- passes/techmap/abc9.cc | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b0602dbd8..dd174d5ee 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 45cacadb6..1302d03df 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Eddie Hung + * Copyright (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 9ea2a7014..17a5c0fe3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above From 7ad9628f07520c06096971ec09f7ae6f7b4b7b06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:41:11 -0800 Subject: [PATCH 078/514] Remove irrelevant citations --- passes/techmap/abc9.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 17a5c0fe3..30cd68881 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -22,14 +22,6 @@ // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification // http://www.eecs.berkeley.edu/~alanmi/abc/ -// [[CITE]] Berkeley Logic Interchange Format (BLIF) -// University of California. Berkeley. July 28, 1992 -// http://www.ece.cmu.edu/~ee760/760docs/blif.pdf - -// [[CITE]] Kahn's Topological sorting algorithm -// 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; 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" From 2811d66dea8a33b6e8440db25d8bf487f70a1dc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:58:40 -0800 Subject: [PATCH 079/514] Revert "abc9 to write_xaiger -symbols, not -map" This reverts commit 04429f8152ae64de050580ec20db60ac6dc1c0e1. --- passes/techmap/abc9.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 30cd68881..d652ef05a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -symbols %s/input.xaig; ", tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %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 @@ -518,7 +518,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", "", true /* wideports */); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.symbols"); + AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", buffer, true /* wideports */); reader.parse_xaiger(); ifs.close(); From 07036b8bf72db260bddc1dfe26c0e9f77473c163 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 17:01:07 -0800 Subject: [PATCH 080/514] read_aiger to work with symbol table --- frontends/aiger/aigerparse.cc | 55 ++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 1302d03df..c8ba1bffd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -254,6 +254,29 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } +static std::pair 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::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1)); + +failed: + return std::pair(name, 0); +} + void AigerReader::parse_xaiger() { std::string header; @@ -288,6 +311,8 @@ void AigerReader::parse_xaiger() unsigned l1; std::string s; bool comment_seen = false; + std::vector> deferred_renames; + deferred_renames.reserve(inputs.size() + latches.size() + outputs.size()); for (int c = f.peek(); c != EOF; c = f.peek()) { if (comment_seen || c == 'c') { if (!comment_seen) { @@ -354,10 +379,7 @@ void AigerReader::parse_xaiger() else if (c == 'o') wire = outputs[l1]; else log_abort(); - module->rename(wire, stringf("\\%s", s.c_str())); - - RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); - module->rename(driver, stringf("%s$lut", wire->name.c_str())); + deferred_renames.emplace_back(wire, RTLIL::escape_id(s)); std::getline(f, line); // Ignore up to start of next line ++line_count; @@ -367,6 +389,23 @@ void AigerReader::parse_xaiger() } dict wideports_cache; + for (auto i : deferred_renames) { + RTLIL::Wire *wire = i.first; + RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); + + module->rename(wire, i.second); + + if (driver) + module->rename(driver, stringf("%s$lut", wire->name.c_str())); + + if (wideports && (wire->port_input || wire->port_output)) { + RTLIL::IdString escaped_symbol; + int index; + std::tie(escaped_symbol,index) = wideports_split(wire->name.str()); + if (index > 0) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + } if (!map_filename.empty()) { std::ifstream mf(map_filename); @@ -381,9 +420,9 @@ void AigerReader::parse_xaiger() log_assert(wire->port_input); if (index == 0) - module->rename(wire, RTLIL::escape_id(symbol)); + module->rename(wire, escaped_symbol); else if (index > 0) { - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); } @@ -397,9 +436,9 @@ void AigerReader::parse_xaiger() RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); if (index == 0) - module->rename(wire, RTLIL::escape_id(symbol)); + module->rename(wire, escaped_symbol); else if (index > 0) { - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); + module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); } From 5180338e8085bdf0bc653e2321559c7504c169f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 17:03:18 -0800 Subject: [PATCH 081/514] write_xaiger to write __dummy_o__ for -symbols too --- backends/aiger/xaiger.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dd174d5ee..2b7f52d30 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -368,7 +368,7 @@ struct XAigerWriter } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -449,6 +449,7 @@ struct XAigerWriter { dict> symbols; + bool output_seen = false; for (auto wire : module->wires()) { //if (wire->name[0] == '$') @@ -458,14 +459,8 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (sig[i].wire == nullptr) { - if (wire->port_output) - sig[i] = SigBit(wire, i); - else - continue; - } - - if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { + RTLIL::SigBit b(wire, i); + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -474,8 +469,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { - int o = ordered_outputs.at(SigSpec(wire, i)); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -502,6 +498,9 @@ struct XAigerWriter } } + if (omode && !output_seen) + symbols["o0"].push_back("__dummy_o__"); + symbols.sort(); for (auto &sym : symbols) { @@ -692,7 +691,7 @@ struct XAigerBackend : public Backend { log_error("Can't find top module in current design!\n"); XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; From d56f02d1fc1d0482aa57b07f24213f5e0c16faea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 17:03:40 -0800 Subject: [PATCH 082/514] abc9 to use AIGER symbol table, as opposed to map file --- passes/techmap/abc9.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d652ef05a..ce93d3fe0 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -319,10 +319,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); - log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.aig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); + std::string abc_script = stringf("read %s/input.aig; &get -n; ", tempdir_name.c_str()); if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); @@ -376,7 +376,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); - abc_script += stringf("; &ps; &write %s/output.xaig", tempdir_name.c_str()); + abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -map %s/input.symbols %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); // Now 'unexpose' those wires by undoing // the expose operation -- remove them from PO/PI @@ -427,6 +427,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } module->fixup_ports(); + //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); + log_push(); //if (count_output > 0) @@ -509,7 +512,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (ret != 0) 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.xaig"); + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig"); std::ifstream ifs; ifs.open(buffer); if (ifs.fail()) @@ -546,6 +549,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri goto cleanup; } + // Attempt another wideports_split here because there + // exists the possibility that different bits of a port + // could be an input and output, therefore parse_xiager() + // could not combine it into a wideport auto r = wideports_split(w->name.str()); wire = module->wire(r.first); log_assert(wire); @@ -872,6 +879,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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_xiager() + // could not combine it into a wideport auto r = wideports_split(w->name.str()); wire = module->wire(r.first); log_assert(wire); From 51f28a67473f503d310b9add2d7a68fc8523faff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 12:55:47 -0800 Subject: [PATCH 083/514] abc9 to call "clean" once at the end of all abc9_module() calls --- passes/techmap/abc9.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ce93d3fe0..f6ace6a94 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -409,6 +409,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); + 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 @@ -919,8 +921,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // log("Don't call ABC as there is nothing to map.\n"); //} - Pass::call(design, "clean"); - cleanup: if (cleanup) { @@ -928,8 +928,6 @@ cleanup: remove_directory(tempdir_name); } - design->selection_stack.pop_back(); - log_pop(); } @@ -1540,6 +1538,8 @@ struct Abc9Pass : public Pass { } } + Pass::call(design, "clean"); + assign_map.clear(); signal_map.clear(); signal_init.clear(); From 65c8ccf7b57a69f1e1629a3b3df7505073b0474c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:06:23 -0800 Subject: [PATCH 084/514] Add broken testcases --- tests/simple_abc9/abc9.v | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index d387b99eb..ad0e86d24 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -46,3 +46,49 @@ endmodule module abc9_test008_sub(input a, output b); assign b = ~a; endmodule + +// TODO +//module abc9_test009(inout io, input oe); +//reg latch; +//always @(io or oe) +// if (!oe) +// latch <= io; +//assign io = oe ? ~latch : 1'bz; +//endmodule + +// TODO +//module abc9_test010(inout [7:0] io, input oe); +//reg [7:0] latch; +//always @(io or oe) +// if (!oe) +// latch <= io; +//assign io = oe ? ~latch : 1'bz; +//endmodule + +// TODO +//module abc9_test011(inout [7:0] io, input oe); +//reg [7:0] latch; +//always @(io or oe) +// if (!oe) +// latch[3:0] <= io; +// else +// latch[7:4] <= io; +//assign io[3:0] = oe ? ~latch[3:0] : 4'bz; +//assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; +//endmodule + +// TODO +//module abc9_test012(inout [7:0] io, input oe); +//abc9_test012_sub sub(io, oe); +//endmodule +// +//module abc9_test012_sub(inout [7:0] io, input oe); +//reg [7:0] latch; +//always @(io or oe) +// if (!oe) +// latch[3:0] <= io; +// else +// latch[7:4] <= io; +//assign io[3:0] = oe ? ~latch[3:0] : 4'bz; +//assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; +//endmodule From 292f80d231174951b8ebda5b1f9b70b6b95a545a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:20:56 -0800 Subject: [PATCH 085/514] Cleanup abc9 code --- backends/aiger/xaiger.cc | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2b7f52d30..db0395d28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -157,8 +157,11 @@ struct XAigerWriter } } - for (auto bit : input_bits) + for (auto bit : input_bits) { undriven_bits.erase(bit); + // Erase POs that are also PIs + output_bits.erase(bit); + } for (auto bit : output_bits) unused_bits.erase(bit); @@ -215,12 +218,14 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.insert(b); + if (!output_bits.count(b)) + co_bits.insert(b); } } else if (cell->output(c.first)) { SigBit O = sigmap(b); - ci_bits.insert(O); + if (!input_bits.count(O) && !output_bits.count(O)) + ci_bits.insert(O); } else log_abort(); } @@ -236,16 +241,6 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all POs and CIs that are also PIs - for (auto bit : input_bits) { - output_bits.erase(bit); - ci_bits.erase(bit); - } - for (auto bit : output_bits) { - ci_bits.erase(bit); - // POs override COs - co_bits.erase(bit); - } // Erase all CIs that are also COs for (auto bit : co_bits) ci_bits.erase(bit); From 0ca3fd6a1cca6f12db4069ed6f73b814aee2eeaf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:31:52 -0800 Subject: [PATCH 086/514] abc9 not to clean after aigmap --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f6ace6a94..90234ea33 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -403,7 +403,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); - Pass::call(design, "aigmap; clean;"); + Pass::call(design, "aigmap"); handle_loops(design); From 721f6a14fb632b671ba10ed13cafad1263e2b073 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:34:02 -0800 Subject: [PATCH 087/514] read_aiger to accept empty string for clk_name, passable only if no latches --- frontends/aiger/aigerparse.cc | 2 ++ passes/techmap/abc9.cc | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c8ba1bffd..a64729a27 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -524,6 +524,7 @@ void AigerReader::parse_aiger_ascii() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { + log_assert(clk_name != ""); clk_wire = module->wire(clk_name); log_assert(!clk_wire); log_debug("Creating %s\n", clk_name.c_str()); @@ -654,6 +655,7 @@ void AigerReader::parse_aiger_binary() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { + log_assert(clk_name != ""); clk_wire = module->wire(clk_name); log_assert(!clk_wire); log_debug("Creating %s\n", clk_name.c_str()); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 90234ea33..68e54f518 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -523,8 +523,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - buffer = stringf("%s/%s", tempdir_name.c_str(), "input.symbols"); - AigerReader reader(mapped_design, ifs, "\\netlist", "\\clk", buffer, true /* wideports */); + AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, "" /* map_filename */, true /* wideports */); reader.parse_xaiger(); ifs.close(); From c492a3a1c4a36c273cb3ce8266d974a7cb595808 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 18:39:36 -0800 Subject: [PATCH 088/514] write_xaiger duplicate inout port into out port with $inout.out suffix --- backends/aiger/xaiger.cc | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index db0395d28..2c4cdf080 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -213,7 +213,10 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (cell->input(c.first)) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { if (!w->port_input) { SigBit I = sigmap(b); if (I != b) @@ -222,12 +225,11 @@ struct XAigerWriter co_bits.insert(b); } } - else if (cell->output(c.first)) { + if (is_output) { SigBit O = sigmap(b); if (!input_bits.count(O) && !output_bits.count(O)) ci_bits.insert(O); } - else log_abort(); } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; @@ -260,6 +262,27 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + init_map.sort(); input_bits.sort(); output_bits.sort(); From 316232a7dde15363a86b9fbef03d87a86551a333 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 18:40:23 -0800 Subject: [PATCH 089/514] parse_xaiger() to untransform $inout.out output ports --- frontends/aiger/aigerparse.cc | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a64729a27..8f0338f7e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -312,6 +312,7 @@ void AigerReader::parse_xaiger() std::string s; bool comment_seen = false; std::vector> deferred_renames; + std::vector> deferred_inouts; deferred_renames.reserve(inputs.size() + latches.size() + outputs.size()); for (int c = f.peek(); c != EOF; c = f.peek()) { if (comment_seen || c == 'c') { @@ -379,7 +380,10 @@ void AigerReader::parse_xaiger() else if (c == 'o') wire = outputs[l1]; else log_abort(); - deferred_renames.emplace_back(wire, RTLIL::escape_id(s)); + if (s.size() > 10 && s.substr(s.size()-10) == "$inout.out") + deferred_inouts.emplace_back(wire, RTLIL::escape_id(s.substr(0, s.size()-10))); + else + deferred_renames.emplace_back(wire, RTLIL::escape_id(s)); std::getline(f, line); // Ignore up to start of next line ++line_count; @@ -389,7 +393,7 @@ void AigerReader::parse_xaiger() } dict wideports_cache; - for (auto i : deferred_renames) { + for (const auto &i : deferred_renames) { RTLIL::Wire *wire = i.first; RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); @@ -407,6 +411,17 @@ void AigerReader::parse_xaiger() } } + for (const auto &i : deferred_inouts) { + RTLIL::Wire *out_wire = i.first; + log_assert(out_wire->port_output); + out_wire->port_output = false; + RTLIL::Wire *wire = module->wire(i.second); + log_assert(wire); + log_assert(wire->port_input && !wire->port_output); + wire->port_output = true; + module->connect(wire, out_wire); + } + if (!map_filename.empty()) { std::ifstream mf(map_filename); std::string type, symbol; @@ -515,7 +530,7 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); - log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? + log_assert(!(l1 & 1)); // Inputs can't be inverted RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_input = true; inputs.push_back(wire); @@ -586,7 +601,7 @@ void AigerReader::parse_aiger_ascii() if (!wire) wire = createWireIfNotExists(module, l1); else { - if ((wire->port_input || wire->port_output)) { + if (wire->port_input || wire->port_output) { RTLIL::Wire *new_wire = module->addWire(NEW_ID); module->connect(new_wire, wire); wire = new_wire; @@ -717,7 +732,7 @@ void AigerReader::parse_aiger_binary() if (!wire) wire = createWireIfNotExists(module, l1); else { - if ((wire->port_input || wire->port_output)) { + if (wire->port_input || wire->port_output) { RTLIL::Wire *new_wire = module->addWire(NEW_ID); module->connect(new_wire, wire); wire = new_wire; From 967297cd57f80f0b55f7e1d1e00fd6c20b8fb52a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 18:40:53 -0800 Subject: [PATCH 090/514] abc9 cleanup --- passes/techmap/abc9.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 68e54f518..de47de92e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -892,21 +892,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } log_assert(GetSize(signal) >= GetSize(remap_wire)); + log_assert(w->port_input || w->port_output); + RTLIL::SigSig conn; if (w->port_input) { - RTLIL::SigSig conn; conn.first = remap_wire; conn.second = signal; in_wires++; - module->connect(conn); } - else if (w->port_output) { - RTLIL::SigSig conn; + if (w->port_output) { conn.first = signal; conn.second = remap_wire; out_wires++; - module->connect(conn); } - else log_abort(); + module->connect(conn); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 8f02c846f602882478469e86dbd598ade23d1d74 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 11:37:34 -0800 Subject: [PATCH 091/514] parse_xaiger() to cope with multi bit inouts --- frontends/aiger/aigerparse.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8f0338f7e..9a9f2b2d8 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -380,11 +380,22 @@ void AigerReader::parse_xaiger() else if (c == 'o') wire = outputs[l1]; else log_abort(); + if (wideports && (wire->port_input || wire->port_output)) { + RTLIL::IdString escaped_symbol; + int index; + std::tie(escaped_symbol,index) = wideports_split(RTLIL::escape_id(s)); + if (escaped_symbol.size() > 10 && escaped_symbol.substr(escaped_symbol.size()-10) == "$inout.out") { + deferred_inouts.emplace_back(wire, stringf("%s[%d]", escaped_symbol.substr(0, escaped_symbol.size()-10).c_str(), index)); + goto next_line; + } + } + if (s.size() > 10 && s.substr(s.size()-10) == "$inout.out") deferred_inouts.emplace_back(wire, RTLIL::escape_id(s.substr(0, s.size()-10))); else deferred_renames.emplace_back(wire, RTLIL::escape_id(s)); +next_line: std::getline(f, line); // Ignore up to start of next line ++line_count; } From 66b5f5166b358ae7efebd278ad32cd05f3eb72be Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 11:39:17 -0800 Subject: [PATCH 092/514] Enable two inout tests --- tests/simple_abc9/abc9.v | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index ad0e86d24..8a809e480 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -47,23 +47,21 @@ module abc9_test008_sub(input a, output b); assign b = ~a; endmodule -// TODO -//module abc9_test009(inout io, input oe); -//reg latch; -//always @(io or oe) -// if (!oe) -// latch <= io; -//assign io = oe ? ~latch : 1'bz; -//endmodule +module abc9_test009(inout io, input oe); +reg latch; +always @(io or oe) + if (!oe) + latch <= io; +assign io = oe ? ~latch : 1'bz; +endmodule -// TODO -//module abc9_test010(inout [7:0] io, input oe); -//reg [7:0] latch; -//always @(io or oe) -// if (!oe) -// latch <= io; -//assign io = oe ? ~latch : 1'bz; -//endmodule +module abc9_test010(inout [7:0] io, input oe); +reg [7:0] latch; +always @(io or oe) + if (!oe) + latch <= io; +assign io = oe ? ~latch : 8'bz; +endmodule // TODO //module abc9_test011(inout [7:0] io, input oe); From 3ea0161ae7f6111cb435c839eff694476a6527ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:04:16 -0800 Subject: [PATCH 093/514] Add IdString::ends_with() --- kernel/rtlil.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f877622aa..eb71fec7b 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -222,6 +222,12 @@ namespace RTLIL return std::string(c_str() + pos, len); } + bool ends_with(const char* suffix) const { + size_t len = strlen(suffix); + if (size() < len) return false; + return substr(size()-len) == suffix; + } + size_t size() const { return str().size(); } From da076344cc4a1777a4c4220b71aefd3768dcfd0b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:04:45 -0800 Subject: [PATCH 094/514] parse_xaiger() to really pass single and multi-bit inout tests --- frontends/aiger/aigerparse.cc | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9a9f2b2d8..c882f8512 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -380,20 +380,22 @@ void AigerReader::parse_xaiger() else if (c == 'o') wire = outputs[l1]; else log_abort(); - if (wideports && (wire->port_input || wire->port_output)) { - RTLIL::IdString escaped_symbol; + RTLIL::IdString escaped_s = RTLIL::escape_id(s); + + if (escaped_s.ends_with("$inout.out")) { + deferred_inouts.emplace_back(wire, escaped_s.substr(0, escaped_s.size()-10)); + goto next_line; + } + else if (wideports && (wire->port_input || wire->port_output)) { + RTLIL::IdString wide_symbol; int index; - std::tie(escaped_symbol,index) = wideports_split(RTLIL::escape_id(s)); - if (escaped_symbol.size() > 10 && escaped_symbol.substr(escaped_symbol.size()-10) == "$inout.out") { - deferred_inouts.emplace_back(wire, stringf("%s[%d]", escaped_symbol.substr(0, escaped_symbol.size()-10).c_str(), index)); + std::tie(wide_symbol,index) = wideports_split(escaped_s.str()); + if (wide_symbol.ends_with("$inout.out")) { + deferred_inouts.emplace_back(wire, stringf("%s[%d]", wide_symbol.substr(0, wide_symbol.size()-10).c_str(), index)); goto next_line; } } - - if (s.size() > 10 && s.substr(s.size()-10) == "$inout.out") - deferred_inouts.emplace_back(wire, RTLIL::escape_id(s.substr(0, s.size()-10))); - else - deferred_renames.emplace_back(wire, RTLIL::escape_id(s)); + deferred_renames.emplace_back(wire, escaped_s); next_line: std::getline(f, line); // Ignore up to start of next line From 8e883d92edef57214093ae7c5d8be6edb8462c8d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:17:51 -0800 Subject: [PATCH 095/514] write_xaiger to behave for undriven/unused inouts --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2c4cdf080..a4ef89931 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -158,13 +158,15 @@ struct XAigerWriter } for (auto bit : input_bits) { - undriven_bits.erase(bit); + if (!bit.wire->port_output) + undriven_bits.erase(bit); // Erase POs that are also PIs output_bits.erase(bit); } for (auto bit : output_bits) - unused_bits.erase(bit); + if (!bit.wire->port_input) + unused_bits.erase(bit); for (auto cell : module->cells()) { @@ -237,6 +239,27 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { @@ -262,27 +285,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - for (auto bit : input_bits) { - RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output) { - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); - if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); - SigBit new_bit(new_wire, bit.offset); - module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); - } - } - init_map.sort(); input_bits.sort(); output_bits.sort(); From 7cac3b1c8bab3ba7749f4e272544f3f5f3dfa1e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:18:28 -0800 Subject: [PATCH 096/514] abc9 -- multiple connections for inouts --- passes/techmap/abc9.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index de47de92e..3ec365bc0 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -898,13 +898,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri conn.first = remap_wire; conn.second = signal; in_wires++; + module->connect(conn); } if (w->port_output) { conn.first = signal; conn.second = remap_wire; out_wires++; + module->connect(conn); } - module->connect(conn); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From dfb23a79dd0e2ffbe4f058eadb552d8194540eef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:18:48 -0800 Subject: [PATCH 097/514] Uncomment out more tests --- tests/simple_abc9/abc9.v | 62 ++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 8a809e480..eca340693 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -63,30 +63,44 @@ always @(io or oe) assign io = oe ? ~latch : 8'bz; endmodule -// TODO -//module abc9_test011(inout [7:0] io, input oe); -//reg [7:0] latch; -//always @(io or oe) -// if (!oe) -// latch[3:0] <= io; -// else -// latch[7:4] <= io; -//assign io[3:0] = oe ? ~latch[3:0] : 4'bz; -//assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; -//endmodule +module abc9_test011(inout io, input oe); +reg latch; +always @(io or oe) + if (!oe) + latch <= io; +//assign io = oe ? ~latch : 8'bz; +endmodule -// TODO -//module abc9_test012(inout [7:0] io, input oe); -//abc9_test012_sub sub(io, oe); -//endmodule -// -//module abc9_test012_sub(inout [7:0] io, input oe); -//reg [7:0] latch; +module abc9_test012(inout io, input oe); +reg latch; //always @(io or oe) // if (!oe) -// latch[3:0] <= io; -// else -// latch[7:4] <= io; -//assign io[3:0] = oe ? ~latch[3:0] : 4'bz; -//assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; -//endmodule +// latch <= io; +assign io = oe ? ~latch : 8'bz; +endmodule + +module abc9_test013(inout [3:0] io, input oe); +reg [3:0] latch; +always @(io or oe) + if (!oe) + latch[3:0] <= io[3:0]; + else + latch[7:4] <= io; +assign io[3:0] = oe ? ~latch[3:0] : 4'bz; +assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; +endmodule + +module abc9_test014(inout [7:0] io, input oe); +abc9_test012_sub sub(io, oe); +endmodule + +module abc9_test012_sub(inout [7:0] io, input oe); +reg [7:0] latch; +always @(io or oe) + if (!oe) + latch[3:0] <= io; + else + latch[7:4] <= io; +assign io[3:0] = oe ? ~latch[3:0] : 4'bz; +assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; +endmodule From 36efec01b8b2b29fadc015d5e061a3a21319aea5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:37:22 -0700 Subject: [PATCH 098/514] Fix spacing --- frontends/aiger/aigerparse.cc | 58 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c882f8512..0eaf64c6e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -805,13 +805,13 @@ struct AigerFrontend : public Frontend { log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); log(" this name (default: clk)\n"); log("\n"); - log(" -map \n"); - log(" read file with port and latch symbols\n"); + log(" -map \n"); + log(" read file with port and latch symbols\n"); + log("\n"); + log(" -wideports\n"); + log(" Merge ports that match the pattern 'name[int]' into a single\n"); + log(" multi-bit port 'name'.\n"); log("\n"); - log(" -wideports\n"); - log(" Merge ports that match the pattern 'name[int]' into a single\n"); - log(" multi-bit port 'name'.\n"); - log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -822,28 +822,28 @@ struct AigerFrontend : public Frontend { std::string map_filename; bool wideports = false; - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-module_name" && argidx+1 < args.size()) { - module_name = RTLIL::escape_id(args[++argidx]); - continue; - } - if (arg == "-clk_name" && argidx+1 < args.size()) { - clk_name = RTLIL::escape_id(args[++argidx]); - continue; - } - if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) { - map_filename = args[++argidx]; - continue; - } - if (arg == "-wideports") { - wideports = true; - continue; - } - break; - } - extra_args(f, filename, args, argidx); + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-module_name" && argidx+1 < args.size()) { + module_name = RTLIL::escape_id(args[++argidx]); + continue; + } + if (arg == "-clk_name" && argidx+1 < args.size()) { + clk_name = RTLIL::escape_id(args[++argidx]); + continue; + } + if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + continue; + } + if (arg == "-wideports") { + wideports = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); if (module_name.empty()) { #ifdef _WIN32 @@ -858,7 +858,7 @@ struct AigerFrontend : public Frontend { } AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports); - reader.parse_aiger(); + reader.parse_aiger(); } } AigerFrontend; From 12c34136ba9dfaebe6a33b8e442ed03208c8b217 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:40:17 -0700 Subject: [PATCH 099/514] More space fixing --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3ec365bc0..da3d36354 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); design->selection_stack.pop_back(); @@ -1536,7 +1536,7 @@ struct Abc9Pass : public Pass { } } - Pass::call(design, "clean"); + Pass::call(design, "clean"); assign_map.clear(); signal_map.clear(); From 3fc474aa73cb447f22e9ca35687b054102f4be32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:06:44 -0700 Subject: [PATCH 100/514] Add support for synth_xilinx -abc9 and ignore abc9 -dress opt --- passes/techmap/abc9.cc | 5 +++++ techlibs/xilinx/synth_xilinx.cc | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index da3d36354..6e2e349ee 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1237,6 +1237,11 @@ struct Abc9Pass : public Pass { map_mux16 = true; continue; } + if (arg == "-dress") { + // TODO + abc_dress = true; + continue; + } if (arg == "-g" && argidx+1 < args.size()) { for (auto g : split_tokens(args[++argidx], ",")) { vector gate_list; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 805ae8e6e..090bcce85 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -80,6 +80,9 @@ struct SynthXilinxPass : public Pass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); + log(" -abc9\n"); + log(" use abc9 instead of abc\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); log("\n"); @@ -142,6 +145,7 @@ struct SynthXilinxPass : public Pass std::string edif_file; std::string blif_file; std::string run_from, run_to; + std::string abc = "abc"; bool flatten = false; bool retime = false; bool vpr = false; @@ -191,6 +195,10 @@ struct SynthXilinxPass : public Pass nodram = true; continue; } + if (args[argidx] == "-abc9") { + abc = "abc9"; + continue; + } break; } extra_args(args, argidx, design); @@ -267,7 +275,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } From 3b6f85b0a6fb08b44dfa7417fce1aeefe9f20e3e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:09:43 -0700 Subject: [PATCH 101/514] Comment out --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6e2e349ee..ec4a28d08 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1239,7 +1239,7 @@ struct Abc9Pass : public Pass { } if (arg == "-dress") { // TODO - abc_dress = true; + //abc_dress = true; continue; } if (arg == "-g" && argidx+1 < args.size()) { From bd523abef5babcc16fbdd67dbf868bd601acaced Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:32:58 -0700 Subject: [PATCH 102/514] Add 'setundef -zero' call prior to aigmap in abc9 --- passes/techmap/abc9.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ec4a28d08..b0326372e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -403,6 +403,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); + // Adopt same behaviour as abc + // TODO: How to specify don't-care to abc9? + Pass::call(design, "setundef -zero"); + Pass::call(design, "aigmap"); handle_loops(design); From 7e304c362bc342abaed46f1906cad8b118ba45e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:58:06 -0700 Subject: [PATCH 103/514] Add "-box" option to abc9 --- passes/techmap/abc9.cc | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b0326372e..765dc7fb8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -272,7 +272,7 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode) + const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file) { module = current_module; map_autoidx = autoidx++; @@ -329,8 +329,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!constr_file.empty()) abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); } else - if (!lut_costs.empty()) + if (!lut_costs.empty()) { abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + if (!box_file.empty()) + abc_script += stringf("read_box -v %s; ", box_file.c_str()); + } else abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); @@ -1004,7 +1007,7 @@ struct Abc9Pass : public Pass { log(" file format).\n"); log("\n"); log(" -constr \n"); - log(" pass this file with timing constraints to ABC. use with -liberty.\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 \n"); @@ -1094,6 +1097,9 @@ struct Abc9Pass : public Pass { 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 \n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); + log("\n"); log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -1123,7 +1129,7 @@ struct Abc9Pass : public Pass { #else std::string exe_file = proc_self_dirname() + "yosys-abc"; #endif - std::string script_file, liberty_file, constr_file, clk_str; + std::string script_file, liberty_file, constr_file, clk_str, box_file; std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; @@ -1169,8 +1175,8 @@ struct Abc9Pass : public Pass { continue; } if (arg == "-constr" && argidx+1 < args.size()) { - rewrite_filename(constr_file); constr_file = args[++argidx]; + rewrite_filename(constr_file); if (!constr_file.empty() && !is_absolute_path(constr_file)) constr_file = std::string(pwd) + "/" + constr_file; continue; @@ -1357,6 +1363,13 @@ struct Abc9Pass : public Pass { markgroups = true; continue; } + if (arg == "-box" && argidx+1 < args.size()) { + box_file = args[++argidx]; + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file)) + box_file = std::string(pwd) + "/" + box_file; + continue; + } break; } extra_args(args, argidx, design); @@ -1395,7 +1408,8 @@ struct Abc9Pass : public Pass { 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); + delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, + box_file); continue; } @@ -1540,7 +1554,8 @@ struct Abc9Pass : public Pass { en_polarity = std::get<2>(it.first); 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); + keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, + box_file); assign_map.set(mod); } } From 2ae26b986cd550e4d3ce4dc5c4f7235144a6f83c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:58:58 -0700 Subject: [PATCH 104/514] Add techlibs/xilinx/cells.box --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/cells.box | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 techlibs/xilinx/cells.box diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index d68f03bb4..9937c0c9c 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,6 +30,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.box)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/cells.box b/techlibs/xilinx/cells.box new file mode 100644 index 000000000..31ad4a656 --- /dev/null +++ b/techlibs/xilinx/cells.box @@ -0,0 +1,5 @@ +MUXF7 1 0 2 1 +1 1 + +MUXF8 2 0 2 1 +1 1 From f2042fc7c43af9f43d42fdd2e8034963122ff5eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 11:01:46 -0700 Subject: [PATCH 105/514] synth_xilinx with abc9 to use -box --- techlibs/xilinx/synth_xilinx.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 090bcce85..eb37feb83 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -275,7 +275,10 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + if (abc == "abc9") + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20 -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); + else + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } From d536379c62d926967d5e7743b32990167f91e762 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 14:31:31 -0700 Subject: [PATCH 106/514] Add "-lut " support to abc9 --- passes/techmap/abc9.cc | 44 +++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 765dc7fb8..e26920f20 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -272,7 +272,7 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode, std::string box_file) + const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file) { module = current_module; map_autoidx = autoidx++; @@ -334,6 +334,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!box_file.empty()) abc_script += stringf("read_box -v %s; ", box_file.c_str()); } + else + if (!lut_file.empty()) { + abc_script += stringf("read_lut %s; ", lut_file.c_str()); + if (!box_file.empty()) + abc_script += stringf("read_box -v %s; ", box_file.c_str()); + } else abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); @@ -348,11 +354,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script += script_file[i]; } else abc_script += stringf("source %s", script_file.c_str()); - } else if (!lut_costs.empty()) { - bool all_luts_cost_same = true; - for (int this_cost : lut_costs) - if (this_cost != lut_costs.front()) - all_luts_cost_same = false; + } else if (!lut_costs.empty() || !lut_file.empty()) { + //bool all_luts_cost_same = true; + //for (int this_cost : lut_costs) + // if (this_cost != lut_costs.front()) + // all_luts_cost_same = false; abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; //if (all_luts_cost_same && !fast_mode) // abc_script += "; lutpack {S}"; @@ -579,7 +585,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Cell *cell; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); - if (!lut_costs.empty()) { + if (!lut_costs.empty() || !lut_file.empty()) { // ABC can return NOT gates that drive POs if (a_bit.wire->port_input) { // If it's a NOT gate that comes from a primary input directly @@ -1044,6 +1050,9 @@ struct Abc9Pass : public Pass { log(" the area cost doubles with each additional input bit. the delay cost\n"); log(" is still constant for all lut widths.\n"); log("\n"); + log(" -lut \n"); + log(" pass this file with lut library to ABC.\n"); + log("\n"); log(" -luts ,,,:,..\n"); log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); @@ -1129,7 +1138,7 @@ struct Abc9Pass : public Pass { #else std::string exe_file = proc_self_dirname() + "yosys-abc"; #endif - std::string script_file, liberty_file, constr_file, clk_str, box_file; + 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"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; @@ -1205,8 +1214,17 @@ struct Abc9Pass : public Pass { 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; + pos = arg.find_first_of('.'); + if (pos != string::npos) { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file)) + lut_file = std::string(pwd) + "/" + lut_file; + } + else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } } lut_costs.clear(); for (int i = 0; i < lut_mode; i++) @@ -1374,7 +1392,7 @@ struct Abc9Pass : public Pass { } extra_args(args, argidx, design); - if (!lut_costs.empty() && !liberty_file.empty()) + if ((!lut_costs.empty() || !lut_file.empty()) && !liberty_file.empty()) log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); @@ -1409,7 +1427,7 @@ struct Abc9Pass : public Pass { 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); + box_file, lut_file); continue; } @@ -1555,7 +1573,7 @@ struct Abc9Pass : public Pass { 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); + box_file, lut_file); assign_map.set(mod); } } From b9e19071b8596b8d06b99cbb653325c0c9dc330f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 14:32:10 -0700 Subject: [PATCH 107/514] Add delays to cells.box --- techlibs/xilinx/cells.box | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells.box b/techlibs/xilinx/cells.box index 31ad4a656..c8092db6e 100644 --- a/techlibs/xilinx/cells.box +++ b/techlibs/xilinx/cells.box @@ -1,5 +1,13 @@ -MUXF7 1 0 2 1 -1 1 +# Max delays from https://pastebin.com/v2hrcksd +# from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 -MUXF8 2 0 2 1 -1 1 +# F7BMUX slower than F7AMUX +# Inputs: 0 1 S0 +# Outputs: OUT +F7BMUX 1 0 3 1 +217 223 296 + +# Inputs: 0 1 S0 +# Outputs: OUT +MUXF8 2 0 3 1 +104 94 273 From fd88ab5c834a45f4828a03fe7722b321e5f7c032 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 14:32:39 -0700 Subject: [PATCH 108/514] synth_xilinx to call abc with -lut +/xilinx/cells.lut --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index eb37feb83..e2a2dfeeb 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -276,9 +276,9 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { if (abc == "abc9") - Pass::call(design, abc + " -luts 2:2,3,6:5,10,20 -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); else - Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -lut +/xilinx/cells.lut" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } From 3e368593eb22d16de60c44ea721ca146082d3472 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 14:33:37 -0700 Subject: [PATCH 109/514] Add cells.lut to techlibs/xilinx/ --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/cells.lut | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 techlibs/xilinx/cells.lut diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 9937c0c9c..432bb0770 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -31,6 +31,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.box)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.lut)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/cells.lut b/techlibs/xilinx/cells.lut new file mode 100644 index 000000000..3f3b69a8e --- /dev/null +++ b/techlibs/xilinx/cells.lut @@ -0,0 +1,15 @@ +# Max delays from https://pastebin.com/v2hrcksd +# from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 + +# Since LUT delays are pushed onto the fabric as routing delays, +# assume each input costs +100ps + +# K area delay +1 11 224 +2 12 224 324 +3 13 224 324 424 +4 14 224 324 424 524 +5 15 224 324 424 524 624 +6 20 224 324 424 524 624 724 +7 40 224 324 424 524 624 724 1020 +8 80 224 324 424 524 624 724 1020 1293 From 4dac9818bde02222f951c25ada5f3fd651ea4e36 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 08:49:39 -0700 Subject: [PATCH 110/514] Update LUT delays --- techlibs/xilinx/cells.lut | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/cells.lut b/techlibs/xilinx/cells.lut index 3f3b69a8e..a1d9b9c42 100644 --- a/techlibs/xilinx/cells.lut +++ b/techlibs/xilinx/cells.lut @@ -1,15 +1,12 @@ # Max delays from https://pastebin.com/v2hrcksd # from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 -# Since LUT delays are pushed onto the fabric as routing delays, -# assume each input costs +100ps - # K area delay -1 11 224 -2 12 224 324 -3 13 224 324 424 -4 14 224 324 424 524 -5 15 224 324 424 524 624 -6 20 224 324 424 524 624 724 -7 40 224 324 424 524 624 724 1020 -8 80 224 324 424 524 624 724 1020 1293 +1 11 624 +2 12 624 +3 13 624 +4 14 624 +5 15 624 +6 20 724 +7 40 1020 +8 80 1293 From e0b46eb4cbadafa5f03a5337f761d0ede2b993fa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 08:49:55 -0700 Subject: [PATCH 111/514] WIP for $shiftx to wide mux --- techlibs/xilinx/cells_map.v | 64 ++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index d5801c0fc..4f5c7ff18 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -17,4 +17,66 @@ * */ -// Empty for now +module \$shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + generate + genvar i; + if (B_WIDTH < 3) begin + reg _TECHMAP_FAIL_; + assign _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH == 3) begin + localparam a_width0 = Y_WIDTH * (2 ** (B_WIDTH-1)); + localparam a_widthN = A_WIDTH - a_width0; + wire [Y_WIDTH-1:0] T0, T1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + //MUXF7 fpga_mux[Y_WIDTH-1:0] (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + for (i = 0; i < Y_WIDTH; i++) + MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + end + else if (B_WIDTH == 4) begin + localparam a_width0 = Y_WIDTH * (2 ** (B_WIDTH-2)); + localparam num_mux8 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; + wire [Y_WIDTH*B_WIDTH-1:0] T; + wire [Y_WIDTH-1:0] T0, T1; + for (i = 0; i < B_WIDTH; i++) + if (i < num_mux8) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + else if (i == num_mux8 && A_WIDTH > i*a_width0) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + else + assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + for (i = 0; i < Y_WIDTH; i++) begin + MUXF7 fpga_mux_0 (.I0(T[i*B_WIDTH+0]), .I1(T[i*B_WIDTH+1]), .S(B[B_WIDTH-2]), .O(T0[i])); + MUXF7 fpga_mux_1 (.I0(T[i*B_WIDTH+2]), .I1(T[i*B_WIDTH+3]), .S(B[B_WIDTH-2]), .O(T1[i])); + MUXF8 fpga_mux_2 (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + end + end + else begin + localparam a_width0 = Y_WIDTH * (2 ** 4); + localparam num_mux16 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux16*a_width0; + wire [Y_WIDTH*(2**(B_WIDTH-4))-1:0] T; + for (i = 0; i < 2 ** (B_WIDTH-4); i++) + if (i < num_mux16) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + else if (i == num_mux16 && a_widthN > 0) begin + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + end + else + assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(Y_WIDTH*(2**(B_WIDTH-4))), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + end + endgenerate +endmodule From 526aef9c2a9d61721add1c5ef1f85d439bfbb61e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 08:50:31 -0700 Subject: [PATCH 112/514] Move map_cells to before map_luts --- techlibs/xilinx/synth_xilinx.cc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e2a2dfeeb..6d3999ae0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -264,25 +264,15 @@ struct SynthXilinxPass : public Pass Pass::call(design, "opt -full"); if (vpr) { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); } else { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); } Pass::call(design, "hierarchy -check"); Pass::call(design, "opt -fast"); } - if (check_label(active, run_from, run_to, "map_luts")) - { - if (abc == "abc9") - Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); - else - Pass::call(design, abc + " -lut +/xilinx/cells.lut" + string(retime ? " -dff" : "")); - Pass::call(design, "clean"); - Pass::call(design, "techmap -map +/xilinx/lut_map.v"); - } - if (check_label(active, run_from, run_to, "map_cells")) { Pass::call(design, "techmap -map +/xilinx/cells_map.v"); @@ -291,6 +281,17 @@ struct SynthXilinxPass : public Pass Pass::call(design, "clean"); } + if (check_label(active, run_from, run_to, "map_luts")) + { + Pass::call(design, "techmap -map +/techmap.v"); + if (abc == "abc9") + Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); + else + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, "clean"); + Pass::call(design, "techmap -map +/xilinx/lut_map.v"); + } + if (check_label(active, run_from, run_to, "check")) { Pass::call(design, "hierarchy -check"); From 1ec949d5edfb6b13b8bf412763ae272a47fec894 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 09:02:42 -0700 Subject: [PATCH 113/514] Tidy up --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 4f5c7ff18..ff33cf8ff 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -53,7 +53,7 @@ module \$shiftx (A, B, Y); for (i = 0; i < B_WIDTH; i++) if (i < num_mux8) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); - else if (i == num_mux8 && A_WIDTH > i*a_width0) + else if (i == num_mux8 && a_widthN > 0) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); else assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; From 17a02df05cb04bf9c597564b130e556f186154f3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 12:36:06 -0700 Subject: [PATCH 114/514] ff_map.v after abc --- techlibs/xilinx/synth_xilinx.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6d3999ae0..9178182fb 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -264,9 +264,9 @@ struct SynthXilinxPass : public Pass Pass::call(design, "opt -full"); if (vpr) { - Pass::call(design, "techmap -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); } else { - Pass::call(design, "techmap -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); } Pass::call(design, "hierarchy -check"); @@ -276,8 +276,6 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { Pass::call(design, "techmap -map +/xilinx/cells_map.v"); - Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); Pass::call(design, "clean"); } @@ -289,7 +287,9 @@ struct SynthXilinxPass : public Pass else Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); - Pass::call(design, "techmap -map +/xilinx/lut_map.v"); + Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v"); + Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); } if (check_label(active, run_from, run_to, "check")) From 1a49cf29d84c16f26b524b989e8fa07b3c6cab1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 14:02:23 -0700 Subject: [PATCH 115/514] parse_aiger() to rename all $lut cells after "clean" --- frontends/aiger/aigerparse.cc | 45 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0eaf64c6e..b752d3127 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -165,15 +165,9 @@ void AigerReader::parse_aiger() int width = wp.second + 1; RTLIL::Wire *wire = module->wire(name); - if (wire) { - RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); - + if (wire) module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); - if (driver) - module->rename(driver, stringf("%s$lut", wire->name.c_str())); - } - // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; @@ -210,6 +204,15 @@ void AigerReader::parse_aiger() design->add(module); Pass::call(design, "clean"); + + for (auto cell : module->cells().to_vector()) { + if (cell->type != "$lut") continue; + auto y_port = cell->getPort("\\Y").as_bit(); + if (y_port.wire->width == 1) + module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); + else + module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); + } } static uint32_t parse_xaiger_literal(std::istream &f) @@ -357,7 +360,7 @@ void AigerReader::parse_xaiger() RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); log_assert(output_cell); module->remove(output_cell); - module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); + module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } else if (c == 'n') { @@ -408,13 +411,9 @@ next_line: dict wideports_cache; for (const auto &i : deferred_renames) { RTLIL::Wire *wire = i.first; - RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); module->rename(wire, i.second); - if (driver) - module->rename(driver, stringf("%s$lut", wire->name.c_str())); - if (wideports && (wire->port_input || wire->port_output)) { RTLIL::IdString escaped_symbol; int index; @@ -461,8 +460,6 @@ next_line: log_assert(wire); log_assert(wire->port_output); - RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); - if (index == 0) module->rename(wire, escaped_symbol); else if (index > 0) { @@ -470,9 +467,6 @@ next_line: if (wideports) wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); } - - if (driver) - module->rename(driver, stringf("%s$lut", wire->name.c_str())); } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); @@ -484,15 +478,9 @@ next_line: int width = wp.second + 1; RTLIL::Wire *wire = module->wire(name); - if (wire) { - RTLIL::Cell* driver = module->cell(stringf("%s$lut", wire->name.c_str())); - + if (wire) module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); - if (driver) - module->rename(driver, stringf("%s$lut", wire->name.c_str())); - } - // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; @@ -529,6 +517,15 @@ next_line: design->add(module); Pass::call(design, "clean"); + + for (auto cell : module->cells().to_vector()) { + if (cell->type != "$lut") continue; + auto y_port = cell->getPort("\\Y").as_bit(); + if (y_port.wire->width == 1) + module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); + else + module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); + } } void AigerReader::parse_aiger_ascii() From 32561332b21b7b072fa6619f0bbb29a69cb30f33 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 14:48:58 -0700 Subject: [PATCH 116/514] Update doc for synth_xilinx --- techlibs/xilinx/synth_xilinx.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 9178182fb..10902a560 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -113,19 +113,20 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); + log(" techmap -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); - log(" map_luts:\n"); - log(" abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n"); - log(" abc -lut 5 [-dff] (with '-vpr' only!)\n"); - log(" clean\n"); - log("\n"); log(" map_cells:\n"); log(" techmap -map +/xilinx/cells_map.v\n"); + log(" clean\n"); + log("\n"); + log(" map_luts:\n"); + log(" techmap -map +/techmap.v\n"); + log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); + log(" clean\n"); + log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v\n"); log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n"); log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); - log(" clean\n"); log("\n"); log(" check:\n"); log(" hierarchy -check\n"); From 3f5dab0d09f881d78fca73c54c20118c52b2e563 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 14:51:10 -0700 Subject: [PATCH 117/514] Fix for when B_SIGNED = 1 --- techlibs/xilinx/cells_map.v | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index ff33cf8ff..758d2ade3 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -28,12 +28,19 @@ module \$shiftx (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + generate genvar i; if (B_WIDTH < 3) begin - reg _TECHMAP_FAIL_; + wire _TECHMAP_FAIL_; assign _TECHMAP_FAIL_ = 1; end + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + else if (B_SIGNED && _TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) begin + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + end else if (B_WIDTH == 3) begin localparam a_width0 = Y_WIDTH * (2 ** (B_WIDTH-1)); localparam a_widthN = A_WIDTH - a_width0; From 3d577586fde783829aae213fac4d1480ce1b8c53 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 16:15:23 -0700 Subject: [PATCH 118/514] Try splitting $shiftx with Y_WIDTH > 1 into Y_WIDTH = 1 --- techlibs/xilinx/cells_map.v | 89 ++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 758d2ade3..253678028 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -32,58 +32,65 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate - genvar i; - if (B_WIDTH < 3) begin - wire _TECHMAP_FAIL_; - assign _TECHMAP_FAIL_ = 1; + genvar i, j; + if (B_SIGNED) begin + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; end - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - else if (B_SIGNED && _TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); - end - else if (B_WIDTH == 3) begin - localparam a_width0 = Y_WIDTH * (2 ** (B_WIDTH-1)); - localparam a_widthN = A_WIDTH - a_width0; - wire [Y_WIDTH-1:0] T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - //MUXF7 fpga_mux[Y_WIDTH-1:0] (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); - for (i = 0; i < Y_WIDTH; i++) - MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); - end - else if (B_WIDTH == 4) begin - localparam a_width0 = Y_WIDTH * (2 ** (B_WIDTH-2)); - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [Y_WIDTH*B_WIDTH-1:0] T; - wire [Y_WIDTH-1:0] T0, T1; - for (i = 0; i < B_WIDTH; i++) - if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); - else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); - else - assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + else if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) begin - MUXF7 fpga_mux_0 (.I0(T[i*B_WIDTH+0]), .I1(T[i*B_WIDTH+1]), .S(B[B_WIDTH-2]), .O(T0[i])); - MUXF7 fpga_mux_1 (.I0(T[i*B_WIDTH+2]), .I1(T[i*B_WIDTH+3]), .S(B[B_WIDTH-2]), .O(T1[i])); - MUXF8 fpga_mux_2 (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + wire [A_WIDTH/Y_WIDTH-1:0] A_i; + for (j = 0; j < A_WIDTH/Y_WIDTH; j++) + assign A_i[j] = A[i*Y_WIDTH+j]; + wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_i = B/Y_WIDTH; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_i), .Y(Y[i])); end end + else if (B_WIDTH < 3) begin + wire _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH == 3) begin + localparam a_width0 = 2 ** 2; + localparam a_widthN = A_WIDTH - a_width0; + wire T0, T1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + end + else if (B_WIDTH == 4) begin + localparam a_width0 = 2 ** 3; + localparam num_mux8 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; + wire [B_WIDTH-1:0] T; + wire T0, T1; + for (i = 0; i < B_WIDTH; i++) + if (i < num_mux8) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); + else if (i == num_mux8 && a_widthN > 0) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = 1'bx; + MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[B_WIDTH-2]), .O(T0)); + MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[B_WIDTH-2]), .O(T1)); + MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + end else begin - localparam a_width0 = Y_WIDTH * (2 ** 4); + localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [Y_WIDTH*(2**(B_WIDTH-4))-1:0] T; + wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) - if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + if (i < num_mux16) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); end else - assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(Y_WIDTH*(2**(B_WIDTH-4))), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + assign T[i] = 1'bx; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule From cd7b2de27f4ffd097af7662a0390a5c86e5532a3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 18:05:09 -0700 Subject: [PATCH 119/514] WIP for cells_map.v -- maybe working? --- techlibs/xilinx/cells_map.v | 59 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 253678028..93d60f60b 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -31,6 +31,7 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + localparam NUM = A_WIDTH/Y_WIDTH; generate genvar i, j; if (B_SIGNED) begin @@ -40,57 +41,51 @@ module \$shiftx (A, B, Y); else wire _TECHMAP_FAIL_ = 1; end - else if (Y_WIDTH > 1) begin - for (i = 0; i < Y_WIDTH; i++) begin - wire [A_WIDTH/Y_WIDTH-1:0] A_i; - for (j = 0; j < A_WIDTH/Y_WIDTH; j++) - assign A_i[j] = A[i*Y_WIDTH+j]; - wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_i = B/Y_WIDTH; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_i), .Y(Y[i])); - end - end - else if (B_WIDTH < 3) begin + else if (NUM <= 4) begin wire _TECHMAP_FAIL_ = 1; end - else if (B_WIDTH == 3) begin - localparam a_width0 = 2 ** 2; + else if (NUM <= 8) begin + localparam a_width0 = Y_WIDTH * 4; localparam a_widthN = A_WIDTH - a_width0; - wire T0, T1; + wire [Y_WIDTH-1:0] T0, T1; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + for (i = 0; i < Y_WIDTH; i++) + MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); end - else if (B_WIDTH == 4) begin - localparam a_width0 = 2 ** 3; + else if (NUM <= 16) begin + localparam a_width0 = Y_WIDTH * 4; localparam num_mux8 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [B_WIDTH-1:0] T; - wire T0, T1; - for (i = 0; i < B_WIDTH; i++) + wire [Y_WIDTH*4-1:0] T; + wire [Y_WIDTH-1:0] T0, T1; + for (i = 0; i < 4; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); else - assign T[i] = 1'bx; - MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[B_WIDTH-2]), .O(T0)); - MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[B_WIDTH-2]), .O(T1)); - MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + for (i = 0; i < Y_WIDTH; i++) begin + MUXF7 fpga_mux_0 (.I0(T[0*Y_WIDTH+i]), .I1(T[1*Y_WIDTH+i]), .S(B[B_WIDTH-2]), .O(T0[i])); + MUXF7 fpga_mux_1 (.I0(T[2*Y_WIDTH+i]), .I1(T[3*Y_WIDTH+i]), .S(B[B_WIDTH-2]), .O(T1[i])); + MUXF8 fpga_mux_2 (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + end end else begin - localparam a_width0 = 2 ** 4; + localparam a_width0 = Y_WIDTH * 16; localparam num_mux16 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) + wire [Y_WIDTH * (2 ** ($clog2(NUM)-4))-1:0] T; + for (i = 0; i < 2 ** ($clog2(NUM)-4); i++) if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH($clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[$clog2(a_width0)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_width0)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); end else - assign T[i] = 1'bx; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(Y_WIDTH * (2 ** ($clog2(NUM)-4))), .B_WIDTH(B_WIDTH-$clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:$clog2(a_width0)]), .Y(Y)); end endgenerate endmodule From 2217d59e299ce0cc15887d53308d7b7cb6400c52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 18:06:33 -0700 Subject: [PATCH 120/514] Add non-input bits driven by unrecognised cells as ci_bits --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a4ef89931..bad9322bb 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -229,7 +229,7 @@ struct XAigerWriter } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O) && !output_bits.count(O)) + if (!input_bits.count(O)) ci_bits.insert(O); } } From 87b8d29a900eef6ec84c87ea7cd87f9a0b744fac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 09:13:39 -0700 Subject: [PATCH 121/514] Juggle opt calls in synth_xilinx --- techlibs/xilinx/cells_map.v | 77 ++++++++++++++++++--------------- techlibs/xilinx/synth_xilinx.cc | 6 +-- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 93d60f60b..253678028 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -31,7 +31,6 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; - localparam NUM = A_WIDTH/Y_WIDTH; generate genvar i, j; if (B_SIGNED) begin @@ -41,51 +40,57 @@ module \$shiftx (A, B, Y); else wire _TECHMAP_FAIL_ = 1; end - else if (NUM <= 4) begin - wire _TECHMAP_FAIL_ = 1; - end - else if (NUM <= 8) begin - localparam a_width0 = Y_WIDTH * 4; - localparam a_widthN = A_WIDTH - a_width0; - wire [Y_WIDTH-1:0] T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - for (i = 0; i < Y_WIDTH; i++) - MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); - end - else if (NUM <= 16) begin - localparam a_width0 = Y_WIDTH * 4; - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [Y_WIDTH*4-1:0] T; - wire [Y_WIDTH-1:0] T0, T1; - for (i = 0; i < 4; i++) - if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); - else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); - else - assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; + else if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) begin - MUXF7 fpga_mux_0 (.I0(T[0*Y_WIDTH+i]), .I1(T[1*Y_WIDTH+i]), .S(B[B_WIDTH-2]), .O(T0[i])); - MUXF7 fpga_mux_1 (.I0(T[2*Y_WIDTH+i]), .I1(T[3*Y_WIDTH+i]), .S(B[B_WIDTH-2]), .O(T1[i])); - MUXF8 fpga_mux_2 (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + wire [A_WIDTH/Y_WIDTH-1:0] A_i; + for (j = 0; j < A_WIDTH/Y_WIDTH; j++) + assign A_i[j] = A[i*Y_WIDTH+j]; + wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_i = B/Y_WIDTH; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_i), .Y(Y[i])); end end + else if (B_WIDTH < 3) begin + wire _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH == 3) begin + localparam a_width0 = 2 ** 2; + localparam a_widthN = A_WIDTH - a_width0; + wire T0, T1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + end + else if (B_WIDTH == 4) begin + localparam a_width0 = 2 ** 3; + localparam num_mux8 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; + wire [B_WIDTH-1:0] T; + wire T0, T1; + for (i = 0; i < B_WIDTH; i++) + if (i < num_mux8) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); + else if (i == num_mux8 && a_widthN > 0) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = 1'bx; + MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[B_WIDTH-2]), .O(T0)); + MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[B_WIDTH-2]), .O(T1)); + MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + end else begin - localparam a_width0 = Y_WIDTH * 16; + localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [Y_WIDTH * (2 ** ($clog2(NUM)-4))-1:0] T; - for (i = 0; i < 2 ** ($clog2(NUM)-4); i++) + wire [(2**(B_WIDTH-4))-1:0] T; + for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH($clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[$clog2(a_width0)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_width0)-1:0]), .Y(T[(i+1)*Y_WIDTH-1:i*Y_WIDTH])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); end else - assign T[(i+1)*Y_WIDTH-1:i*Y_WIDTH] = {Y_WIDTH{1'bx}}; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(Y_WIDTH * (2 ** ($clog2(NUM)-4))), .B_WIDTH(B_WIDTH-$clog2(a_width0)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:$clog2(a_width0)]), .Y(Y)); + assign T[i] = 1'bx; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 10902a560..0058f626f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -118,7 +118,7 @@ struct SynthXilinxPass : public Pass log("\n"); log(" map_cells:\n"); log(" techmap -map +/xilinx/cells_map.v\n"); - log(" clean\n"); + log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); log(" techmap -map +/techmap.v\n"); @@ -258,11 +258,10 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "opt -fast -full"); + Pass::call(design, "opt -fast"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "opt -full"); if (vpr) { Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); @@ -282,6 +281,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { + Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v"); if (abc == "abc9") Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); From bca37796578ee3a259a8327d881d5ac1264c3ac9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 09:25:19 -0700 Subject: [PATCH 122/514] Fix typo --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 253678028..8bf0a28b5 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -58,7 +58,7 @@ module \$shiftx (A, B, Y); wire T0, T1; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - MUXF7 fpga_mux (.I0(T0[i]), .I1(T1[i]), .S(B[B_WIDTH-1]), .O(Y[i])); + MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); end else if (B_WIDTH == 4) begin localparam a_width0 = 2 ** 3; From 0ec85640993e0eeb089334efbcd486a254d32786 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 10:04:58 -0700 Subject: [PATCH 123/514] Fix cells_map.v --- techlibs/xilinx/cells_map.v | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 8bf0a28b5..f1ea8f6df 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -41,12 +41,12 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else if (Y_WIDTH > 1) begin + wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_bitty = B/Y_WIDTH; for (i = 0; i < Y_WIDTH; i++) begin wire [A_WIDTH/Y_WIDTH-1:0] A_i; for (j = 0; j < A_WIDTH/Y_WIDTH; j++) - assign A_i[j] = A[i*Y_WIDTH+j]; - wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_i = B/Y_WIDTH; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_i), .Y(Y[i])); + assign A_i[j] = A[j*Y_WIDTH+i]; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_bitty), .Y(Y[i])); end end else if (B_WIDTH < 3) begin @@ -68,9 +68,9 @@ module \$shiftx (A, B, Y); wire T0, T1; for (i = 0; i < B_WIDTH; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = 1'bx; MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[B_WIDTH-2]), .O(T0)); @@ -84,9 +84,9 @@ module \$shiftx (A, B, Y); wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[(i+1)*a_width0-1:i*a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); end else assign T[i] = 1'bx; From 8658b56a08737cef6040015b192c11da3e6b4eb4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 10:08:05 -0700 Subject: [PATCH 124/514] More fine tuning --- techlibs/xilinx/cells_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f1ea8f6df..071014d47 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -56,7 +56,7 @@ module \$shiftx (A, B, Y); localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[B_WIDTH-2:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); end @@ -68,7 +68,7 @@ module \$shiftx (A, B, Y); wire T0, T1; for (i = 0; i < B_WIDTH; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(B_WIDTH-2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[B_WIDTH-3:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(3), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[3-1:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else From 233edf00fec32c8acd7ed442323e0cd515f0e681 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 10:48:14 -0700 Subject: [PATCH 125/514] Fix cells_map.v some more --- techlibs/xilinx/cells_map.v | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 071014d47..2981f89f6 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -61,21 +61,21 @@ module \$shiftx (A, B, Y); MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); end else if (B_WIDTH == 4) begin - localparam a_width0 = 2 ** 3; + localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [B_WIDTH-1:0] T; + wire [4-1:0] T; wire T0, T1; - for (i = 0; i < B_WIDTH; i++) + for (i = 0; i < 4; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(3), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[3-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = 1'bx; - MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[B_WIDTH-2]), .O(T0)); - MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[B_WIDTH-2]), .O(T1)); - MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); + MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); + MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; From ca8ef92a82897b71c3dbc13ab5ff0cbd28339689 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 10:36:05 -0700 Subject: [PATCH 126/514] PI before CI --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bad9322bb..b0770ec96 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -295,12 +295,12 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : ci_bits) { + for (auto bit : input_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; } - for (auto bit : input_bits) { + for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; } From 1c6f0cffd95876eac620bdfe9be50b366dabd8c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 12:27:07 -0700 Subject: [PATCH 127/514] Cope with an output having same name as an input (i.e. CO) --- frontends/aiger/aigerparse.cc | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b752d3127..0b0f6dd2e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -460,12 +460,30 @@ next_line: log_assert(wire); log_assert(wire->port_output); - if (index == 0) - module->rename(wire, escaped_symbol); + if (index == 0) { + // Cope with the fact that a CO might be identical + // to a PO (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_symbol); + if (!existing) + module->rename(wire, escaped_symbol); + else { + wire->port_output = false; + module->connect(wire, existing); + } + } else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + std::string indexed_name = stringf("%s[%d]", escaped_symbol.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + else { + module->connect(wire, existing); + wire->port_output = false; + } } } else From 04e466d5e4ca4654495cb1044f6f200d817f63a2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:06:44 -0700 Subject: [PATCH 128/514] Add support for synth_xilinx -abc9 and ignore abc9 -dress opt --- passes/techmap/abc9.cc | 5 +++++ techlibs/xilinx/synth_xilinx.cc | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index da3d36354..6e2e349ee 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1237,6 +1237,11 @@ struct Abc9Pass : public Pass { map_mux16 = true; continue; } + if (arg == "-dress") { + // TODO + abc_dress = true; + continue; + } if (arg == "-g" && argidx+1 < args.size()) { for (auto g : split_tokens(args[++argidx], ",")) { vector gate_list; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 805ae8e6e..090bcce85 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -80,6 +80,9 @@ struct SynthXilinxPass : public Pass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); + log(" -abc9\n"); + log(" use abc9 instead of abc\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); log("\n"); @@ -142,6 +145,7 @@ struct SynthXilinxPass : public Pass std::string edif_file; std::string blif_file; std::string run_from, run_to; + std::string abc = "abc"; bool flatten = false; bool retime = false; bool vpr = false; @@ -191,6 +195,10 @@ struct SynthXilinxPass : public Pass nodram = true; continue; } + if (args[argidx] == "-abc9") { + abc = "abc9"; + continue; + } break; } extra_args(args, argidx, design); @@ -267,7 +275,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } From 941365b4bb9db6fac6b57230482c6be61aafc53a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Apr 2019 10:09:43 -0700 Subject: [PATCH 129/514] Comment out --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6e2e349ee..ec4a28d08 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1239,7 +1239,7 @@ struct Abc9Pass : public Pass { } if (arg == "-dress") { // TODO - abc_dress = true; + //abc_dress = true; continue; } if (arg == "-g" && argidx+1 < args.size()) { From c7483917307bd1c281b159fe15f0f79af4e305b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 14:13:11 -0700 Subject: [PATCH 130/514] WIP --- backends/aiger/xaiger.cc | 82 +++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bad9322bb..ce10028f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -61,6 +61,8 @@ struct XAigerWriter dict init_inputs; int initstate_ff = 0; + vector box_list; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -211,7 +213,7 @@ struct XAigerWriter } for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; + /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -219,30 +221,32 @@ struct XAigerWriter auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - if (!w->port_input) { + /*if (!w->port_input)*/ { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (!output_bits.count(b)) + /*if (!output_bits.count(b))*/ co_bits.insert(b); } } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O)) + /*if (!input_bits.count(O))*/ ci_bits.insert(O); } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + + box_list.emplace_back(cell); + log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing + // suffix, make it a PO driven by the existing inout, and inherit existing // inout's drivers if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); @@ -256,19 +260,19 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); + output_bits.insert(new_bit); } } // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { - co_bits.erase(bit); + //co_bits.erase(bit); output_bits.erase(bit); } // Erase all CIs that are also COs - for (auto bit : co_bits) - ci_bits.erase(bit); + //for (auto bit : co_bits) + // ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); @@ -491,7 +495,8 @@ struct XAigerWriter if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); - output_seen = !miter_mode; + if (output_seen && output_bits.count(b)) + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -532,7 +537,52 @@ struct XAigerWriter } } - f << stringf("c\nGenerated by %s\n", yosys_version_str); + f << "c"; + + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + int box_id = 0; + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + for (const auto &c : cell->connections()) + if (cell->input(c.first)) + box_inputs += c.second.size(); + else + box_outputs += c.second.size(); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id++); + write_h_buffer(0 /* OldBoxNum */); + } + std::string h_buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); +#else + int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); +#endif + f << "h"; + f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); + f.write(h_buffer_str.data(), h_buffer_str.size()); + + f << stringf("Generated by %s\n", yosys_version_str); } void write_map(std::ostream &f, bool verbose_map, bool omode) @@ -557,7 +607,11 @@ struct XAigerWriter int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; + + // Only continue if this input is not a CO, + // otherwise write as CO below + if (!co_bits.count(b)) + continue; } if (output_bits.count(b) || co_bits.count(b)) { @@ -606,7 +660,7 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) - f << "output 0 0 __dummy_o__\n"; + f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) From ada130b4599db74744df34d8608611fd746bf08a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 16:17:12 -0700 Subject: [PATCH 131/514] Also cope with duplicated CIs --- frontends/aiger/aigerparse.cc | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0b0f6dd2e..0d81cc2fd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -446,12 +446,30 @@ next_line: log_assert(wire); log_assert(wire->port_input); - if (index == 0) - module->rename(wire, escaped_symbol); + if (index == 0) { + // Cope with the fact that a CI might be identical + // to a PI (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_symbol); + if (!existing) + module->rename(wire, escaped_symbol); + else { + wire->port_input = false; + module->connect(wire, existing); + } + } else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + std::string indexed_name = stringf("%s[%d]", escaped_symbol.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + } + else { + module->connect(wire, existing); + wire->port_input = false; + } } } else if (type == "output") { From 686e772f0bb3129e7d6469dc25548497f107ebc5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 16:17:48 -0700 Subject: [PATCH 132/514] ci_bits and co_bits now a list, order is important for ABC --- backends/aiger/xaiger.cc | 58 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce10028f7..f67f7620b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -47,7 +47,7 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; - pool ci_bits, co_bits; + vector> ci_bits, co_bits; dict type_map; vector> aig_gates; @@ -226,13 +226,13 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ - co_bits.insert(b); + co_bits.emplace_back(b, 0); } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ - ci_bits.insert(O); + ci_bits.emplace_back(O, 0); } } if (!type_map.count(cell->type)) @@ -240,7 +240,7 @@ struct XAigerWriter } box_list.emplace_back(cell); - log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { @@ -274,8 +274,8 @@ struct XAigerWriter //for (auto bit : co_bits) // ci_bits.erase(bit); // CIs cannot be undriven - for (auto bit : ci_bits) - undriven_bits.erase(bit); + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -299,9 +299,10 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : ci_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } for (auto bit : input_bits) { @@ -369,15 +370,15 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); - for (auto bit : co_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + for (auto &c : co_bits) { + RTLIL::SigBit bit = c.first; + c.second = aig_o++; + ordered_outputs[bit] = c.second; aig_outputs.push_back(bit2aig(bit)); } for (auto bit : output_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -484,7 +485,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -493,10 +494,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); - if (output_seen && output_bits.count(b)) - output_seen = !miter_mode; + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -603,18 +603,13 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - - // Only continue if this input is not a CO, - // otherwise write as CO below - if (!co_bits.count(b)) - continue; } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); continue; @@ -646,6 +641,21 @@ struct XAigerWriter } } + for (const auto &c : ci_bits) { + RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; + int i = b.offset; + int a = c.second; + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + for (const auto &c : co_bits) { + RTLIL::SigBit b = c.first; + int o = c.second; + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + } + input_lines.sort(); for (auto &it : input_lines) f << it.second; From 88d43a519bd0ea9657baba8bf9bc6a845b6cf14d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 16:29:14 -0700 Subject: [PATCH 133/514] Use -map instead of -symbols for aiger --- passes/techmap/abc9.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ec4a28d08..17d082833 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -symbols %s/input.aig; ", tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.aig; ", tempdir_name.c_str(), tempdir_name.c_str())); design->selection_stack.pop_back(); @@ -523,7 +523,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool builtin_lib = liberty_file.empty(); RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); - AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, "" /* map_filename */, true /* wideports */); + buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); + AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); reader.parse_xaiger(); ifs.close(); From acf3f5694bb0cd9911566855df27c17e7e82b8cc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 17:02:24 -0700 Subject: [PATCH 134/514] Fix inout handling for -map option --- frontends/aiger/aigerparse.cc | 40 ++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b752d3127..009b28455 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -439,7 +439,7 @@ next_line: std::string type, symbol; int variable, index; while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_symbol = RTLIL::escape_id(symbol); + RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); if (type == "input") { log_assert(static_cast(variable) < inputs.size()); RTLIL::Wire* wire = inputs[variable]; @@ -447,11 +447,11 @@ next_line: log_assert(wire->port_input); if (index == 0) - module->rename(wire, escaped_symbol); + module->rename(wire, escaped_s); else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); + module->rename(wire, stringf("%s[%d]", escaped_s.c_str(), index)); if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); } } else if (type == "output") { @@ -460,12 +460,32 @@ next_line: log_assert(wire); log_assert(wire->port_output); - if (index == 0) - module->rename(wire, escaped_symbol); - else if (index > 0) { - module->rename(wire, stringf("%s[%d]", escaped_symbol.c_str(), index)); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); + if (index == 0) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else + module->rename(wire, escaped_s); + } + else if (index > 0) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else { + module->rename(wire, stringf("%s[%d]", escaped_s.c_str(), index)); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } } } else From fe0b421212a17dae32cd30a09dc43c688a285f8c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:16:25 -0700 Subject: [PATCH 135/514] Output __const0__ and __const1__ CIs --- backends/aiger/xaiger.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f67f7620b..d3384e136 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,8 +215,6 @@ struct XAigerWriter for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); @@ -382,7 +380,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -561,11 +559,12 @@ struct XAigerWriter int box_id = 0; for (auto cell : box_list) { int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) + for (const auto &c : cell->connections()) { if (cell->input(c.first)) box_inputs += c.second.size(); - else + if (cell->output(c.first)) box_outputs += c.second.size(); + } write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id++); @@ -652,8 +651,12 @@ struct XAigerWriter for (const auto &c : co_bits) { RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; int o = c.second; - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + if (wire) + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); + else + output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); } input_lines.sort(); @@ -669,7 +672,7 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); - if (omode && output_lines.empty()) + if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); From 482a60825b607880c5984b1b39e06e58c5f75ada Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:16:50 -0700 Subject: [PATCH 136/514] abc to ignore __dummy_o__ and __const[01]__ when re-integrating --- passes/techmap/abc9.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 17d082833..52b1b6d35 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -319,10 +319,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); - log_header(design, "Extracting gate netlist of module `%s' to `%s/input.aig'..\n", + log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("read %s/input.aig; &get -n; ", tempdir_name.c_str()); + std::string abc_script = stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); @@ -407,7 +407,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.aig; ", tempdir_name.c_str(), tempdir_name.c_str())); + Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); design->selection_stack.pop_back(); @@ -546,9 +546,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri output_bits.insert({wire, i}); } else { - if (w->name.str() == "\\__dummy_o__") { - log("Don't call ABC as there is nothing to map.\n"); - goto cleanup; + if (w->name.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { + //log("Don't call ABC as there is nothing to map.\n"); + //goto cleanup; + continue; } // Attempt another wideports_split here because there @@ -874,6 +875,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Wire *w = it.second; if (!w->port_input && !w->port_output) continue; + if (w->name == "\\__const0__") { + log_assert(w->port_output); + module->connect(w, RTLIL::S0); + continue; + } + if (w->name == "\\__const1__") { + log_assert(w->port_output); + module->connect(w, RTLIL::S1); + continue; + } + if (w->name == "\\__dummy_o__") + continue; + RTLIL::Wire *wire = module->wire(w->name); RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); RTLIL::SigSpec signal; From 9bfcd8006378dc0d81a1c902501a6efeb8406cba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:21:16 -0700 Subject: [PATCH 137/514] Handle __dummy_o__ and __const[01]__ in read_aiger not abc --- frontends/aiger/aigerparse.cc | 4 ++++ passes/techmap/abc9.cc | 22 ++++------------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7e91c8cac..e35a8ad62 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -477,6 +477,10 @@ next_line: RTLIL::Wire* wire = outputs[variable]; log_assert(wire); log_assert(wire->port_output); + if (escaped_s.in("__dummy_o__", "__const0__", "__const1__")) { + wire->port_output = false; + continue; + } if (index == 0) { // Cope with the fact that a CO might be identical diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 52b1b6d35..edc07092b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -546,11 +546,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri output_bits.insert({wire, i}); } else { - if (w->name.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { - //log("Don't call ABC as there is nothing to map.\n"); - //goto cleanup; - continue; - } + //if (w->name == "\\__dummy_o__") { + // log("Don't call ABC as there is nothing to map.\n"); + // goto cleanup; + //} // Attempt another wideports_split here because there // exists the possibility that different bits of a port @@ -875,19 +874,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Wire *w = it.second; if (!w->port_input && !w->port_output) continue; - if (w->name == "\\__const0__") { - log_assert(w->port_output); - module->connect(w, RTLIL::S0); - continue; - } - if (w->name == "\\__const1__") { - log_assert(w->port_output); - module->connect(w, RTLIL::S1); - continue; - } - if (w->name == "\\__dummy_o__") - continue; - RTLIL::Wire *wire = module->wire(w->name); RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); RTLIL::SigSpec signal; From fecafb2207efc772fec49b357bc6e20ca6a25aca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:22:44 -0700 Subject: [PATCH 138/514] Forgot backslashes --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e35a8ad62..f2d21f1db 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -477,7 +477,7 @@ next_line: RTLIL::Wire* wire = outputs[variable]; log_assert(wire); log_assert(wire->port_output); - if (escaped_s.in("__dummy_o__", "__const0__", "__const1__")) { + if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { wire->port_output = false; continue; } From 8fbbd9b129697152c93c35831c1d50982702a3ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Apr 2019 22:25:09 -0700 Subject: [PATCH 139/514] Add abc_box_id attribute to MUXF7/F8 cells --- techlibs/xilinx/cells_sim.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 0c8f282a4..05dd9229f 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -159,10 +159,12 @@ module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule +(* abc_box_id = 1 *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +(* abc_box_id = 2 *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule From e084240a813b618cea6b5a80d41e2d4516388e44 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Apr 2019 22:25:37 -0700 Subject: [PATCH 140/514] Check abc_box_id attr --- backends/aiger/xaiger.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d3384e136..eb31bfcef 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -212,6 +212,8 @@ struct XAigerWriter continue; } + bool abc_box = module->design->module(cell->type)->attributes.count("\\abc_box_id"); + for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -224,20 +226,33 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ + if (abc_box) co_bits.emplace_back(b, 0); + else { + output_bits.insert(b); + if (!b.wire->port_input) + unused_bits.erase(b); + } } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ + if (abc_box) ci_bits.emplace_back(O, 0); + else { + input_bits.insert(O); + if (!O.wire->port_output) + undriven_bits.erase(O); + } } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - box_list.emplace_back(cell); + if (abc_box) + box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } From 18108e024ae7d3b246aa83e8a9e7ac5327837d0a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Apr 2019 22:27:36 -0700 Subject: [PATCH 141/514] Use abc_box_id --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index eb31bfcef..841adf8f6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -571,7 +571,6 @@ struct XAigerWriter write_h_buffer(input_bits.size()); write_h_buffer(num_outputs); write_h_buffer(box_list.size()); - int box_id = 0; for (auto cell : box_list) { int box_inputs = 0, box_outputs = 0; for (const auto &c : cell->connections()) { @@ -582,7 +581,7 @@ struct XAigerWriter } write_h_buffer(box_inputs); write_h_buffer(box_outputs); - write_h_buffer(box_id++); + write_h_buffer(module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int()); write_h_buffer(0 /* OldBoxNum */); } std::string h_buffer_str = h_buffer.str(); From 8c6cf07acff290ab2132c1a7d262bf195fa85b8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 11:14:59 -0700 Subject: [PATCH 142/514] Revert "Add abc_box_id attribute to MUXF7/F8 cells" This reverts commit 8fbbd9b129697152c93c35831c1d50982702a3ec. --- techlibs/xilinx/cells_sim.v | 2 -- 1 file changed, 2 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 05dd9229f..0c8f282a4 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -159,12 +159,10 @@ module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule -(* abc_box_id = 1 *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule -(* abc_box_id = 2 *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule From a2b106135b29d1d44255f1b3b6c4173c6e1f3624 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 11:19:42 -0700 Subject: [PATCH 143/514] Do not call abc on modules with abc_box_id attr --- passes/techmap/abc9.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index caaff9256..fbf3a47ee 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1405,6 +1405,9 @@ struct Abc9Pass : public Pass { continue; } + if (mod->attributes.count("\\abc_box_id")) + continue; + assign_map.set(mod); signal_init.clear(); From b89bb744529fc8a5e4cd38522f86a797117f2abc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 11:19:54 -0700 Subject: [PATCH 144/514] For 'stat' do not count modules with abc_box_id --- passes/cmds/stat.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 54f4ea817..3909c4c8c 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -269,6 +269,9 @@ struct StatPass : public Pass { if (mod->get_bool_attribute("\\top")) top_mod = mod; + if (mod->attributes.count("\\abc_box_id")) + continue; + statdata_t data(design, mod, width_mode, cell_area); mod_stat[mod->name] = data; From 3ac4977b70a373cdabaa72e5f08050f49a3d4046 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 11:21:03 -0700 Subject: [PATCH 145/514] Add +/xilinx/cells_box.v containing models for ABC boxes --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/cells_box.v | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 techlibs/xilinx/cells_box.v diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 432bb0770..43be55d51 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -31,6 +31,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.box)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_box.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.lut)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) diff --git a/techlibs/xilinx/cells_box.v b/techlibs/xilinx/cells_box.v new file mode 100644 index 000000000..7805e6306 --- /dev/null +++ b/techlibs/xilinx/cells_box.v @@ -0,0 +1,10 @@ +(* abc_box_id = 1 *) +module MUXF7(output O, input I0, I1, S); + assign O = S ? I1 : I0; +endmodule + +(* abc_box_id = 2 *) +module MUXF8(output O, input I0, I1, S); + assign O = S ? I1 : I0; +endmodule + From d259e6dc14dadf9101116c622569f5b961adde69 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 11:21:46 -0700 Subject: [PATCH 146/514] synth_xilinx: before abc read +/xilinx/cells_box.v --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0058f626f..c10e42532 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -283,6 +283,7 @@ struct SynthXilinxPass : public Pass { Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v"); + Pass::call(design, "read_verilog +/xilinx/cells_box.v"); if (abc == "abc9") Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); else From 51896953626ddf7cffdbddfe64e8d85264d968a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 12:41:56 -0700 Subject: [PATCH 147/514] read_verilog cells_box.v before techmap --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c10e42532..d5e9b80c8 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,8 +282,8 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { Pass::call(design, "opt -full"); - Pass::call(design, "techmap -map +/techmap.v"); Pass::call(design, "read_verilog +/xilinx/cells_box.v"); + Pass::call(design, "techmap -map +/techmap.v"); if (abc == "abc9") Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); else From 53b19ab1f5631bcfc6c3def14f5d44ecc05c1cbc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 12:43:14 -0700 Subject: [PATCH 148/514] Make cells.box whiteboxes not blackboxes --- techlibs/xilinx/cells.box | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells.box b/techlibs/xilinx/cells.box index c8092db6e..c236d3c90 100644 --- a/techlibs/xilinx/cells.box +++ b/techlibs/xilinx/cells.box @@ -4,10 +4,10 @@ # F7BMUX slower than F7AMUX # Inputs: 0 1 S0 # Outputs: OUT -F7BMUX 1 0 3 1 +F7BMUX 1 1 3 1 217 223 296 # Inputs: 0 1 S0 # Outputs: OUT -MUXF8 2 0 3 1 +MUXF8 2 1 3 1 104 94 273 From 98c297fabfb960beadedaccf7cc9f765f20e044b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 12:44:10 -0700 Subject: [PATCH 149/514] ABC to read_box before reading netlist --- passes/techmap/abc9.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fbf3a47ee..f5f7add9a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -322,7 +322,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); + std::string abc_script; if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); @@ -343,6 +343,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri else abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); + abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); + if (!script_file.empty()) { if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) From f22aa4422dfa6165386b9d2e1e55dafe9b9e5cea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 12:57:27 -0700 Subject: [PATCH 150/514] WIP for box support --- backends/aiger/xaiger.cc | 129 ++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 36 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 841adf8f6..f7c757754 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -212,7 +212,8 @@ struct XAigerWriter continue; } - bool abc_box = module->design->module(cell->type)->attributes.count("\\abc_box_id"); + RTLIL::Module* box_module = module->design->module(cell->type); + bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ @@ -552,48 +553,104 @@ struct XAigerWriter f << "c"; - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { + if (!box_list.empty()) { + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + + RTLIL::Module *holes_module = nullptr; + holes_module = module->design->addModule("\\__holes__"); + + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + Cell *holes_cell = nullptr; + if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); + RTLIL::Wire *holes_wire; + int num_inputs = 0; + for (const auto &c : cell->connections()) { + if (cell->input(c.first)) { + box_inputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->wire(stringf("\\i%d", num_inputs++)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire->port_input = true; + } + holes_cell->setPort(c.first, holes_wire); + } + } + if (cell->output(c.first)) { + box_outputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); + holes_wire->port_output = true; + holes_cell->setPort(c.first, holes_wire); + } + } + } + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id); + write_h_buffer(0 /* OldBoxNum */); + } + + f << "h"; + std::string buffer_str = h_buffer.str(); // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int i32_be = __builtin_bswap32(i32); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; - write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); - write_h_buffer(box_list.size()); - for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) { - if (cell->input(c.first)) - box_inputs += c.second.size(); - if (cell->output(c.first)) - box_outputs += c.second.size(); - } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(0 /* OldBoxNum */); - } - std::string h_buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + if (holes_module) { + holes_module->fixup_ports(); + + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); + + Pass::call(holes_module->design, "flatten; aigmap; write_verilog -noexpr -norename holes.v"); + + holes_module->design->selection_stack.pop_back(); + + std::stringstream a_buffer; + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + + f << "a"; + std::string buffer_str = a_buffer.str(); + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - f << "h"; - f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); - f.write(h_buffer_str.data(), h_buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + holes_module->design->remove(holes_module); + } + } f << stringf("Generated by %s\n", yosys_version_str); } From fed1f0ba637941cc0c2c4cc75c08ba7e3994c1a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 12:59:48 -0700 Subject: [PATCH 151/514] NULL check before use --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f7c757754..875a2ec03 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -231,7 +231,7 @@ struct XAigerWriter co_bits.emplace_back(b, 0); else { output_bits.insert(b); - if (!b.wire->port_input) + if (b.wire && !b.wire->port_input) unused_bits.erase(b); } } From afcb86c3d143c95643855da1159b0f245f75262c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 13:10:13 -0700 Subject: [PATCH 152/514] abc9 to call "setundef -zero" behaving as for abc --- passes/techmap/abc9.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index edc07092b..3c4919b1f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -403,6 +403,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); + // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero + Pass::call(design, "setundef -zero"); + Pass::call(design, "aigmap"); handle_loops(design); From 0c8a839f13bf7bc8368625ab55960dd3f219b0d8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 13:10:35 -0700 Subject: [PATCH 153/514] Re-enable partsel.v test --- tests/simple_abc9/run-test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index bf48d007d..af003d52e 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -18,6 +18,5 @@ if ! which iverilog > /dev/null ; then fi cp ../simple/*.v . -rm partsel.v # FIXME: Contains 1'hx, thus write_xaiger fails DOLLAR='?' exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_'" From aece97024de574fd765e18e31f685e9ffb0a13c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 13:16:20 -0700 Subject: [PATCH 154/514] Fix spacing --- backends/aiger/xaiger.cc | 2 +- techlibs/xilinx/cells.lut | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 875a2ec03..bd7347a19 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -576,7 +576,7 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); - + for (auto cell : box_list) { int box_inputs = 0, box_outputs = 0; int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); diff --git a/techlibs/xilinx/cells.lut b/techlibs/xilinx/cells.lut index a1d9b9c42..c6bc7b1f7 100644 --- a/techlibs/xilinx/cells.lut +++ b/techlibs/xilinx/cells.lut @@ -1,4 +1,4 @@ -# Max delays from https://pastebin.com/v2hrcksd +# Max delays from https://pastebin.com/v2hrcksd # from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 # K area delay From 61ca83e099ce9b08b0dcbfaac65a2e2870d58413 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 13:24:54 -0700 Subject: [PATCH 155/514] Remove write_verilog call --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bd7347a19..99ca4f8d5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -630,7 +630,7 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten; aigmap; write_verilog -noexpr -norename holes.v"); + Pass::call(holes_module->design, "flatten; aigmap"); holes_module->design->selection_stack.pop_back(); From 43cd047fb9d73c43f8fe2c35c457cfa8fc3523ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 13:44:15 -0700 Subject: [PATCH 156/514] Do not put constants into output_bits --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 99ca4f8d5..7c7697874 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -229,9 +229,9 @@ struct XAigerWriter /*if (!output_bits.count(b))*/ if (abc_box) co_bits.emplace_back(b, 0); - else { + else if (b.wire) { output_bits.insert(b); - if (b.wire && !b.wire->port_input) + if (!b.wire->port_input) unused_bits.erase(b); } } From ece5c3ab38023abc251828b9379ea4eca9573abc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 14:53:01 -0700 Subject: [PATCH 157/514] Fix wire numbering --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7c7697874..66ab3878e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -589,11 +589,12 @@ struct XAigerWriter if (cell->input(c.first)) { box_inputs += c.second.size(); if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", num_inputs++)); + holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); if (!holes_wire) { holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); holes_wire->port_input = true; } + ++num_inputs; holes_cell->setPort(c.first, holes_wire); } } From cbb85e40e87fbfb1602bb934ed76a97efb9e55c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 14:53:28 -0700 Subject: [PATCH 158/514] Add MUXCY and XORCY to cells_box.v --- techlibs/xilinx/cells.box | 6 ++++++ techlibs/xilinx/cells_box.v | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/techlibs/xilinx/cells.box b/techlibs/xilinx/cells.box index c236d3c90..5ad284f47 100644 --- a/techlibs/xilinx/cells.box +++ b/techlibs/xilinx/cells.box @@ -11,3 +11,9 @@ F7BMUX 1 1 3 1 # Outputs: OUT MUXF8 2 1 3 1 104 94 273 + +MUXCY 3 1 3 1 +1 1 1 + +XORCY 4 1 2 1 +1 1 diff --git a/techlibs/xilinx/cells_box.v b/techlibs/xilinx/cells_box.v index 7805e6306..ef6f81d27 100644 --- a/techlibs/xilinx/cells_box.v +++ b/techlibs/xilinx/cells_box.v @@ -8,3 +8,12 @@ module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +(* abc_box_id = 3 *) +module MUXCY(output O, input CI, DI, S); + assign O = S ? CI : DI; +endmodule + +(* abc_box_id = 4 *) +module XORCY(output O, input CI, LI); + assign O = CI ^ LI; +endmodule From 55a3638c71229e2730e1d0f7340f6c9d4087522d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 15:01:45 -0700 Subject: [PATCH 159/514] Port from xc7mux branch --- backends/aiger/xaiger.cc | 146 +++++++++++++++++++++++++++++---------- passes/cmds/stat.cc | 3 + passes/techmap/abc9.cc | 72 ++++++++++++++----- 3 files changed, 167 insertions(+), 54 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d3384e136..66ab3878e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -212,6 +212,9 @@ struct XAigerWriter continue; } + RTLIL::Module* box_module = module->design->module(cell->type); + bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -224,20 +227,33 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ + if (abc_box) co_bits.emplace_back(b, 0); + else if (b.wire) { + output_bits.insert(b); + if (!b.wire->port_input) + unused_bits.erase(b); + } } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ + if (abc_box) ci_bits.emplace_back(O, 0); + else { + input_bits.insert(O); + if (!O.wire->port_output) + undriven_bits.erase(O); + } } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - box_list.emplace_back(cell); + if (abc_box) + box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -537,49 +553,105 @@ struct XAigerWriter f << "c"; - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { + if (!box_list.empty()) { + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + + RTLIL::Module *holes_module = nullptr; + holes_module = module->design->addModule("\\__holes__"); + + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + Cell *holes_cell = nullptr; + if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); + RTLIL::Wire *holes_wire; + int num_inputs = 0; + for (const auto &c : cell->connections()) { + if (cell->input(c.first)) { + box_inputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire->port_input = true; + } + ++num_inputs; + holes_cell->setPort(c.first, holes_wire); + } + } + if (cell->output(c.first)) { + box_outputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); + holes_wire->port_output = true; + holes_cell->setPort(c.first, holes_wire); + } + } + } + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id); + write_h_buffer(0 /* OldBoxNum */); + } + + f << "h"; + std::string buffer_str = h_buffer.str(); // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int i32_be = __builtin_bswap32(i32); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; - write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); - write_h_buffer(box_list.size()); - int box_id = 0; - for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) { - if (cell->input(c.first)) - box_inputs += c.second.size(); - if (cell->output(c.first)) - box_outputs += c.second.size(); - } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_id++); - write_h_buffer(0 /* OldBoxNum */); - } - std::string h_buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + if (holes_module) { + holes_module->fixup_ports(); + + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); + + Pass::call(holes_module->design, "flatten; aigmap"); + + holes_module->design->selection_stack.pop_back(); + + std::stringstream a_buffer; + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + + f << "a"; + std::string buffer_str = a_buffer.str(); + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - f << "h"; - f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); - f.write(h_buffer_str.data(), h_buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + holes_module->design->remove(holes_module); + } + } f << stringf("Generated by %s\n", yosys_version_str); } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 54f4ea817..3909c4c8c 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -269,6 +269,9 @@ struct StatPass : public Pass { if (mod->get_bool_attribute("\\top")) top_mod = mod; + if (mod->attributes.count("\\abc_box_id")) + continue; + statdata_t data(design, mod, width_mode, cell_area); mod_stat[mod->name] = data; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3c4919b1f..b14eef485 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -272,7 +272,7 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode) + const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file) { module = current_module; map_autoidx = autoidx++; @@ -322,18 +322,29 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script = stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); + std::string abc_script; if (!liberty_file.empty()) { abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); if (!constr_file.empty()) abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); } else - if (!lut_costs.empty()) + if (!lut_costs.empty()) { abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + if (!box_file.empty()) + abc_script += stringf("read_box -v %s; ", box_file.c_str()); + } + else + if (!lut_file.empty()) { + abc_script += stringf("read_lut %s; ", lut_file.c_str()); + if (!box_file.empty()) + abc_script += stringf("read_box -v %s; ", box_file.c_str()); + } else abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); + abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); + if (!script_file.empty()) { if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) @@ -345,11 +356,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script += script_file[i]; } else abc_script += stringf("source %s", script_file.c_str()); - } else if (!lut_costs.empty()) { - bool all_luts_cost_same = true; - for (int this_cost : lut_costs) - if (this_cost != lut_costs.front()) - all_luts_cost_same = false; + } else if (!lut_costs.empty() || !lut_file.empty()) { + //bool all_luts_cost_same = true; + //for (int this_cost : lut_costs) + // if (this_cost != lut_costs.front()) + // all_luts_cost_same = false; abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; //if (all_luts_cost_same && !fast_mode) // abc_script += "; lutpack {S}"; @@ -576,7 +587,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Cell *cell; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); - if (!lut_costs.empty()) { + if (!lut_costs.empty() || !lut_file.empty()) { // ABC can return NOT gates that drive POs if (a_bit.wire->port_input) { // If it's a NOT gate that comes from a primary input directly @@ -1004,7 +1015,7 @@ struct Abc9Pass : public Pass { log(" file format).\n"); log("\n"); log(" -constr \n"); - log(" pass this file with timing constraints to ABC. use with -liberty.\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 \n"); @@ -1041,6 +1052,9 @@ struct Abc9Pass : public Pass { log(" the area cost doubles with each additional input bit. the delay cost\n"); log(" is still constant for all lut widths.\n"); log("\n"); + log(" -lut \n"); + log(" pass this file with lut library to ABC.\n"); + log("\n"); log(" -luts ,,,:,..\n"); log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); @@ -1094,6 +1108,9 @@ struct Abc9Pass : public Pass { 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 \n"); + log(" pass this file with box library to ABC. Use with -lut.\n"); + log("\n"); log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -1123,7 +1140,7 @@ struct Abc9Pass : public Pass { #else std::string exe_file = proc_self_dirname() + "yosys-abc"; #endif - std::string script_file, liberty_file, constr_file, clk_str; + 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"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; @@ -1169,8 +1186,8 @@ struct Abc9Pass : public Pass { continue; } if (arg == "-constr" && argidx+1 < args.size()) { - rewrite_filename(constr_file); constr_file = args[++argidx]; + rewrite_filename(constr_file); if (!constr_file.empty() && !is_absolute_path(constr_file)) constr_file = std::string(pwd) + "/" + constr_file; continue; @@ -1199,8 +1216,17 @@ struct Abc9Pass : public Pass { 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; + pos = arg.find_first_of('.'); + if (pos != string::npos) { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file)) + lut_file = std::string(pwd) + "/" + lut_file; + } + else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } } lut_costs.clear(); for (int i = 0; i < lut_mode; i++) @@ -1357,11 +1383,18 @@ struct Abc9Pass : public Pass { markgroups = true; continue; } + if (arg == "-box" && argidx+1 < args.size()) { + box_file = args[++argidx]; + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file)) + box_file = std::string(pwd) + "/" + box_file; + continue; + } break; } extra_args(args, argidx, design); - if (!lut_costs.empty() && !liberty_file.empty()) + if ((!lut_costs.empty() || !lut_file.empty()) && !liberty_file.empty()) log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); @@ -1373,6 +1406,9 @@ struct Abc9Pass : public Pass { continue; } + if (mod->attributes.count("\\abc_box_id")) + continue; + assign_map.set(mod); signal_init.clear(); @@ -1395,7 +1431,8 @@ struct Abc9Pass : public Pass { 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); + delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, + box_file, lut_file); continue; } @@ -1540,7 +1577,8 @@ struct Abc9Pass : public Pass { en_polarity = std::get<2>(it.first); 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); + keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, + box_file, lut_file); assign_map.set(mod); } } From e7a8955818b8b0fee02673607b429f1de0f7164e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 16:37:47 -0700 Subject: [PATCH 160/514] CIs before PIs; also sort each cell's connections before iterating --- backends/aiger/xaiger.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 66ab3878e..ce93ffb28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,6 +215,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -313,17 +314,17 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; + for (auto bit : input_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; aig_map[c.first] = c.second; } - for (auto bit : input_bits) { - aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; - } - if (imode && input_bits.empty()) { aig_m++, aig_i++; } @@ -585,6 +586,7 @@ struct XAigerWriter holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; int num_inputs = 0; + // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { if (cell->input(c.first)) { box_inputs += c.second.size(); From ae2653c50f196a0480e715c609852218f7c57090 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 16:39:16 -0700 Subject: [PATCH 161/514] abc9 to output some more info --- passes/techmap/abc9.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b14eef485..e28e3e59a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -343,7 +343,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri else abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); - abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str()); + abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); if (!script_file.empty()) { if (script_file[0] == '+') { @@ -388,6 +388,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3); abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc_script += "; &ps -l -s"; abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) From 7980118d74aae04479be3b9e9b59f95bf3bfbfe5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 16:39:30 -0700 Subject: [PATCH 162/514] Add ice40 box files --- techlibs/ice40/Makefile.inc | 3 +++ techlibs/ice40/cells.box | 6 ++++++ techlibs/ice40/cells_box.v | 5 +++++ techlibs/ice40/cells_sim.v | 1 + techlibs/ice40/lut.lut | 4 ++++ techlibs/ice40/synth_ice40.cc | 9 ++++++++- 6 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 techlibs/ice40/cells.box create mode 100644 techlibs/ice40/cells_box.v create mode 100644 techlibs/ice40/lut.lut diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 723b59d6f..cd992bb24 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -28,6 +28,9 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_box.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/lut.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/cells.box new file mode 100644 index 000000000..e4cfb71e6 --- /dev/null +++ b/techlibs/ice40/cells.box @@ -0,0 +1,6 @@ +# NB: Inputs/Outputs must be ordered alphabetically + +# Inputs: CI I0 I1 +# Outputs: CO +SB_CARRY 1 1 3 1 +126 259 231 diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/cells_box.v new file mode 100644 index 000000000..cca88f9aa --- /dev/null +++ b/techlibs/ice40/cells_box.v @@ -0,0 +1,5 @@ +(* abc_box_id = 1 *) +module SB_CARRY (output CO, input CI, I0, I1); + assign CO = (I0 && I1) || ((I0 || I1) && CI); +endmodule + diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 62a28364b..322c1e5c7 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -881,6 +881,7 @@ module SB_WARMBOOT ( ); endmodule +(* nomem2reg *) module SB_SPRAM256KA ( input [13:0] ADDRESS, input [15:0] DATAIN, diff --git a/techlibs/ice40/lut.lut b/techlibs/ice40/lut.lut new file mode 100644 index 000000000..48da89f46 --- /dev/null +++ b/techlibs/ice40/lut.lut @@ -0,0 +1,4 @@ +1 1 316 +2 1 316 379 +3 1 316 379 400 +4 1 316 379 400 449 diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 6c77e5482..3faa10b4f 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -316,7 +316,14 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); } if (!noabc) { - run(abc + " -dress -lut 4", "(skip if -noabc)"); + if (abc == "abc9") { + run("read_verilog +/ice40/cells_box.v"); + run("techmap -map +/techmap.v A:abc_box_id"); + run(abc + " -dress -lut +/ice40/lut.lut -box +/ice40/cells.box", "(skip if -noabc)"); + run("blackbox A:abc_box_id"); + } + else + run(abc + " -lut 4", "(skip if -noabc)"); } run("clean"); if (relut || help_mode) { From 743c164eee06abb44601e00304db18cdb36a180f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 17:34:11 -0700 Subject: [PATCH 163/514] Add SB_LUT4 to box library --- techlibs/ice40/cells.box | 7 +++++++ techlibs/ice40/cells_box.v | 7 +++++++ techlibs/ice40/lut.lut | 2 ++ 3 files changed, 16 insertions(+) diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/cells.box index e4cfb71e6..d775efa78 100644 --- a/techlibs/ice40/cells.box +++ b/techlibs/ice40/cells.box @@ -1,6 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/81c33a3/icefuzz/timings_hx8k.txt + # NB: Inputs/Outputs must be ordered alphabetically # Inputs: CI I0 I1 # Outputs: CO SB_CARRY 1 1 3 1 126 259 231 + +# Inputs: I0 I1 I2 I3 +# Outputs: O +SB_LUT4 2 1 4 1 +316 379 400 449 diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/cells_box.v index cca88f9aa..e2a54a42c 100644 --- a/techlibs/ice40/cells_box.v +++ b/techlibs/ice40/cells_box.v @@ -3,3 +3,10 @@ module SB_CARRY (output CO, input CI, I0, I1); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule +(* abc_box_id = 2 *) +module SB_LUT4 (output O, input I0, I1, I2, I3); + parameter [15:0] LUT_INIT = 0; + // Indicate this is a black-box + assign O = 1'b0; +endmodule + diff --git a/techlibs/ice40/lut.lut b/techlibs/ice40/lut.lut index 48da89f46..6fa0682da 100644 --- a/techlibs/ice40/lut.lut +++ b/techlibs/ice40/lut.lut @@ -1,3 +1,5 @@ +# From https://github.com/cliffordwolf/icestorm/blob/81c33a3/icefuzz/timings_hx8k.txt + 1 1 316 2 1 316 379 3 1 316 379 400 From 5c134980c4d0f5c1f961d50c9c1fe1752d966e48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 21:05:44 -0700 Subject: [PATCH 164/514] Optimise --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce93ffb28..06496dbc3 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -585,18 +585,17 @@ struct XAigerWriter if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; - int num_inputs = 0; // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { + log_assert(c.second.size() == 1); if (cell->input(c.first)) { box_inputs += c.second.size(); if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - ++num_inputs; holes_cell->setPort(c.first, holes_wire); } } From 17fb6c35229bddc636021def319547e4d8fdf271 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 08:40:50 -0700 Subject: [PATCH 165/514] Fix spacing --- techlibs/ice40/lut.lut | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/ice40/lut.lut b/techlibs/ice40/lut.lut index 6fa0682da..eef997869 100644 --- a/techlibs/ice40/lut.lut +++ b/techlibs/ice40/lut.lut @@ -1,6 +1,6 @@ # From https://github.com/cliffordwolf/icestorm/blob/81c33a3/icefuzz/timings_hx8k.txt - -1 1 316 -2 1 316 379 -3 1 316 379 400 -4 1 316 379 400 449 +# I3 I2 I1 I0 +1 1 316 +2 1 316 379 +3 1 316 379 400 +4 1 316 379 400 449 From e1b550d203eecacc5b79b87de7a3d49ed5713382 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 10:55:23 -0700 Subject: [PATCH 166/514] Ignore a/i/o/h XAIGER extensions --- frontends/aiger/aigerparse.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index f2d21f1db..9c8cee63a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -368,6 +368,13 @@ void AigerReader::parse_xaiger() f >> s; log_debug("n: '%s'\n", s.c_str()); } + else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') { + uint32_t dataSize = parse_xaiger_literal(f); + f.ignore(dataSize); + } + else { + break; + } } else if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); From d59185f1d6bdc5f63704b41553bfc72eecd84223 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:08:42 -0700 Subject: [PATCH 167/514] Remove init* from xaiger, also topo-sort cells for box flow --- backends/aiger/xaiger.cc | 248 ++++++++++++++++++++++++--------------- 1 file changed, 155 insertions(+), 93 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 06496dbc3..ed0fc656f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,6 +20,8 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/utils.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -46,9 +48,8 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - pool initstate_bits; + //pool initstate_bits; vector> ci_bits, co_bits; - dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -58,11 +59,11 @@ struct XAigerWriter dict ordered_outputs; dict ordered_latches; - dict init_inputs; - int initstate_ff = 0; - vector box_list; + //dict init_inputs; + //int initstate_ff = 0; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -76,10 +77,10 @@ struct XAigerWriter { aig_map[bit] = -1; - if (initstate_bits.count(bit)) { - log_assert(initstate_ff > 0); - aig_map[bit] = initstate_ff; - } else + //if (initstate_bits.count(bit)) { + // log_assert(initstate_ff > 0); + // aig_map[bit] = initstate_ff; + //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -170,8 +171,35 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + dict> bit_drivers, bit_users; + TopoSort toposort; + bool abc_box_seen = false; + for (auto cell : module->cells()) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + // HACK!!! + if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) + continue; + + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -204,58 +232,92 @@ struct XAigerWriter continue; } - if (cell->type == "$initstate") - { - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - undriven_bits.erase(Y); - initstate_bits.insert(Y); - continue; - } + //if (cell->type == "$initstate") + //{ + // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + // undriven_bits.erase(Y); + // initstate_bits.insert(Y); + // continue; + //} RTLIL::Module* box_module = module->design->module(cell->type); - bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); - - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - if (abc_box) - co_bits.emplace_back(b, 0); - else if (b.wire) { + if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; output_bits.insert(b); - if (!b.wire->port_input) - unused_bits.erase(b); + unused_bits.erase(b); } } - } - if (is_output) { - SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - if (abc_box) - ci_bits.emplace_back(O, 0); - else { + if (is_output) { + SigBit O = sigmap(b); input_bits.insert(O); if (!O.wire->port_output) undriven_bits.erase(O); } } } - if (!type_map.count(cell->type)) - type_map[cell->type] = type_map.size()+1; + } + else + abc_box_seen = true; + + //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + } + + if (abc_box_seen) { + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + toposort.sort(); + log_assert(!toposort.found_loops); + + for (auto cell_name : toposort.sorted) { + RTLIL::Cell *cell = module->cell(cell_name); + RTLIL::Module* box_module = module->design->module(cell->type); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; + + cell->connections_.sort(RTLIL::sort_by_id_str()); + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + /*if (!w->port_input)*/ { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + /*if (!output_bits.count(b))*/ + co_bits.emplace_back(b, 0); + } + } + if (is_output) { + SigBit O = sigmap(b); + /*if (!input_bits.count(O))*/ + ci_bits.emplace_back(O, 0); + } + } + } + + box_list.emplace_back(cell); } - if (abc_box) - box_list.emplace_back(cell); - //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { @@ -329,15 +391,15 @@ struct XAigerWriter aig_m++, aig_i++; } - if (zinit_mode) - { - for (auto it : ff_map) { - if (init_map.count(it.first)) - continue; - aig_m++, aig_i++; - init_inputs[it.first] = 2*aig_m; - } - } + //if (zinit_mode) + //{ + // for (auto it : ff_map) { + // if (init_map.count(it.first)) + // continue; + // aig_m++, aig_i++; + // init_inputs[it.first] = 2*aig_m; + // } + //} for (auto it : ff_map) { aig_m++, aig_l++; @@ -349,29 +411,29 @@ struct XAigerWriter aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); } - if (!initstate_bits.empty() || !init_inputs.empty()) { - aig_m++, aig_l++; - initstate_ff = 2*aig_m+1; - aig_latchinit.push_back(0); - } + //if (!initstate_bits.empty() || !init_inputs.empty()) { + // aig_m++, aig_l++; + // initstate_ff = 2*aig_m+1; + // aig_latchinit.push_back(0); + //} - if (zinit_mode) - { - for (auto it : ff_map) - { - int l = ordered_latches[it.first]; + //if (zinit_mode) + //{ + // for (auto it : ff_map) + // { + // int l = ordered_latches[it.first]; - if (aig_latchinit.at(l) == 1) - aig_map[it.first] ^= 1; + // if (aig_latchinit.at(l) == 1) + // aig_map[it.first] ^= 1; - if (aig_latchinit.at(l) == 2) - { - int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - } - } - } + // if (aig_latchinit.at(l) == 2) + // { + // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + // } + // } + //} for (auto it : ff_map) { int a = bit2aig(it.second); @@ -382,8 +444,8 @@ struct XAigerWriter aig_latchin.push_back(a); } - if (!initstate_bits.empty() || !init_inputs.empty()) - aig_latchin.push_back(1); + //if (!initstate_bits.empty() || !init_inputs.empty()) + // aig_latchin.push_back(1); for (auto &c : co_bits) { RTLIL::SigBit bit = c.first; @@ -518,14 +580,14 @@ struct XAigerWriter symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // if (GetSize(wire) != 1) + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + // else + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); @@ -687,12 +749,12 @@ struct XAigerWriter continue; } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + // continue; + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); From a7632ab3326c5247b8152a53808413b259c13253 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:10:04 -0700 Subject: [PATCH 168/514] Try using an ICE40_CARRY_LUT primitive to avoid ABC issues --- techlibs/ice40/arith_map.v | 37 +++++++++++++++++++++-------------- techlibs/ice40/cells.box | 12 ++++-------- techlibs/ice40/cells_box.v | 24 ++++++++++++++--------- techlibs/ice40/cells_map.v | 24 +++++++++++++++++++++++ techlibs/ice40/cells_sim.v | 22 +++++++++++++++++++++ techlibs/ice40/ice40_opt.cc | 16 +++++++++++++-- techlibs/ice40/synth_ice40.cc | 2 +- 7 files changed, 102 insertions(+), 35 deletions(-) diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 4449fdc1b..eefc375dd 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -44,25 +44,32 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - SB_CARRY carry ( - .I0(AA[i]), - .I1(BB[i]), - .CI(C[i]), - .CO(CO[i]) - ); - SB_LUT4 #( - // I0: 1010 1010 1010 1010 - // I1: 1100 1100 1100 1100 - // I2: 1111 0000 1111 0000 - // I3: 1111 1111 0000 0000 - .LUT_INIT(16'b 0110_1001_1001_0110) - ) adder ( - .I0(1'b0), + ICE40_CARRY_LUT carry_lut ( .I1(AA[i]), .I2(BB[i]), - .I3(C[i]), + .CI(C[i]), + .CO(CO[i]), .O(Y[i]) ); +// SB_CARRY carry ( +// .I0(AA[i]), +// .I1(BB[i]), +// .CI(C[i]), +// .CO(CO[i]) +// ); +// SB_LUT4 #( +// // I0: 1010 1010 1010 1010 +// // I1: 1100 1100 1100 1100 +// // I2: 1111 0000 1111 0000 +// // I3: 1111 1111 0000 0000 +// .LUT_INIT(16'b 0110_1001_1001_0110) +// ) adder ( +// .I0(1'b0), +// .I1(AA[i]), +// .I2(BB[i]), +// .I3(C[i]), +// .O(Y[i]) +// ); end endgenerate assign X = AA ^ BB; diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/cells.box index d775efa78..34d1f372e 100644 --- a/techlibs/ice40/cells.box +++ b/techlibs/ice40/cells.box @@ -2,12 +2,8 @@ # NB: Inputs/Outputs must be ordered alphabetically -# Inputs: CI I0 I1 -# Outputs: CO -SB_CARRY 1 1 3 1 +# Inputs: CI I1 I2 +# Outputs: CO O +ICE40_CARRY_LUT 1 1 3 2 126 259 231 - -# Inputs: I0 I1 I2 I3 -# Outputs: O -SB_LUT4 2 1 4 1 -316 379 400 449 +316 400 379 diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/cells_box.v index e2a54a42c..d0eb8708c 100644 --- a/techlibs/ice40/cells_box.v +++ b/techlibs/ice40/cells_box.v @@ -1,12 +1,18 @@ (* abc_box_id = 1 *) -module SB_CARRY (output CO, input CI, I0, I1); - assign CO = (I0 && I1) || ((I0 || I1) && CI); -endmodule +module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2); + assign CO = (I1 && I2) || ((I1 || I2) && CI); -(* abc_box_id = 2 *) -module SB_LUT4 (output O, input I0, I1, I2, I3); - parameter [15:0] LUT_INIT = 0; - // Indicate this is a black-box - assign O = 1'b0; -endmodule + wire I0, I3; + assign I0 = 1'b0; + assign I3 = CI; + // I0: 1010 1010 1010 1010 + // I1: 1100 1100 1100 1100 + // I2: 1111 0000 1111 0000 + // I3: 1111 1111 0000 0000 + localparam [15:0] LUT_INIT = 16'b 0110_1001_1001_0110; + wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; + wire [3:0] s2 = I2 ? s3[ 7:4] : s3[3:0]; + wire [1:0] s1 = I1 ? s2[ 3:2] : s2[1:0]; + assign O = I0 ? s1[1] : s1[0]; +endmodule diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index d0ddfd02e..d4c611686 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -57,3 +57,27 @@ module \$lut (A, Y); endgenerate endmodule `endif + +`ifndef NO_CARRY +module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2); + SB_CARRY carry ( + .I0(I1), + .I1(I2), + .CI(CI), + .CO(CO), + ); + SB_LUT4 #( + // I0: 1010 1010 1010 1010 + // I1: 1100 1100 1100 1100 + // I2: 1111 0000 1111 0000 + // I3: 1111 1111 0000 0000 + .LUT_INIT(16'b 0110_1001_1001_0110) + ) adder ( + .I0(1'b0), + .I1(I1), + .I2(I2), + .I3(CI), + .O(O) + ); +endmodule +`endif diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 322c1e5c7..b5a739a63 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -1384,3 +1384,25 @@ module SB_MAC16 ( assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI; assign O = {Oh, Ol}; endmodule + +module ICE40_CARRY_LUT (input CI, input I1, input I2, output CO, output O); + SB_CARRY carry ( + .I0(I1), + .I1(I2), + .CI(CI), + .CO(CO), + ); + SB_LUT4 #( + // I0: 1010 1010 1010 1010 + // I1: 1100 1100 1100 1100 + // I2: 1111 0000 1111 0000 + // I3: 1111 1111 0000 0000 + .LUT_INIT(16'b 0110_1001_1001_0110) + ) adder ( + .I0(1'b0), + .I1(I1), + .I2(I2), + .I3(CI), + .O(O) + ); +endmodule diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index f528607d6..edb293b93 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -47,16 +47,20 @@ static void run_ice40_opts(Module *module) continue; } - if (cell->type == "\\SB_CARRY") + if (cell->type.in("\\SB_CARRY", "\\ICE40_CARRY_LUT")) { SigSpec non_const_inputs, replacement_output; int count_zeros = 0, count_ones = 0; SigBit inbit[3] = { - get_bit_or_zero(cell->getPort("\\I0")), get_bit_or_zero(cell->getPort("\\I1")), get_bit_or_zero(cell->getPort("\\CI")) }; + if (cell->type == "\\SB_CARRY") + inbit[2] = get_bit_or_zero(cell->getPort("\\I0")); + else if (cell->type == "\\ICE40_CARRY_LUT") + inbit[2] = get_bit_or_zero(cell->getPort("\\I2")); + else log_abort(); for (int i = 0; i < 3; i++) if (inbit[i].wire == nullptr) { if (inbit[i] == State::S1) @@ -79,6 +83,14 @@ static void run_ice40_opts(Module *module) module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized away SB_CARRY cell %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); + + if (cell->type == "\\ICE40_CARRY_LUT") + module->addLut(NEW_ID, + { RTLIL::S0, cell->getPort("\\I1"), cell->getPort("\\I2"), cell->getPort("\\CI") }, + cell->getPort("\\O"), + RTLIL::Const("0110_1001_1001_0110"), + cell->get_src_attribute()); + module->remove(cell); } continue; diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 3faa10b4f..d09a1184c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -296,7 +296,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_merge"); run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); } - run("techmap -D NO_LUT -map +/ice40/cells_map.v"); + run("techmap -D NO_LUT -D NO_CARRY -map +/ice40/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); run("ice40_ffinit"); From c1ebe51a75ef8ce47d6b1406fa87b15bd8f97760 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:10:20 -0700 Subject: [PATCH 169/514] Revert "Try using an ICE40_CARRY_LUT primitive to avoid ABC issues" This reverts commit a7632ab3326c5247b8152a53808413b259c13253. --- techlibs/ice40/arith_map.v | 37 ++++++++++++++--------------------- techlibs/ice40/cells.box | 12 ++++++++---- techlibs/ice40/cells_box.v | 26 ++++++++++-------------- techlibs/ice40/cells_map.v | 24 ----------------------- techlibs/ice40/cells_sim.v | 22 --------------------- techlibs/ice40/ice40_opt.cc | 16 ++------------- techlibs/ice40/synth_ice40.cc | 2 +- 7 files changed, 36 insertions(+), 103 deletions(-) diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index eefc375dd..4449fdc1b 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -44,32 +44,25 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice - ICE40_CARRY_LUT carry_lut ( + SB_CARRY carry ( + .I0(AA[i]), + .I1(BB[i]), + .CI(C[i]), + .CO(CO[i]) + ); + SB_LUT4 #( + // I0: 1010 1010 1010 1010 + // I1: 1100 1100 1100 1100 + // I2: 1111 0000 1111 0000 + // I3: 1111 1111 0000 0000 + .LUT_INIT(16'b 0110_1001_1001_0110) + ) adder ( + .I0(1'b0), .I1(AA[i]), .I2(BB[i]), - .CI(C[i]), - .CO(CO[i]), + .I3(C[i]), .O(Y[i]) ); -// SB_CARRY carry ( -// .I0(AA[i]), -// .I1(BB[i]), -// .CI(C[i]), -// .CO(CO[i]) -// ); -// SB_LUT4 #( -// // I0: 1010 1010 1010 1010 -// // I1: 1100 1100 1100 1100 -// // I2: 1111 0000 1111 0000 -// // I3: 1111 1111 0000 0000 -// .LUT_INIT(16'b 0110_1001_1001_0110) -// ) adder ( -// .I0(1'b0), -// .I1(AA[i]), -// .I2(BB[i]), -// .I3(C[i]), -// .O(Y[i]) -// ); end endgenerate assign X = AA ^ BB; diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/cells.box index 34d1f372e..d775efa78 100644 --- a/techlibs/ice40/cells.box +++ b/techlibs/ice40/cells.box @@ -2,8 +2,12 @@ # NB: Inputs/Outputs must be ordered alphabetically -# Inputs: CI I1 I2 -# Outputs: CO O -ICE40_CARRY_LUT 1 1 3 2 +# Inputs: CI I0 I1 +# Outputs: CO +SB_CARRY 1 1 3 1 126 259 231 -316 400 379 + +# Inputs: I0 I1 I2 I3 +# Outputs: O +SB_LUT4 2 1 4 1 +316 379 400 449 diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/cells_box.v index d0eb8708c..e2a54a42c 100644 --- a/techlibs/ice40/cells_box.v +++ b/techlibs/ice40/cells_box.v @@ -1,18 +1,12 @@ (* abc_box_id = 1 *) -module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2); - assign CO = (I1 && I2) || ((I1 || I2) && CI); - - wire I0, I3; - assign I0 = 1'b0; - assign I3 = CI; - - // I0: 1010 1010 1010 1010 - // I1: 1100 1100 1100 1100 - // I2: 1111 0000 1111 0000 - // I3: 1111 1111 0000 0000 - localparam [15:0] LUT_INIT = 16'b 0110_1001_1001_0110; - wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; - wire [3:0] s2 = I2 ? s3[ 7:4] : s3[3:0]; - wire [1:0] s1 = I1 ? s2[ 3:2] : s2[1:0]; - assign O = I0 ? s1[1] : s1[0]; +module SB_CARRY (output CO, input CI, I0, I1); + assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule + +(* abc_box_id = 2 *) +module SB_LUT4 (output O, input I0, I1, I2, I3); + parameter [15:0] LUT_INIT = 0; + // Indicate this is a black-box + assign O = 1'b0; +endmodule + diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index d4c611686..d0ddfd02e 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -57,27 +57,3 @@ module \$lut (A, Y); endgenerate endmodule `endif - -`ifndef NO_CARRY -module ICE40_CARRY_LUT (output CO, O, input CI, I1, I2); - SB_CARRY carry ( - .I0(I1), - .I1(I2), - .CI(CI), - .CO(CO), - ); - SB_LUT4 #( - // I0: 1010 1010 1010 1010 - // I1: 1100 1100 1100 1100 - // I2: 1111 0000 1111 0000 - // I3: 1111 1111 0000 0000 - .LUT_INIT(16'b 0110_1001_1001_0110) - ) adder ( - .I0(1'b0), - .I1(I1), - .I2(I2), - .I3(CI), - .O(O) - ); -endmodule -`endif diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index b5a739a63..322c1e5c7 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -1384,25 +1384,3 @@ module SB_MAC16 ( assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI; assign O = {Oh, Ol}; endmodule - -module ICE40_CARRY_LUT (input CI, input I1, input I2, output CO, output O); - SB_CARRY carry ( - .I0(I1), - .I1(I2), - .CI(CI), - .CO(CO), - ); - SB_LUT4 #( - // I0: 1010 1010 1010 1010 - // I1: 1100 1100 1100 1100 - // I2: 1111 0000 1111 0000 - // I3: 1111 1111 0000 0000 - .LUT_INIT(16'b 0110_1001_1001_0110) - ) adder ( - .I0(1'b0), - .I1(I1), - .I2(I2), - .I3(CI), - .O(O) - ); -endmodule diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index edb293b93..f528607d6 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -47,20 +47,16 @@ static void run_ice40_opts(Module *module) continue; } - if (cell->type.in("\\SB_CARRY", "\\ICE40_CARRY_LUT")) + if (cell->type == "\\SB_CARRY") { SigSpec non_const_inputs, replacement_output; int count_zeros = 0, count_ones = 0; SigBit inbit[3] = { + get_bit_or_zero(cell->getPort("\\I0")), get_bit_or_zero(cell->getPort("\\I1")), get_bit_or_zero(cell->getPort("\\CI")) }; - if (cell->type == "\\SB_CARRY") - inbit[2] = get_bit_or_zero(cell->getPort("\\I0")); - else if (cell->type == "\\ICE40_CARRY_LUT") - inbit[2] = get_bit_or_zero(cell->getPort("\\I2")); - else log_abort(); for (int i = 0; i < 3; i++) if (inbit[i].wire == nullptr) { if (inbit[i] == State::S1) @@ -83,14 +79,6 @@ static void run_ice40_opts(Module *module) module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized away SB_CARRY cell %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); - - if (cell->type == "\\ICE40_CARRY_LUT") - module->addLut(NEW_ID, - { RTLIL::S0, cell->getPort("\\I1"), cell->getPort("\\I2"), cell->getPort("\\CI") }, - cell->getPort("\\O"), - RTLIL::Const("0110_1001_1001_0110"), - cell->get_src_attribute()); - module->remove(cell); } continue; diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index d09a1184c..3faa10b4f 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -296,7 +296,7 @@ struct SynthIce40Pass : public ScriptPass run("opt_merge"); run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); } - run("techmap -D NO_LUT -D NO_CARRY -map +/ice40/cells_map.v"); + run("techmap -D NO_LUT -map +/ice40/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); run("ice40_ffinit"); From 42c33db22caeffa05bde59d915a4433b756929a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:15:34 -0700 Subject: [PATCH 170/514] Rename to abc.* --- techlibs/ice40/{cells.box => abc.box} | 0 techlibs/ice40/{lut.lut => abc.lut} | 0 techlibs/ice40/{cells_box.v => abc.v} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename techlibs/ice40/{cells.box => abc.box} (100%) rename techlibs/ice40/{lut.lut => abc.lut} (100%) rename techlibs/ice40/{cells_box.v => abc.v} (100%) diff --git a/techlibs/ice40/cells.box b/techlibs/ice40/abc.box similarity index 100% rename from techlibs/ice40/cells.box rename to techlibs/ice40/abc.box diff --git a/techlibs/ice40/lut.lut b/techlibs/ice40/abc.lut similarity index 100% rename from techlibs/ice40/lut.lut rename to techlibs/ice40/abc.lut diff --git a/techlibs/ice40/cells_box.v b/techlibs/ice40/abc.v similarity index 100% rename from techlibs/ice40/cells_box.v rename to techlibs/ice40/abc.v From 4fb9ccfcd81db6d2e574bea3d142b714126d1123 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:22:03 -0700 Subject: [PATCH 171/514] synth_ice40 to use renamed files --- techlibs/ice40/synth_ice40.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 3faa10b4f..91cd063a2 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -317,9 +317,9 @@ struct SynthIce40Pass : public ScriptPass } if (!noabc) { if (abc == "abc9") { - run("read_verilog +/ice40/cells_box.v"); + run("read_verilog +/ice40/abc.v"); run("techmap -map +/techmap.v A:abc_box_id"); - run(abc + " -dress -lut +/ice40/lut.lut -box +/ice40/cells.box", "(skip if -noabc)"); + run(abc + " -dress -lut +/ice40/abc.lut -box +/ice40/abc.box", "(skip if -noabc)"); run("blackbox A:abc_box_id"); } else From 1eade0667102b50afa927f64e22968dd28365167 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:27:02 -0700 Subject: [PATCH 172/514] Also update Makefile.inc --- techlibs/ice40/Makefile.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index cd992bb24..abfede011 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -28,9 +28,9 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_box.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/lut.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) From 58847df1b94d2caaa1fe959acb04425397f3567f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:27:45 -0700 Subject: [PATCH 173/514] Mark seq output ports with "abc_flop_q" attr --- techlibs/ice40/cells_sim.v | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 322c1e5c7..cf7b9d252 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -132,18 +132,18 @@ endmodule // Positive Edge SiliconBlue FF Cells -module SB_DFF (output `SB_DFF_REG, input C, D); +module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, D); always @(posedge C) Q <= D; endmodule -module SB_DFFE (output `SB_DFF_REG, input C, E, D); +module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); always @(posedge C) if (E) Q <= D; endmodule -module SB_DFFSR (output `SB_DFF_REG, input C, R, D); +module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(posedge C) if (R) Q <= 0; @@ -151,7 +151,7 @@ module SB_DFFSR (output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFR (output `SB_DFF_REG, input C, R, D); +module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -159,7 +159,7 @@ module SB_DFFR (output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFSS (output `SB_DFF_REG, input C, S, D); +module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(posedge C) if (S) Q <= 1; @@ -167,7 +167,7 @@ module SB_DFFSS (output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFS (output `SB_DFF_REG, input C, S, D); +module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -175,7 +175,7 @@ module SB_DFFS (output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D); +module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(posedge C) if (E) begin if (R) @@ -185,7 +185,7 @@ module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFER (output `SB_DFF_REG, input C, E, R, D); +module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -193,7 +193,7 @@ module SB_DFFER (output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D); +module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(posedge C) if (E) begin if (S) @@ -203,7 +203,7 @@ module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFES (output `SB_DFF_REG, input C, E, S, D); +module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -213,18 +213,18 @@ endmodule // Negative Edge SiliconBlue FF Cells -module SB_DFFN (output `SB_DFF_REG, input C, D); +module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, D); always @(negedge C) Q <= D; endmodule -module SB_DFFNE (output `SB_DFF_REG, input C, E, D); +module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); always @(negedge C) if (E) Q <= D; endmodule -module SB_DFFNSR (output `SB_DFF_REG, input C, R, D); +module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(negedge C) if (R) Q <= 0; @@ -232,7 +232,7 @@ module SB_DFFNSR (output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNR (output `SB_DFF_REG, input C, R, D); +module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -240,7 +240,7 @@ module SB_DFFNR (output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNSS (output `SB_DFF_REG, input C, S, D); +module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(negedge C) if (S) Q <= 1; @@ -248,7 +248,7 @@ module SB_DFFNSS (output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNS (output `SB_DFF_REG, input C, S, D); +module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -256,7 +256,7 @@ module SB_DFFNS (output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D); +module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(negedge C) if (E) begin if (R) @@ -266,7 +266,7 @@ module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D); +module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -274,7 +274,7 @@ module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D); +module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(negedge C) if (E) begin if (S) @@ -284,7 +284,7 @@ module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D); +module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -295,7 +295,7 @@ endmodule // SiliconBlue RAM Cells module SB_RAM40_4K ( - output [15:0] RDATA, + (* abc_flop_q *) output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, input WCLK, WCLKE, WE, @@ -463,7 +463,7 @@ module SB_RAM40_4K ( endmodule module SB_RAM40_4KNR ( - output [15:0] RDATA, + (* abc_flop_q *) output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, input WCLK, WCLKE, WE, @@ -528,7 +528,7 @@ module SB_RAM40_4KNR ( endmodule module SB_RAM40_4KNW ( - output [15:0] RDATA, + (* abc_flop_q *) output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, input WCLKN, WCLKE, WE, @@ -593,7 +593,7 @@ module SB_RAM40_4KNW ( endmodule module SB_RAM40_4KNRNW ( - output [15:0] RDATA, + (* abc_flop_q *) output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, input WCLKN, WCLKE, WE, From 2b860809e9dae557a435f01a3125e6dd4b4a8599 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:28:19 -0700 Subject: [PATCH 174/514] Stop topological sort at abc_flop_q --- backends/aiger/xaiger.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ed0fc656f..070d6d403 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,14 +180,20 @@ struct XAigerWriter toposort.node(cell->name); for (const auto &conn : cell->connections()) { - // HACK!!! - if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) - continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } From fd89c1056ef8a8010c77a5b645df14908e3c68d9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:33:32 -0700 Subject: [PATCH 175/514] Working ABC9 script --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e28e3e59a..429bdb293 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,8 @@ #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; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs" +//#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps" +#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m -s" #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" @@ -388,7 +389,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3); abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); - abc_script += "; &ps -l -s"; abc_script = add_echos_to_abc_cmd(abc_script); for (size_t i = 0; i+1 < abc_script.size(); i++) From 437fec0d88b4a2ad172edf0d1a861a38845f3b1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 13:01:17 -0700 Subject: [PATCH 176/514] Map to SB_LUT4 from fastest input first --- techlibs/ice40/cells_map.v | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index d0ddfd02e..287c48b11 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -37,20 +37,24 @@ module \$lut (A, Y); generate if (WIDTH == 1) begin - SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0)); + localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}}; + SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0])); end else if (WIDTH == 2) begin - SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0)); + localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}}; + SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0])); end else if (WIDTH == 3) begin - SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0)); + localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}}; + SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0])); end else if (WIDTH == 4) begin + localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]}; SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); + .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; end From 1ec5f18346dd3f50e2340f4b79239a045ce7dd72 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 14:43:45 -0700 Subject: [PATCH 177/514] Cope with inout ports --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 070d6d403..14fa4fb7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -197,9 +197,12 @@ struct XAigerWriter continue; } - if (cell->input(conn.first)) + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); + } if (cell->output(conn.first)) for (auto bit : sigmap(conn.second)) @@ -287,7 +290,18 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); +#ifndef NDEBUG + toposort.analyze_loops = true; +#endif toposort.sort(); +#ifndef NDEBUG + for (auto &it : toposort.loops) { + log(" loop"); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif log_assert(!toposort.found_loops); for (auto cell_name : toposort.sorted) { From 671cca59a9f63f9fb7102727eb4dee1b18fe3ef6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 14:44:08 -0700 Subject: [PATCH 178/514] Missing abc_flop_q attribute on SPRAM --- techlibs/ice40/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index cf7b9d252..70cd51ed1 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -887,7 +887,7 @@ module SB_SPRAM256KA ( input [15:0] DATAIN, input [3:0] MASKWREN, input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF, - output reg [15:0] DATAOUT + (* abc_flop_q *) output reg [15:0] DATAOUT ); `ifndef BLACKBOX `ifndef EQUIV From 6f3e5297dbf1a0b28e6bfa51990f957939d722d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:04:46 -0700 Subject: [PATCH 179/514] Add "-device" argument to synth_ice40 --- techlibs/ice40/Makefile.inc | 6 ++++-- techlibs/ice40/{abc.box => hx8k.box} | 4 ++-- techlibs/ice40/{abc.lut => hx8k.lut} | 2 +- techlibs/ice40/synth_ice40.cc | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) rename techlibs/ice40/{abc.box => hx8k.box} (70%) rename techlibs/ice40/{abc.lut => hx8k.lut} (64%) diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index abfede011..efcea6e98 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -28,9 +28,11 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.box)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx8k.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx8k.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/up5k.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/up5k.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) diff --git a/techlibs/ice40/abc.box b/techlibs/ice40/hx8k.box similarity index 70% rename from techlibs/ice40/abc.box rename to techlibs/ice40/hx8k.box index d775efa78..c31f7bf39 100644 --- a/techlibs/ice40/abc.box +++ b/techlibs/ice40/hx8k.box @@ -1,4 +1,4 @@ -# From https://github.com/cliffordwolf/icestorm/blob/81c33a3/icefuzz/timings_hx8k.txt +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt # NB: Inputs/Outputs must be ordered alphabetically @@ -10,4 +10,4 @@ SB_CARRY 1 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O SB_LUT4 2 1 4 1 -316 379 400 449 +449 400 379 316 diff --git a/techlibs/ice40/abc.lut b/techlibs/ice40/hx8k.lut similarity index 64% rename from techlibs/ice40/abc.lut rename to techlibs/ice40/hx8k.lut index eef997869..3b3bb11e2 100644 --- a/techlibs/ice40/abc.lut +++ b/techlibs/ice40/hx8k.lut @@ -1,4 +1,4 @@ -# From https://github.com/cliffordwolf/icestorm/blob/81c33a3/icefuzz/timings_hx8k.txt +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt # I3 I2 I1 I0 1 1 316 2 1 316 379 diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 91cd063a2..2981875eb 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass log("\n"); log("This command runs synthesis for iCE40 FPGAs.\n"); log("\n"); + log(" -device < hx1k | lp384 | lp1k | lp8k | hx8k | u4k | up5k >\n"); + log(" optimise the synthesis netlist for the specified device.\n"); + log(" HX1K is the default target if no device argument specified.\n"); + log("\n"); log(" -top \n"); log(" use the specified module as top module\n"); log("\n"); @@ -102,7 +106,7 @@ struct SynthIce40Pass : public ScriptPass } - string top_opt, blif_file, edif_file, json_file, abc; + string top_opt, blif_file, edif_file, json_file, abc, device_opt; bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr; int min_ce_use; @@ -124,6 +128,7 @@ struct SynthIce40Pass : public ScriptPass abc2 = false; vpr = false; abc = "abc"; + device_opt = "hx1k"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -210,12 +215,18 @@ struct SynthIce40Pass : public ScriptPass abc = "abc9"; continue; } + if (args[argidx] == "-device" && argidx+1 < args.size()) { + device_opt = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); + if (device_opt != "hx1k" && device_opt !="lp384" && device_opt != "lp1k" && device_opt !="lp8k" && device_opt !="hx8k" && device_opt != "u4k" && device_opt != "up5k") + log_cmd_error("Invalid or no family specified: '%s'\n", device_opt.c_str()); log_header(design, "Executing SYNTH_ICE40 pass.\n"); log_push(); @@ -319,7 +330,7 @@ struct SynthIce40Pass : public ScriptPass if (abc == "abc9") { run("read_verilog +/ice40/abc.v"); run("techmap -map +/techmap.v A:abc_box_id"); - run(abc + " -dress -lut +/ice40/abc.lut -box +/ice40/abc.box", "(skip if -noabc)"); + run(abc + stringf(" -dress -lut +/ice40/%s.lut -box +/ice40/%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); run("blackbox A:abc_box_id"); } else From 3105a8a6531545efefe228fb4fc4b7b09ae127e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:07:44 -0700 Subject: [PATCH 180/514] Update error message --- techlibs/ice40/synth_ice40.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 2981875eb..62589ad87 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -226,7 +226,7 @@ struct SynthIce40Pass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); if (device_opt != "hx1k" && device_opt !="lp384" && device_opt != "lp1k" && device_opt !="lp8k" && device_opt !="hx8k" && device_opt != "u4k" && device_opt != "up5k") - log_cmd_error("Invalid or no family specified: '%s'\n", device_opt.c_str()); + log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); log_header(design, "Executing SYNTH_ICE40 pass.\n"); log_push(); From 4b520ae627f696499eb91b1b4e762ef0b1dfdd2d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:10:22 -0700 Subject: [PATCH 181/514] Fix grammar --- techlibs/intel/synth_intel.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 0f1d7a7b5..d2291b8d4 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -38,7 +38,7 @@ struct SynthIntelPass : public ScriptPass { log("\n"); log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n"); log(" generate the synthesis netlist for the specified family.\n"); - log(" MAX10 is the default target if not family argument specified.\n"); + log(" MAX10 is the default target if no family argument specified.\n"); log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n"); log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n"); log("\n"); @@ -146,7 +146,7 @@ struct SynthIntelPass : public ScriptPass { if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); if (family_opt != "max10" && family_opt !="a10gx" && family_opt != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10") - log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str()); + log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str()); log_header(design, "Executing SYNTH_INTEL pass.\n"); log_push(); From 5c0853fc518bbbad77b819a5c916e438d0e33cb0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:10:39 -0700 Subject: [PATCH 182/514] Add up5k timings --- techlibs/ice40/up5k.box | 13 +++++++++++++ techlibs/ice40/up5k.lut | 6 ++++++ 2 files changed, 19 insertions(+) create mode 100644 techlibs/ice40/up5k.box create mode 100644 techlibs/ice40/up5k.lut diff --git a/techlibs/ice40/up5k.box b/techlibs/ice40/up5k.box new file mode 100644 index 000000000..94df1df8f --- /dev/null +++ b/techlibs/ice40/up5k.box @@ -0,0 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt + +# NB: Inputs/Outputs must be ordered alphabetically + +# Inputs: CI I0 I1 +# Outputs: CO +SB_CARRY 1 1 3 1 +278 675 609 + +# Inputs: I0 I1 I2 I3 +# Outputs: O +SB_LUT4 2 1 4 1 +1285 1231 1205 874 diff --git a/techlibs/ice40/up5k.lut b/techlibs/ice40/up5k.lut new file mode 100644 index 000000000..1e4fcadb6 --- /dev/null +++ b/techlibs/ice40/up5k.lut @@ -0,0 +1,6 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt +# I3 I2 I1 I0 +1 1 874 +2 1 874 1205 +3 1 874 1205 1231 +4 1 874 1205 1231 1285 From abcd3103ffa8965160e2d489c81e0a61c9a937bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:11:14 -0700 Subject: [PATCH 183/514] Do not print slack histogram --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 429bdb293..8b5b172ab 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -26,7 +26,7 @@ #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; &if; &mfs; &ps" -#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m -s" +#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m" #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" From c795e14d25b42ae28bd4b8f7e259e969442437b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:19:02 -0700 Subject: [PATCH 184/514] Reduce to three devices: hx, lp, u --- techlibs/ice40/{hx8k.box => hx.box} | 0 techlibs/ice40/{hx8k.lut => hx.lut} | 0 techlibs/ice40/lp.box | 13 +++++++++++++ techlibs/ice40/lp.lut | 6 ++++++ techlibs/ice40/synth_ice40.cc | 8 ++++---- techlibs/ice40/{up5k.box => u.box} | 0 techlibs/ice40/{up5k.lut => u.lut} | 0 7 files changed, 23 insertions(+), 4 deletions(-) rename techlibs/ice40/{hx8k.box => hx.box} (100%) rename techlibs/ice40/{hx8k.lut => hx.lut} (100%) create mode 100644 techlibs/ice40/lp.box create mode 100644 techlibs/ice40/lp.lut rename techlibs/ice40/{up5k.box => u.box} (100%) rename techlibs/ice40/{up5k.lut => u.lut} (100%) diff --git a/techlibs/ice40/hx8k.box b/techlibs/ice40/hx.box similarity index 100% rename from techlibs/ice40/hx8k.box rename to techlibs/ice40/hx.box diff --git a/techlibs/ice40/hx8k.lut b/techlibs/ice40/hx.lut similarity index 100% rename from techlibs/ice40/hx8k.lut rename to techlibs/ice40/hx.lut diff --git a/techlibs/ice40/lp.box b/techlibs/ice40/lp.box new file mode 100644 index 000000000..7eb8e86e0 --- /dev/null +++ b/techlibs/ice40/lp.box @@ -0,0 +1,13 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt + +# NB: Inputs/Outputs must be ordered alphabetically + +# Inputs: CI I0 I1 +# Outputs: CO +SB_CARRY 1 1 3 1 +186 675 609 + +# Inputs: I0 I1 I2 I3 +# Outputs: O +SB_LUT4 2 1 4 1 +465 558 589 661 diff --git a/techlibs/ice40/lp.lut b/techlibs/ice40/lp.lut new file mode 100644 index 000000000..e72f760a2 --- /dev/null +++ b/techlibs/ice40/lp.lut @@ -0,0 +1,6 @@ +# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt +# I3 I2 I1 I0 +1 1 465 +2 1 465 558 +3 1 465 558 589 +4 1 465 558 589 661 diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 62589ad87..7c95588e4 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -37,9 +37,9 @@ struct SynthIce40Pass : public ScriptPass log("\n"); log("This command runs synthesis for iCE40 FPGAs.\n"); log("\n"); - log(" -device < hx1k | lp384 | lp1k | lp8k | hx8k | u4k | up5k >\n"); + log(" -device < hx | lp | u >\n"); log(" optimise the synthesis netlist for the specified device.\n"); - log(" HX1K is the default target if no device argument specified.\n"); + log(" HX is the default target if no device argument specified.\n"); log("\n"); log(" -top \n"); log(" use the specified module as top module\n"); @@ -128,7 +128,7 @@ struct SynthIce40Pass : public ScriptPass abc2 = false; vpr = false; abc = "abc"; - device_opt = "hx1k"; + device_opt = "hx"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -225,7 +225,7 @@ struct SynthIce40Pass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); - if (device_opt != "hx1k" && device_opt !="lp384" && device_opt != "lp1k" && device_opt !="lp8k" && device_opt !="hx8k" && device_opt != "u4k" && device_opt != "up5k") + if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); log_header(design, "Executing SYNTH_ICE40 pass.\n"); diff --git a/techlibs/ice40/up5k.box b/techlibs/ice40/u.box similarity index 100% rename from techlibs/ice40/up5k.box rename to techlibs/ice40/u.box diff --git a/techlibs/ice40/up5k.lut b/techlibs/ice40/u.lut similarity index 100% rename from techlibs/ice40/up5k.lut rename to techlibs/ice40/u.lut From 8fd455c91070e1e4cf05cbece79999fef04bb9b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 15:19:48 -0700 Subject: [PATCH 185/514] Update Makefile.inc too --- techlibs/ice40/Makefile.inc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index efcea6e98..cb2121a11 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -29,10 +29,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx8k.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx8k.lut)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/up5k.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/up5k.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/lp.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/lp.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/u.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/u.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) From 23cd2e5de042949bf47a9c72b8dd8fae48e900ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 16:03:29 -0700 Subject: [PATCH 186/514] Fix $anyseq warning and cleanup --- backends/aiger/xaiger.cc | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 14fa4fb7f..582c49976 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -252,7 +252,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ + if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -271,8 +271,7 @@ struct XAigerWriter if (is_output) { SigBit O = sigmap(b); input_bits.insert(O); - if (!O.wire->port_output) - undriven_bits.erase(O); + undriven_bits.erase(O); } } } @@ -312,24 +311,19 @@ struct XAigerWriter cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - co_bits.emplace_back(b, 0); - } + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, 0); } if (is_output) { SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, 0); } } } @@ -367,9 +361,6 @@ struct XAigerWriter //co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs - //for (auto bit : co_bits) - // ci_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); From 709f76c10742602f5cbc0d32805a325ecab982ee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 16:35:27 -0700 Subject: [PATCH 187/514] Remove use of abc_box_id in stat --- passes/cmds/stat.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 3909c4c8c..54f4ea817 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -269,9 +269,6 @@ struct StatPass : public Pass { if (mod->get_bool_attribute("\\top")) top_mod = mod; - if (mod->attributes.count("\\abc_box_id")) - continue; - statdata_t data(design, mod, width_mode, cell_area); mod_stat[mod->name] = data; From a20ed260e1b12da64bc4b40682c53145f6ffe827 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 16:36:03 -0700 Subject: [PATCH 188/514] Skip if abc_box_id earlier --- passes/techmap/abc9.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8b5b172ab..18f860e36 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1402,14 +1402,14 @@ struct Abc9Pass : public Pass { for (auto mod : design->selected_modules()) { + if (mod->attributes.count("\\abc_box_id")) + continue; + if (mod->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(mod)); continue; } - if (mod->attributes.count("\\abc_box_id")) - continue; - assign_map.set(mod); signal_init.clear(); From ed5e75ed7d5a4515e23a496570c7eb03f48742b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 09:02:58 -0700 Subject: [PATCH 189/514] Rename to abc_*.{box,lut} --- techlibs/ice40/{hx.box => abc_hx.box} | 0 techlibs/ice40/{lp.box => abc_lp.box} | 0 techlibs/ice40/{lp.lut => abc_lp.lut} | 0 techlibs/ice40/{hx.lut => abc_lut.box} | 0 techlibs/ice40/{u.box => abc_u.box} | 0 techlibs/ice40/{u.lut => abc_u.lut} | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename techlibs/ice40/{hx.box => abc_hx.box} (100%) rename techlibs/ice40/{lp.box => abc_lp.box} (100%) rename techlibs/ice40/{lp.lut => abc_lp.lut} (100%) rename techlibs/ice40/{hx.lut => abc_lut.box} (100%) rename techlibs/ice40/{u.box => abc_u.box} (100%) rename techlibs/ice40/{u.lut => abc_u.lut} (100%) diff --git a/techlibs/ice40/hx.box b/techlibs/ice40/abc_hx.box similarity index 100% rename from techlibs/ice40/hx.box rename to techlibs/ice40/abc_hx.box diff --git a/techlibs/ice40/lp.box b/techlibs/ice40/abc_lp.box similarity index 100% rename from techlibs/ice40/lp.box rename to techlibs/ice40/abc_lp.box diff --git a/techlibs/ice40/lp.lut b/techlibs/ice40/abc_lp.lut similarity index 100% rename from techlibs/ice40/lp.lut rename to techlibs/ice40/abc_lp.lut diff --git a/techlibs/ice40/hx.lut b/techlibs/ice40/abc_lut.box similarity index 100% rename from techlibs/ice40/hx.lut rename to techlibs/ice40/abc_lut.box diff --git a/techlibs/ice40/u.box b/techlibs/ice40/abc_u.box similarity index 100% rename from techlibs/ice40/u.box rename to techlibs/ice40/abc_u.box diff --git a/techlibs/ice40/u.lut b/techlibs/ice40/abc_u.lut similarity index 100% rename from techlibs/ice40/u.lut rename to techlibs/ice40/abc_u.lut From 8024f4189738af196f7ce432d95c73efd1f02955 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 09:04:34 -0700 Subject: [PATCH 190/514] Fix rename --- techlibs/ice40/{abc_lut.box => abc_hx.lut} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename techlibs/ice40/{abc_lut.box => abc_hx.lut} (100%) diff --git a/techlibs/ice40/abc_lut.box b/techlibs/ice40/abc_hx.lut similarity index 100% rename from techlibs/ice40/abc_lut.box rename to techlibs/ice40/abc_hx.lut From 7b6ab937c14ae30d331527c71dffbc050aaba13c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 09:05:22 -0700 Subject: [PATCH 191/514] Make SB_LUT4 a blackbox --- techlibs/ice40/abc_hx.box | 2 +- techlibs/ice40/abc_lp.box | 2 +- techlibs/ice40/abc_u.box | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index c31f7bf39..5a18a8423 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -9,5 +9,5 @@ SB_CARRY 1 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 1 4 1 +SB_LUT4 2 0 4 1 449 400 379 316 diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index 7eb8e86e0..87fe81585 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -9,5 +9,5 @@ SB_CARRY 1 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 1 4 1 +SB_LUT4 2 0 4 1 465 558 589 661 diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 94df1df8f..5035a4169 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -9,5 +9,5 @@ SB_CARRY 1 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 1 4 1 +SB_LUT4 2 0 4 1 1285 1231 1205 874 From 9278192efe5ae6382f4e011abaf417b45a6abfef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 09:58:34 -0700 Subject: [PATCH 192/514] Also update Makefile.inc --- techlibs/ice40/Makefile.inc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index cb2121a11..d258d5a5d 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -28,13 +28,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc.v)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/hx.lut)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/lp.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/lp.lut)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/u.box)) -$(eval $(call add_share_file,share/ice40,techlibs/ice40/u.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh)) $(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh)) From c997a77014b5d8dbfb24e77bb8157454619ea366 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:19:45 -0700 Subject: [PATCH 193/514] Ignore 'whitebox' attr in flatten with "-wb" option --- kernel/rtlil.h | 4 ++-- passes/techmap/techmap.cc | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c11c020c1..db0a8f762 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -575,8 +575,8 @@ struct RTLIL::AttrObject void set_bool_attribute(RTLIL::IdString id); bool get_bool_attribute(RTLIL::IdString id) const; - bool get_blackbox_attribute() const { - return get_bool_attribute("\\blackbox") || get_bool_attribute("\\whitebox"); + bool get_blackbox_attribute(bool ignore_wb=false) const { + return get_bool_attribute("\\blackbox") || (!ignore_wb && get_bool_attribute("\\whitebox")); } void set_strpool_attribute(RTLIL::IdString id, const pool &data); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index d694e8165..82c815e2e 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -84,6 +84,7 @@ struct TechmapWorker bool flatten_mode; bool recursive_mode; bool autoproc_mode; + bool ignore_wb; TechmapWorker() { @@ -92,6 +93,7 @@ struct TechmapWorker flatten_mode = false; recursive_mode = false; autoproc_mode = false; + ignore_wb = false; } std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) @@ -472,7 +474,7 @@ struct TechmapWorker RTLIL::Module *tpl = map->modules_[tpl_name]; std::map parameters(cell->parameters.begin(), cell->parameters.end()); - if (tpl->get_blackbox_attribute()) + if (tpl->get_blackbox_attribute(ignore_wb)) continue; if (!flatten_mode) @@ -1145,7 +1147,7 @@ struct FlattenPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" flatten [selection]\n"); + log(" flatten [options] [selection]\n"); log("\n"); log("This pass flattens the design by replacing cells by their implementation. This\n"); log("pass is very similar to the 'techmap' pass. The only difference is that this\n"); @@ -1154,17 +1156,29 @@ struct FlattenPass : public Pass { log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n"); log("flattened by this command.\n"); log("\n"); + log(" -wb\n"); + log(" Ignore the 'whitebox' attribute on cell implementations.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FLATTEN pass (flatten design).\n"); log_push(); - extra_args(args, 1, design); - TechmapWorker worker; worker.flatten_mode = true; + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-wb") { + worker.ignore_wb = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + std::map> celltypeMap; for (auto module : design->modules()) celltypeMap[module->name].insert(module->name); @@ -1209,7 +1223,7 @@ struct FlattenPass : public Pass { dict new_modules; for (auto mod : vector(design->modules())) - if (used_modules[mod->name] || mod->get_blackbox_attribute()) { + if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) { new_modules[mod->name] = mod; } else { log("Deleting now unused module %s.\n", log_id(mod)); From 79881141e2f9354a12df81277b82e011f52994ae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:30:45 -0700 Subject: [PATCH 194/514] write_json to not write contents (cells/wires) of whiteboxes --- backends/json/json.cc | 115 ++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..b4f82a3fe 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,72 +130,75 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n },\n"); + f << stringf("\n }"); - f << stringf(" \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); + if (!module->get_blackbox_attribute()) { + f << stringf(",\n \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); + } } - } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + first2 = false; + } + f << stringf("\n },\n"); + } + f << stringf(" \"connections\": {"); bool first2 = true; for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); first2 = false; } - f << stringf("\n },\n"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf(" \"connections\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); - first2 = false; - } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; - } - f << stringf("\n },\n"); + f << stringf("\n },\n"); - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n }"); } - f << stringf("\n }\n"); + f << stringf("\n"); f << stringf(" }"); } From 4c327cf316404fbedb1d26b0aebecaaf01d46f6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:32:41 -0700 Subject: [PATCH 195/514] Use new -wb flag for ABC flow --- backends/aiger/xaiger.cc | 60 ++++++++++++++++++----------------- techlibs/ice40/abc.v | 12 ------- techlibs/ice40/cells_sim.v | 2 ++ techlibs/ice40/synth_ice40.cc | 10 ++---- 4 files changed, 36 insertions(+), 48 deletions(-) delete mode 100644 techlibs/ice40/abc.v diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582c49976..975780488 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -103,7 +103,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -177,36 +177,38 @@ struct XAigerWriter for (auto cell : module->cells()) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + if (!ignore_boxes) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } - - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); } if (cell->type == "$_NOT_") @@ -249,7 +251,7 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = module->design->module(cell->type); + RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; @@ -705,12 +707,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; diff --git a/techlibs/ice40/abc.v b/techlibs/ice40/abc.v deleted file mode 100644 index e2a54a42c..000000000 --- a/techlibs/ice40/abc.v +++ /dev/null @@ -1,12 +0,0 @@ -(* abc_box_id = 1 *) -module SB_CARRY (output CO, input CI, I0, I1); - assign CO = (I0 && I1) || ((I0 || I1) && CI); -endmodule - -(* abc_box_id = 2 *) -module SB_LUT4 (output O, input I0, I1, I2, I3); - parameter [15:0] LUT_INIT = 0; - // Indicate this is a black-box - assign O = 1'b0; -endmodule - diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 70cd51ed1..dba563e37 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -118,6 +118,7 @@ endmodule // SiliconBlue Logic Cells +(* abc_box_id = 2 *) module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; @@ -126,6 +127,7 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule +(* abc_box_id = 1, whitebox *) module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 7c95588e4..84abf7181 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -lib +/ice40/cells_sim.v"); + run("read_verilog -wb +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } @@ -327,12 +327,8 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); } if (!noabc) { - if (abc == "abc9") { - run("read_verilog +/ice40/abc.v"); - run("techmap -map +/techmap.v A:abc_box_id"); - run(abc + stringf(" -dress -lut +/ice40/%s.lut -box +/ice40/%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); - run("blackbox A:abc_box_id"); - } + if (abc == "abc9") + run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); else run(abc + " -lut 4", "(skip if -noabc)"); } From b531efd6d9febe679571c897a8e22dbeaedeb96e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:35:16 -0700 Subject: [PATCH 196/514] Spelling --- backends/aiger/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index dfe506c66..516e538a5 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -685,7 +685,7 @@ struct AigerBackend : public Backend { log("invariant constraints.\n"); log("\n"); log(" -ascii\n"); - log(" write ASCII version of AGIER format\n"); + log(" write ASCII version of AIGER format\n"); log("\n"); log(" -zinit\n"); log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); From 21701cc1df461a77d39afaddf0f31ab78f307e32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:39:36 -0700 Subject: [PATCH 197/514] read_aiger to parse 'r' extension --- frontends/aiger/aigerparse.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9c8cee63a..db5f9d2b9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -363,6 +363,24 @@ void AigerReader::parse_xaiger() module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } + else if (c == 'r') { + uint32_t dataSize = parse_xaiger_literal(f); + uint32_t flopNum = parse_xaiger_literal(f); + f.ignore(flopNum * sizeof(uint32_t)); + log_assert(inputs.size() >= flopNum); + for (auto it = inputs.end() - flopNum; it != inputs.end(); ++it) { + log_assert((*it)->port_input); + (*it)->port_input = false; + } + inputs.erase(inputs.end() - flopNum, inputs.end()); + log_assert(outputs.size() >= flopNum); + for (auto it = outputs.end() - flopNum; it != outputs.end(); ++it) { + log_assert((*it)->port_output); + (*it)->port_output = false; + } + outputs.erase(outputs.end() - flopNum, outputs.end()); + module->fixup_ports(); + } else if (c == 'n') { parse_xaiger_literal(f); f >> s; From 6bdf98d591a4ee5752d687d35238b454288e1d96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:43:13 -0700 Subject: [PATCH 198/514] Add flop support for write_xaiger --- backends/aiger/xaiger.cc | 94 +++++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 975780488..587294a40 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -177,6 +178,9 @@ struct XAigerWriter for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + if (!ignore_boxes) { toposort.node(cell->name); for (const auto &conn : cell->connections()) @@ -189,7 +193,6 @@ struct XAigerWriter continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); @@ -251,8 +254,32 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; - if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + log_assert(inst_module); + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (!inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -311,6 +338,7 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { for (auto b : c.second.bits()) { @@ -394,10 +422,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -472,6 +510,12 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -629,7 +673,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -644,10 +688,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -700,6 +744,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); @@ -792,7 +864,7 @@ struct XAigerWriter RTLIL::SigBit b = c.first; RTLIL::Wire *wire = b.wire; int i = b.offset; - int a = c.second; + int a = bit2aig(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } @@ -845,7 +917,7 @@ struct XAigerBackend : public Backend { log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); - log(" write ASCII version of AGIER format\n"); + log(" write ASCII version of AIGER format\n"); log("\n"); log(" -zinit\n"); log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); From ca1eb98a975e1d95629f8e55bfdd021221edf0b7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:46:32 -0700 Subject: [PATCH 199/514] Add SB_DFF* to boxes --- techlibs/ice40/abc_hx.box | 104 +++++++++++++++++++++++++++++++++++++- techlibs/ice40/abc_lp.box | 104 +++++++++++++++++++++++++++++++++++++- techlibs/ice40/abc_u.box | 104 +++++++++++++++++++++++++++++++++++++- 3 files changed, 306 insertions(+), 6 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index 5a18a8423..9ebdae18b 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -2,12 +2,112 @@ # NB: Inputs/Outputs must be ordered alphabetically +# Inputs: C D +# Outputs: Q +SB_DFF 1 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFE 2 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFSR 3 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFR 4 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFSS 5 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFS 6 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFESR 7 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFER 8 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFESS 9 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFES 10 0 4 1 +- - - - + +# Inputs: C D +# Outputs: Q +SB_DFFN 11 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFNE 12 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNSR 13 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNR 14 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNSS 15 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNS 16 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNESR 17 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNER 18 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNESS 19 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNES 20 0 4 1 +- - - - + # Inputs: CI I0 I1 # Outputs: CO -SB_CARRY 1 1 3 1 +SB_CARRY 21 1 3 1 126 259 231 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 0 4 1 +SB_LUT4 22 0 4 1 449 400 379 316 diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index 87fe81585..464821dac 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -2,12 +2,112 @@ # NB: Inputs/Outputs must be ordered alphabetically +# Inputs: C D +# Outputs: Q +SB_DFF 1 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFE 2 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFSR 3 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFR 4 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFSS 5 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFS 6 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFESR 7 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFER 8 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFESS 9 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFES 10 0 4 1 +- - - - + +# Inputs: C D +# Outputs: Q +SB_DFFN 11 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFNE 12 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNSR 13 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNR 14 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNSS 15 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNS 16 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNESR 17 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNER 18 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNESS 19 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNES 20 0 4 1 +- - - - + # Inputs: CI I0 I1 # Outputs: CO -SB_CARRY 1 1 3 1 +SB_CARRY 21 1 3 1 186 675 609 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 0 4 1 +SB_LUT4 22 0 4 1 465 558 589 661 diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 5035a4169..314bff401 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -2,12 +2,112 @@ # NB: Inputs/Outputs must be ordered alphabetically +# Inputs: C D +# Outputs: Q +SB_DFF 1 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFE 2 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFSR 3 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFR 4 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFSS 5 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFS 6 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFESR 7 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFER 8 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFESS 9 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFES 10 0 4 1 +- - - - + +# Inputs: C D +# Outputs: Q +SB_DFFN 11 0 2 1 +- - + +# Inputs: C D E +# Outputs: Q +SB_DFFNE 12 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNSR 13 0 3 1 +- - - + +# Inputs: C D R +# Outputs: Q +SB_DFFNR 14 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNSS 15 0 3 1 +- - - + +# Inputs: C D S +# Outputs: Q +SB_DFFNS 16 0 3 1 +- - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNESR 17 0 4 1 +- - - - + +# Inputs: C D E R +# Outputs: Q +SB_DFFNER 18 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNESS 19 0 4 1 +- - - - + +# Inputs: C D E S +# Outputs: Q +SB_DFFNES 20 0 4 1 +- - - - + # Inputs: CI I0 I1 # Outputs: CO -SB_CARRY 1 1 3 1 +SB_CARRY 21 1 3 1 278 675 609 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 2 0 4 1 +SB_LUT4 22 0 4 1 1285 1231 1205 874 From cf66416110f60b7dce10a78960898ceb52f51626 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:46:53 -0700 Subject: [PATCH 200/514] Annotate SB_DFF* with abc_flop and abc_box_id --- techlibs/ice40/cells_sim.v | 71 ++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index dba563e37..a6f1fc9de 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -118,7 +118,7 @@ endmodule // SiliconBlue Logic Cells -(* abc_box_id = 2 *) +(* abc_box_id = 22 * module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; @@ -127,25 +127,35 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 1, whitebox *) +(* abc_box_id = 21, whitebox *) module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule // Positive Edge SiliconBlue FF Cells -module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, D); +(* abc_box_id = 1, abc_flop *) +`ifdef ABC_FLOPS + (* whitebox *) +`endif +module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); +`ifndef ABC_FLOPS always @(posedge C) Q <= D; +`else + assign Q = D; +`endif endmodule -module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); +//(* abc_box_id = 2, abc_flop *) +module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D); always @(posedge C) if (E) Q <= D; endmodule -module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +//(* abc_box_id = 3, abc_flop *) +module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); always @(posedge C) if (R) Q <= 0; @@ -153,7 +163,8 @@ module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +//(* abc_box_id = 4, abc_flop *) +module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -161,7 +172,8 @@ module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +//(* abc_box_id = 5, abc_flop *) +module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); always @(posedge C) if (S) Q <= 1; @@ -169,7 +181,8 @@ module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +//(* abc_box_id = 6, abc_flop *) +module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -177,7 +190,8 @@ module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +//(* abc_box_id = 7, abc_flop *) +module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); always @(posedge C) if (E) begin if (R) @@ -187,7 +201,8 @@ module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +//(* abc_box_id = 8, abc_flop *) +module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -195,7 +210,8 @@ module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +//(* abc_box_id = 9, abc_flop *) +module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); always @(posedge C) if (E) begin if (S) @@ -205,7 +221,8 @@ module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +//(* abc_box_id = 10, abc_flop *) +module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -215,18 +232,21 @@ endmodule // Negative Edge SiliconBlue FF Cells -module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, D); +//(* abc_box_id = 11, abc_flop *) +module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); always @(negedge C) Q <= D; endmodule -module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); +//(* abc_box_id = 12, abc_flop *) +module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D); always @(negedge C) if (E) Q <= D; endmodule -module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +//(* abc_box_id = 13, abc_flop *) +module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); always @(negedge C) if (R) Q <= 0; @@ -234,7 +254,8 @@ module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +//(* abc_box_id = 14, abc_flop *) +module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -242,7 +263,8 @@ module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +//(* abc_box_id = 15, abc_flop *) +module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); always @(negedge C) if (S) Q <= 1; @@ -250,7 +272,8 @@ module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +//(* abc_box_id = 16, abc_flop *) +module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -258,7 +281,8 @@ module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +//(* abc_box_id = 17, abc_flop *) +module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); always @(negedge C) if (E) begin if (R) @@ -268,7 +292,8 @@ module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +//(* abc_box_id = 18, abc_flop *) +module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -276,7 +301,8 @@ module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +//(* abc_box_id = 19, abc_flop *) +module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); always @(negedge C) if (E) begin if (S) @@ -286,7 +312,8 @@ module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +//(* abc_box_id = 20, abc_flop *) +module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); always @(negedge C, posedge S) if (S) Q <= 1; From 0919f36b88bed88e6dbfa23381540dc8ee035962 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:50:11 -0700 Subject: [PATCH 201/514] Missing close bracket --- techlibs/ice40/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index a6f1fc9de..1d104c5d7 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -118,7 +118,7 @@ endmodule // SiliconBlue Logic Cells -(* abc_box_id = 22 * +(* abc_box_id = 22 *) module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; From 19b660ff6e8b493ff3de43ce59e393c56b9a6b3b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 23:07:16 -0700 Subject: [PATCH 202/514] Fix SB_DFF comb model --- techlibs/ice40/cells_sim.v | 2 +- techlibs/ice40/synth_ice40.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 1d104c5d7..c49b29ab3 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -143,7 +143,7 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) in always @(posedge C) Q <= D; `else - assign Q = D; + always @* Q = D; `endif endmodule diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 84abf7181..d5d354701 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -wb +/ice40/cells_sim.v"); + run("read_verilog -wb -D ABC_FLOPS +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } @@ -293,7 +293,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap"); else run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); - if (retime || help_mode) + if ((retime || help_mode) && abc != "abc9") run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); } From 2776925bcf04e67d1c33812e102d1195dca393bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:36:38 -0700 Subject: [PATCH 203/514] Make SB_DFF whitebox --- techlibs/ice40/abc_hx.box | 2 +- techlibs/ice40/abc_lp.box | 2 +- techlibs/ice40/abc_u.box | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index 9ebdae18b..994f3091d 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 0 2 1 +SB_DFF 1 1 2 1 - - # Inputs: C D E diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index 464821dac..002b7bba4 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 0 2 1 +SB_DFF 1 1 2 1 - - # Inputs: C D E diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 314bff401..cb336181c 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 0 2 1 +SB_DFF 1 1 2 1 - - # Inputs: C D E From 3544a7cd7b6b2595d25c56c5b1c3fbf6c9cccf7e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:37:10 -0700 Subject: [PATCH 204/514] ignore_boxes -> holes_mode --- backends/aiger/xaiger.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 587294a40..71aaebfd9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,7 +104,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -181,7 +181,7 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (!ignore_boxes) { + if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { @@ -398,7 +398,7 @@ struct XAigerWriter for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { + if (!undriven_bits.empty() && !holes_mode) { undriven_bits.sort(); for (auto bit : undriven_bits) { log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); @@ -511,7 +511,6 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; aig_o++; aig_outputs.push_back(ff_aig_map.at(f.second)); } @@ -779,12 +778,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; From 35f44f3ae8618b5e5da068c3df3d35b2fdc3d1aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:44:53 -0700 Subject: [PATCH 205/514] Do not assume inst_module is always present --- backends/aiger/xaiger.cc | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 71aaebfd9..31b74f9aa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -193,12 +193,13 @@ struct XAigerWriter continue; } - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); + if (inst_module) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + } } if (cell->input(conn.first)) { @@ -254,7 +255,6 @@ struct XAigerWriter // continue; //} - log_assert(inst_module); if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { @@ -279,7 +279,7 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (!inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -386,15 +386,12 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all POs and COs that are undriven - for (auto bit : undriven_bits) { - //co_bits.erase(bit); + // Erase all POs that are undriven + for (auto bit : undriven_bits) output_bits.erase(bit); - } // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); - for (auto bit : unused_bits) undriven_bits.erase(bit); From 76bba4918205445e9129895f071d35e42e23efec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 15:47:36 -0700 Subject: [PATCH 206/514] Fixes for simple_abc9 tests --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 31b74f9aa..e93fd35f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,13 +180,14 @@ struct XAigerWriter { RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { + if (known_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -279,7 +280,10 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + abc_box_seen = true; + } + else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -305,8 +309,6 @@ struct XAigerWriter } } } - else - abc_box_seen = true; //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -381,6 +383,8 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); + else + alias_map[new_bit] = bit; output_bits.insert(new_bit); } } From 59c993e4372df1624b538bd12aee96381c874f6f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 15:47:53 -0700 Subject: [PATCH 207/514] Select to find union of both sets on stack --- tests/simple_abc9/run-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index af003d52e..97f284378 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -19,4 +19,4 @@ fi cp ../simple/*.v . DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_'" +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" From af4652522fd01aaec84664e65d7fe1474c578c49 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 21:09:55 -0700 Subject: [PATCH 208/514] ABC_FLOPS -> ABC_MODEL -- only whitebox if ABC_MODEL set --- techlibs/ice40/cells_sim.v | 9 ++++++--- techlibs/ice40/synth_ice40.cc | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index c49b29ab3..a98bc30d9 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -127,7 +127,10 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 21, whitebox *) +(* abc_box_id = 21 *) +`ifdef ABC_MODEL + (* whitebox *) +`endif module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule @@ -135,11 +138,11 @@ endmodule // Positive Edge SiliconBlue FF Cells (* abc_box_id = 1, abc_flop *) -`ifdef ABC_FLOPS +`ifdef ABC_MODEL (* whitebox *) `endif module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); -`ifndef ABC_FLOPS +`ifndef ABC_MODEL always @(posedge C) Q <= D; `else diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index d5d354701..7cedecdff 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -wb -D ABC_FLOPS +/ice40/cells_sim.v"); + run("read_verilog -wb -D ABC_MODEL +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } From d7f0700bae9785a55353ca76fe9f354ee4ffe03e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 15:19:02 -0700 Subject: [PATCH 209/514] Convert to use #945 --- techlibs/ice40/cells_sim.v | 10 ++-------- techlibs/ice40/synth_ice40.cc | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index a98bc30d9..93d970762 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -127,20 +127,14 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 21 *) -`ifdef ABC_MODEL - (* whitebox *) -`endif +(* abc_box_id = 21, lib_whitebox *) module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule // Positive Edge SiliconBlue FF Cells -(* abc_box_id = 1, abc_flop *) -`ifdef ABC_MODEL - (* whitebox *) -`endif +(* abc_box_id = 1, abc_flop, lib_whitebox *) module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); `ifndef ABC_MODEL always @(posedge C) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 7cedecdff..718f9d9e0 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -wb -D ABC_MODEL +/ice40/cells_sim.v"); + run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } From 2c6358ea25d595bf014a564860e3ffde7eddb2cb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:21:17 -0700 Subject: [PATCH 210/514] Remove kernel/cost.cc since master has refactored it --- Makefile | 1 - kernel/cost.cc | 75 -------------------------------------------------- 2 files changed, 76 deletions(-) delete mode 100644 kernel/cost.cc diff --git a/Makefile b/Makefile index d9e01c865..249c1d0ee 100644 --- a/Makefile +++ b/Makefile @@ -471,7 +471,6 @@ $(eval $(call add_include_file,backends/ilang/ilang_backend.h)) OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o OBJS += kernel/cellaigs.o kernel/celledges.o -OBJS += kernel/cost.o kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' diff --git a/kernel/cost.cc b/kernel/cost.cc deleted file mode 100644 index 175f01e64..000000000 --- a/kernel/cost.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/cost.h" - -YOSYS_NAMESPACE_BEGIN - -int get_cell_cost(RTLIL::IdString type, const dict ¶meters, - RTLIL::Design *design, dict *mod_cost_cache) -{ - static dict gate_cost = { - { "$_BUF_", 1 }, - { "$_NOT_", 2 }, - { "$_AND_", 4 }, - { "$_NAND_", 4 }, - { "$_OR_", 4 }, - { "$_NOR_", 4 }, - { "$_ANDNOT_", 4 }, - { "$_ORNOT_", 4 }, - { "$_XOR_", 8 }, - { "$_XNOR_", 8 }, - { "$_AOI3_", 6 }, - { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, - { "$_MUX_", 4 } - }; - - if (gate_cost.count(type)) - return gate_cost.at(type); - - if (parameters.empty() && design && design->module(type)) - { - RTLIL::Module *mod = design->module(type); - - if (mod->attributes.count("\\cost")) - return mod->attributes.at("\\cost").as_int(); - - dict local_mod_cost_cache; - if (mod_cost_cache == nullptr) - mod_cost_cache = &local_mod_cost_cache; - - if (mod_cost_cache->count(mod->name)) - return mod_cost_cache->at(mod->name); - - int module_cost = 1; - for (auto c : mod->cells()) - module_cost += get_cell_cost(c, mod_cost_cache); - - (*mod_cost_cache)[mod->name] = module_cost; - return module_cost; - } - - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); - return 1; -} - -YOSYS_NAMESPACE_END From b780c0a7de3b0f095099461af1434624d2af0c32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:22:29 -0700 Subject: [PATCH 211/514] Allow POs to be PIs in XAIG --- backends/aiger/xaiger.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e93fd35f7..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -161,12 +161,8 @@ struct XAigerWriter } } - for (auto bit : input_bits) { - if (!bit.wire->port_output) - undriven_bits.erase(bit); - // Erase POs that are also PIs - output_bits.erase(bit); - } + for (auto bit : input_bits) + undriven_bits.erase(bit); for (auto bit : output_bits) if (!bit.wire->port_input) @@ -275,7 +271,8 @@ struct XAigerWriter } } } - if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); undriven_bits.erase(q); From eaf3c247729365cec776e147f380ce59f7dccd4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:54:19 -0700 Subject: [PATCH 212/514] Temporarily remove 'r' extension --- backends/aiger/xaiger.cc | 84 +++-------------------------------- frontends/aiger/aigerparse.cc | 18 -------- 2 files changed, 7 insertions(+), 95 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..d6438a297 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; - vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -175,7 +174,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -252,32 +250,7 @@ struct XAigerWriter // continue; //} - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - d = b; - } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - - ff_bits.emplace_back(d, q); - undriven_bits.erase(q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -420,20 +393,10 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - auto bit = f.second; - aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - auto r = aig_map.insert(std::make_pair(c.first, c.second)); - if (!r.second) { - ff_aig_map[c.first] = c.second; - } + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -508,11 +471,6 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto &f : ff_bits) { - aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); - } - if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -670,7 +628,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -685,10 +643,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -741,34 +699,6 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } - if (holes_module) { holes_module->fixup_ports(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4e3f5e7c9..3fa6f5c2d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -360,24 +360,6 @@ void AigerReader::parse_xaiger() module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } - else if (c == 'r') { - uint32_t dataSize = parse_xaiger_literal(f); - uint32_t flopNum = parse_xaiger_literal(f); - f.ignore(flopNum * sizeof(uint32_t)); - log_assert(inputs.size() >= flopNum); - for (auto it = inputs.end() - flopNum; it != inputs.end(); ++it) { - log_assert((*it)->port_input); - (*it)->port_input = false; - } - inputs.erase(inputs.end() - flopNum, inputs.end()); - log_assert(outputs.size() >= flopNum); - for (auto it = outputs.end() - flopNum; it != outputs.end(); ++it) { - log_assert((*it)->port_output); - (*it)->port_output = false; - } - outputs.erase(outputs.end() - flopNum, outputs.end()); - module->fixup_ports(); - } else if (c == 'n') { parse_xaiger_literal(f); f >> s; From 79fb291dbedbb6cf582925329e8140cbc7e502a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 12:14:37 -0700 Subject: [PATCH 213/514] Cleanup, call pmux2shiftx even without -nosrl --- techlibs/xilinx/Makefile.inc | 5 ++--- techlibs/xilinx/{cells.box => abc.box} | 8 ++++---- techlibs/xilinx/{cells.lut => abc.lut} | 0 techlibs/xilinx/cells_box.v | 19 ----------------- techlibs/xilinx/cells_sim.v | 28 +++++++++++++++----------- techlibs/xilinx/synth_xilinx.cc | 15 +++++++------- 6 files changed, 30 insertions(+), 45 deletions(-) rename techlibs/xilinx/{cells.box => abc.box} (79%) rename techlibs/xilinx/{cells.lut => abc.lut} (100%) delete mode 100644 techlibs/xilinx/cells_box.v diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 43be55d51..296edace9 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,9 +30,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.box)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_box.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.lut)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/cells.box b/techlibs/xilinx/abc.box similarity index 79% rename from techlibs/xilinx/cells.box rename to techlibs/xilinx/abc.box index 5ad284f47..d572817df 100644 --- a/techlibs/xilinx/cells.box +++ b/techlibs/xilinx/abc.box @@ -2,13 +2,13 @@ # from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 # F7BMUX slower than F7AMUX -# Inputs: 0 1 S0 -# Outputs: OUT +# Inputs: I0 I1 S0 +# Outputs: O F7BMUX 1 1 3 1 217 223 296 -# Inputs: 0 1 S0 -# Outputs: OUT +# Inputs: I0 I1 S0 +# Outputs: O MUXF8 2 1 3 1 104 94 273 diff --git a/techlibs/xilinx/cells.lut b/techlibs/xilinx/abc.lut similarity index 100% rename from techlibs/xilinx/cells.lut rename to techlibs/xilinx/abc.lut diff --git a/techlibs/xilinx/cells_box.v b/techlibs/xilinx/cells_box.v deleted file mode 100644 index ef6f81d27..000000000 --- a/techlibs/xilinx/cells_box.v +++ /dev/null @@ -1,19 +0,0 @@ -(* abc_box_id = 1 *) -module MUXF7(output O, input I0, I1, S); - assign O = S ? I1 : I0; -endmodule - -(* abc_box_id = 2 *) -module MUXF8(output O, input I0, I1, S); - assign O = S ? I1 : I0; -endmodule - -(* abc_box_id = 3 *) -module MUXCY(output O, input CI, DI, S); - assign O = S ? CI : DI; -endmodule - -(* abc_box_id = 4 *) -module XORCY(output O, input CI, LI); - assign O = CI ^ LI; -endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3a4540b83..8b231480f 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -155,18 +155,22 @@ module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5); assign O5 = I0 ? s5_1[1] : s5_1[0]; endmodule +(* abc_box_id = 3, lib_whitebox *) module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule +(* abc_box_id = 1, lib_whitebox *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +(* abc_box_id = 2, lib_whitebox *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +(* abc_box_id = 4, lib_whitebox *) module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule @@ -202,7 +206,7 @@ endmodule `endif -module FDRE (output reg Q, input C, CE, D, R); +module FDRE ((* abc_flop_q *) output reg Q, input C, CE, input D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -214,7 +218,7 @@ module FDRE (output reg Q, input C, CE, D, R); endcase endgenerate endmodule -module FDSE (output reg Q, input C, CE, D, S); +module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -226,7 +230,7 @@ module FDSE (output reg Q, input C, CE, D, S); endcase endgenerate endmodule -module FDCE (output reg Q, input C, CE, D, CLR); +module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -240,7 +244,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); endcase endgenerate endmodule -module FDPE (output reg Q, input C, CE, D, PRE); +module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -254,32 +258,32 @@ module FDPE (output reg Q, input C, CE, D, PRE); endcase endgenerate endmodule -module FDRE_1 (output reg Q, input C, CE, D, R); +module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; endmodule -module FDSE_1 (output reg Q, input C, CE, D, S); +module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule -module FDCE_1 (output reg Q, input C, CE, D, CLR); +module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -module FDPE_1 (output reg Q, input C, CE, D, PRE); +module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule module RAM64X1D ( - output DPO, SPO, + (* abc_flop_q *) output DPO, SPO, input D, WCLK, WE, input A0, A1, A2, A3, A4, A5, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 @@ -296,7 +300,7 @@ module RAM64X1D ( endmodule module RAM128X1D ( - output DPO, SPO, + (* abc_flop_q *) output DPO, SPO, input D, WCLK, WE, input [6:0] A, DPRA ); @@ -310,7 +314,7 @@ module RAM128X1D ( endmodule module SRL16E ( - output Q, + (* abc_flop_q *) output Q, input A0, A1, A2, A3, CE, CLK, D ); parameter [15:0] INIT = 16'h0000; @@ -328,7 +332,7 @@ module SRL16E ( endmodule module SRLC32E ( - output Q, + (* abc_flop_q *) output Q, output Q31, input [4:0] A, input CE, CLK, D diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index fa87a3ad6..5de2803e9 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -119,8 +119,8 @@ struct SynthXilinxPass : public Pass log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); + log(" pmux2shiftx\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); - log(" pmux2shiftx (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/xilinx/cells_map.v\n"); @@ -288,14 +288,16 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifying variable-length shift registers, + // so attempt to convert $pmux-es to the former + // Also: wide multiplexers inference benefits from this too + Pass::call(design, "pmux2shiftx"); + if (!nosrl) { // shregmap operates on bit-level flops, not word-level, // so break those down here Pass::call(design, "simplemap t:$dff t:$dffe"); - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifiying variable-length shift registers, - // so attempt to convert $pmux-es to the former - Pass::call(design, "pmux2shiftx"); // pmux2shiftx can leave behind a $pmux with a single entry // -- need this to clean that up before shregmap Pass::call(design, "opt_expr -mux_undef"); @@ -311,9 +313,8 @@ struct SynthXilinxPass : public Pass { Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); - Pass::call(design, "read_verilog +/xilinx/cells_box.v"); if (abc == "abc9") - Pass::call(design, abc + " -lut +/xilinx/cells.lut -box +/xilinx/cells.box" + string(retime ? " -dff" : "")); + Pass::call(design, abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box" + string(retime ? " -dff" : "")); else Pass::call(design, abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); From 75b96b1afff6062c936624c8d7ac19970299cd34 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 12:36:15 -0700 Subject: [PATCH 214/514] Add synth_xilinx -nomux option --- techlibs/xilinx/cells_map.v | 2 ++ techlibs/xilinx/synth_xilinx.cc | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 3c4d8f4cd..e71d4bafb 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -142,6 +142,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule +`ifndef NO_MUXFN module \$shiftx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -219,3 +220,4 @@ module \$shiftx (A, B, Y); end endgenerate endmodule +`endif // NO_MUXFN diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 5de2803e9..04b0dabca 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -72,6 +72,9 @@ struct SynthXilinxPass : public Pass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); + log(" -nomux\n"); + log(" disable inference of wide multiplexers\n"); + log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); log(" from label is synonymous to 'begin', and empty to label is\n"); @@ -119,7 +122,7 @@ struct SynthXilinxPass : public Pass log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); - log(" pmux2shiftx\n"); + log(" pmux2shiftx (without '-nosrl' and '-nomux' only)\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); @@ -161,6 +164,7 @@ struct SynthXilinxPass : public Pass bool nobram = false; bool nodram = false; bool nosrl = false; + bool nomux = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -209,6 +213,10 @@ struct SynthXilinxPass : public Pass nosrl = true; continue; } + if (args[argidx] == "-nomux") { + nomux = true; + continue; + } if (args[argidx] == "-abc9") { abc = "abc9"; continue; @@ -291,8 +299,9 @@ struct SynthXilinxPass : public Pass // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former - // Also: wide multiplexers inference benefits from this too - Pass::call(design, "pmux2shiftx"); + // Also: wide multiplexer inference benefits from this too + if (!nosrl || !nomux) + Pass::call(design, "pmux2shiftx"); if (!nosrl) { // shregmap operates on bit-level flops, not word-level, @@ -305,7 +314,10 @@ struct SynthXilinxPass : public Pass Pass::call(design, "shregmap -tech xilinx -minlen 3"); } - Pass::call(design, "techmap -map +/xilinx/cells_map.v"); + std::string define; + if (nomux) + define += " -D NO_MUXFN"; + Pass::call(design, "techmap" + define + " -map +/xilinx/cells_map.v"); Pass::call(design, "clean"); } From ac1e13819e9241eea0e047ecf396f3f4cd822a5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 14:26:13 -0700 Subject: [PATCH 215/514] Fix for non-pow2 width muxes --- techlibs/xilinx/cells_map.v | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e71d4bafb..87a14c961 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -78,7 +78,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end else if (DEPTH > 65 && DEPTH <= 96) begin wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); if (&_TECHMAP_CONSTMSK_L_) @@ -91,7 +91,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end else if (DEPTH > 97 && DEPTH < 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); @@ -105,9 +105,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + SRLC32E #(.INIT(INIT_R[ 32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[ 64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[ 96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; @@ -157,6 +157,15 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + function integer first_B_nonzero; + integer i; + begin + for (i = B_WIDTH-1; i >= 0; i--) + if (_TECHMAP_CONSTMSK_B_[i] == 1'b0 || _TECHMAP_CONSTVAL_B_ != 1'b0) + first_B_nonzero = i; + end + endfunction + generate genvar i, j; if (B_SIGNED) begin @@ -167,12 +176,12 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else if (Y_WIDTH > 1) begin - wire [$clog2(A_WIDTH/Y_WIDTH)-1:0] B_bitty = B/Y_WIDTH; + localparam inc = first_B_nonzero(); for (i = 0; i < Y_WIDTH; i++) begin wire [A_WIDTH/Y_WIDTH-1:0] A_i; - for (j = 0; j < A_WIDTH/Y_WIDTH; j++) - assign A_i[j] = A[j*Y_WIDTH+i]; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH/Y_WIDTH), .B_WIDTH($clog2(A_WIDTH/Y_WIDTH)), .Y_WIDTH(1)) bitblast (.A(A_i), .B(B_bitty), .Y(Y[i])); + for (j = 0; j*(1< Date: Mon, 22 Apr 2019 16:56:18 -0700 Subject: [PATCH 216/514] Fix for mux_case_* mappings --- techlibs/xilinx/cells_map.v | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 87a14c961..1def7b973 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -157,32 +157,24 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; - function integer first_B_nonzero; - integer i; - begin - for (i = B_WIDTH-1; i >= 0; i--) - if (_TECHMAP_CONSTMSK_B_[i] == 1'b0 || _TECHMAP_CONSTVAL_B_ != 1'b0) - first_B_nonzero = i; - end - endfunction - generate genvar i, j; if (B_SIGNED) begin if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); else wire _TECHMAP_FAIL_ = 1; end else if (Y_WIDTH > 1) begin - localparam inc = first_B_nonzero(); - for (i = 0; i < Y_WIDTH; i++) begin - wire [A_WIDTH/Y_WIDTH-1:0] A_i; - for (j = 0; j*(1< Date: Mon, 22 Apr 2019 16:58:44 -0700 Subject: [PATCH 217/514] Add comment --- techlibs/xilinx/cells_map.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 1def7b973..38c8a49e7 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -170,6 +170,9 @@ module \$shiftx (A, B, Y); for (i = 0; i < Y_WIDTH; i++) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A({{i{1'bx}}, A[A_WIDTH-1:i]}), .B(B), .Y(Y[i])); end + // If the LSB of B is constant zero (and Y_WIDTH is 1) then + // we can optimise by removing every other entry from A + // and popping the constant zero from B else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin wire [(A_WIDTH+1)/2-1:0] A_i; for (i = 0; i < (A_WIDTH+1)/2; i++) From 1fa2c36fbd98ff8d748a70c4cb352fa1c6070dae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:14:11 -0700 Subject: [PATCH 218/514] Trim A_WIDTH by Y_WIDTH-1 --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 38c8a49e7..60bc08b48 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -168,7 +168,7 @@ module \$shiftx (A, B, Y); end else if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A({{i{1'bx}}, A[A_WIDTH-1:i]}), .B(B), .Y(Y[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); end // If the LSB of B is constant zero (and Y_WIDTH is 1) then // we can optimise by removing every other entry from A From 8f30019b68c68258979137a9d9fbbe68794781c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:41:21 -0700 Subject: [PATCH 219/514] Revert "Temporarily remove 'r' extension" This reverts commit eaf3c247729365cec776e147f380ce59f7dccd4d. --- backends/aiger/xaiger.cc | 84 ++++++++++++++++++++++++++++++++--- frontends/aiger/aigerparse.cc | 18 ++++++++ 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -174,6 +175,7 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -250,7 +252,32 @@ struct XAigerWriter // continue; //} - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -393,10 +420,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -471,6 +508,11 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -628,7 +670,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -643,10 +685,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -699,6 +741,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3fa6f5c2d..4e3f5e7c9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -360,6 +360,24 @@ void AigerReader::parse_xaiger() module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); } } + else if (c == 'r') { + uint32_t dataSize = parse_xaiger_literal(f); + uint32_t flopNum = parse_xaiger_literal(f); + f.ignore(flopNum * sizeof(uint32_t)); + log_assert(inputs.size() >= flopNum); + for (auto it = inputs.end() - flopNum; it != inputs.end(); ++it) { + log_assert((*it)->port_input); + (*it)->port_input = false; + } + inputs.erase(inputs.end() - flopNum, inputs.end()); + log_assert(outputs.size() >= flopNum); + for (auto it = outputs.end() - flopNum; it != outputs.end(); ++it) { + log_assert((*it)->port_output); + (*it)->port_output = false; + } + outputs.erase(outputs.end() - flopNum, outputs.end()); + module->fixup_ports(); + } else if (c == 'n') { parse_xaiger_literal(f); f >> s; From 5f30a8795d9a3b2c4ebaaa16ecf186e35e82a04b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:47:05 -0700 Subject: [PATCH 220/514] Tidy up --- frontends/aiger/aigerparse.cc | 2 +- passes/techmap/abc9.cc | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4e3f5e7c9..b9ab6fc09 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -361,7 +361,7 @@ void AigerReader::parse_xaiger() } } else if (c == 'r') { - uint32_t dataSize = parse_xaiger_literal(f); + /*uint32_t dataSize =*/ parse_xaiger_literal(f); uint32_t flopNum = parse_xaiger_literal(f); f.ignore(flopNum * sizeof(uint32_t)); log_assert(inputs.size() >= flopNum); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 18f860e36..67d0981f4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -561,11 +561,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri output_bits.insert({wire, i}); } else { - //if (w->name == "\\__dummy_o__") { - // log("Don't call ABC as there is nothing to map.\n"); - // goto cleanup; - //} - // Attempt another wideports_split here because there // exists the possibility that different bits of a port // could be an input and output, therefore parse_xiager() @@ -935,7 +930,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // log("Don't call ABC as there is nothing to map.\n"); //} -cleanup: if (cleanup) { log("Removing temp directory.\n"); From 26e461f47da12b79e5b6682f692d81e2721ca0c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:58:28 -0700 Subject: [PATCH 221/514] Fix for A_WIDTH == 2 but B_WIDTH==3 --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 60bc08b48..10dbb8b9a 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -179,7 +179,7 @@ module \$shiftx (A, B, Y); assign A_i[i] = A[i*2]; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end - else if (B_WIDTH < 3) begin + else if (B_WIDTH < 3 || A_WIDTH == 2**2) begin wire _TECHMAP_FAIL_ = 1; end else if (B_WIDTH == 3) begin From 60026842b20e04affe60a7871fd14bb544add37b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:59:56 -0700 Subject: [PATCH 222/514] Tweak --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 10dbb8b9a..4275c03e6 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -179,7 +179,7 @@ module \$shiftx (A, B, Y); assign A_i[i] = A[i*2]; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end - else if (B_WIDTH < 3 || A_WIDTH == 2**2) begin + else if (B_WIDTH < 3 || A_WIDTH <= 4) begin wire _TECHMAP_FAIL_ = 1; end else if (B_WIDTH == 3) begin From 91c3afcab723d85d3c6931561cb13ad7b70e7e5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 13:42:06 -0700 Subject: [PATCH 223/514] Use nonblocking --- techlibs/ice40/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 40e54f9f0..40972766d 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -149,7 +149,7 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) in always @(posedge C) Q <= D; `else - always @* Q = D; + always @* Q <= D; `endif endmodule From d9c915042a610672e313f976cdbcbf9a814c380d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 13:42:35 -0700 Subject: [PATCH 224/514] Move clean from aigerparse to abc9 --- frontends/aiger/aigerparse.cc | 2 -- passes/techmap/abc9.cc | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b9ab6fc09..904a1079d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -598,8 +598,6 @@ next_line: module->fixup_ports(); design->add(module); - Pass::call(design, "clean"); - for (auto cell : module->cells().to_vector()) { if (cell->type != "$lut") continue; auto y_port = cell->getPort("\\Y").as_bit(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 67d0981f4..2aa19b348 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -548,6 +548,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; if (mapped_mod == NULL) log_error("ABC output file does not contain a module `netlist'.\n"); + Pass::call(mapped_design, "clean"); pool output_bits; for (auto &it : mapped_mod->wires_) { From 9d122d3c51575fe6803729e8f953141edb3b12c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 15:06:19 -0700 Subject: [PATCH 225/514] Refactor into AigerReader::post_process() --- frontends/aiger/aigerparse.cc | 409 +++++++++++++--------------------- frontends/aiger/aigerparse.h | 1 + 2 files changed, 161 insertions(+), 249 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3fa6f5c2d..8b3fa6536 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -113,103 +113,7 @@ void AigerReader::parse_aiger() std::getline(f, line); // Ignore up to start of next line } - dict wideports_cache; - - if (!map_filename.empty()) { - std::ifstream mf(map_filename); - std::string type, symbol; - int variable, index; - while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_symbol = RTLIL::escape_id(symbol); - if (type == "input") { - log_assert(static_cast(variable) < inputs.size()); - RTLIL::Wire* wire = inputs[variable]; - log_assert(wire); - log_assert(wire->port_input); - - if (index == 0) - module->rename(wire, RTLIL::escape_id(symbol)); - else if (index > 0) { - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); - } - } - else if (type == "output") { - log_assert(static_cast(variable) < outputs.size()); - RTLIL::Wire* wire = outputs[variable]; - log_assert(wire); - // Ignore direct output -> input connections - if (!wire->port_output) - continue; - log_assert(wire->port_output); - - if (index == 0) - module->rename(wire, RTLIL::escape_id(symbol)); - else if (index > 0) { - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", symbol.c_str(), index))); - if (wideports) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); - } - } - else - log_error("Symbol type '%s' not recognised.\n", type.c_str()); - } - } - - for (auto &wp : wideports_cache) { - auto name = wp.first; - int width = wp.second + 1; - - RTLIL::Wire *wire = module->wire(name); - if (wire) - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); - - // Do not make ports with a mix of input/output into - // wide ports - bool port_input = false, port_output = false; - for (int i = 0; i < width; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); - RTLIL::Wire *other_wire = module->wire(other_name); - if (other_wire) { - port_input = port_input || other_wire->port_input; - port_output = port_output || other_wire->port_output; - } - } - if ((port_input && port_output) || (!port_input && !port_output)) - continue; - - wire = module->addWire(name, width); - wire->port_input = port_input; - wire->port_output = port_output; - - for (int i = 0; i < width; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); - RTLIL::Wire *other_wire = module->wire(other_name); - if (other_wire) { - other_wire->port_input = false; - other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i)); - else - module->connect(SigSpec(wire, i), other_wire); - } - } - } - - module->fixup_ports(); - design->add(module); - - Pass::call(design, "clean"); - - for (auto cell : module->cells().to_vector()) { - if (cell->type != "$lut") continue; - auto y_port = cell->getPort("\\Y").as_bit(); - if (y_port.wire->width == 1) - module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); - else - module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); - } + post_process(); } static uint32_t parse_xaiger_literal(std::istream &f) @@ -438,158 +342,7 @@ next_line: module->connect(wire, out_wire); } - if (!map_filename.empty()) { - std::ifstream mf(map_filename); - std::string type, symbol; - int variable, index; - while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); - if (type == "input") { - log_assert(static_cast(variable) < inputs.size()); - RTLIL::Wire* wire = inputs[variable]; - log_assert(wire); - log_assert(wire->port_input); - - if (index == 0) { - // Cope with the fact that a CI might be identical - // to a PI (necessary due to ABC); in those cases - // simply connect the latter to the former - RTLIL::Wire* existing = module->wire(escaped_s); - if (!existing) - module->rename(wire, escaped_s); - else { - wire->port_input = false; - module->connect(wire, existing); - } - } - else if (index > 0) { - std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); - RTLIL::Wire* existing = module->wire(indexed_name); - if (!existing) { - module->rename(wire, indexed_name); - if (wideports) - wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); - } - else { - module->connect(wire, existing); - wire->port_input = false; - } - } - } - else if (type == "output") { - log_assert(static_cast(variable) < outputs.size()); - RTLIL::Wire* wire = outputs[variable]; - log_assert(wire); - log_assert(wire->port_output); - if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { - wire->port_output = false; - continue; - } - - if (index == 0) { - // Cope with the fact that a CO might be identical - // to a PO (necessary due to ABC); in those cases - // simply connect the latter to the former - RTLIL::Wire* existing = module->wire(escaped_s); - if (!existing) { - if (escaped_s.ends_with("$inout.out")) { - wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10)); - log_assert(in_wire); - log_assert(in_wire->port_input && !in_wire->port_output); - in_wire->port_output = true; - module->connect(in_wire, wire); - } - else - module->rename(wire, escaped_s); - } - else { - wire->port_output = false; - module->connect(wire, existing); - } - } - else if (index > 0) { - std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); - RTLIL::Wire* existing = module->wire(indexed_name); - if (!existing) { - if (escaped_s.ends_with("$inout.out")) { - wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index)); - log_assert(in_wire); - log_assert(in_wire->port_input && !in_wire->port_output); - in_wire->port_output = true; - module->connect(in_wire, wire); - } - else { - module->rename(wire, indexed_name); - if (wideports) - wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); - } - } - else { - module->connect(wire, existing); - wire->port_output = false; - } - } - } - else - log_error("Symbol type '%s' not recognised.\n", type.c_str()); - } - } - - for (auto &wp : wideports_cache) { - auto name = wp.first; - int width = wp.second + 1; - - RTLIL::Wire *wire = module->wire(name); - if (wire) - module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); - - // Do not make ports with a mix of input/output into - // wide ports - bool port_input = false, port_output = false; - for (int i = 0; i < width; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); - RTLIL::Wire *other_wire = module->wire(other_name); - if (other_wire) { - port_input = port_input || other_wire->port_input; - port_output = port_output || other_wire->port_output; - } - } - if ((port_input && port_output) || (!port_input && !port_output)) - continue; - - wire = module->addWire(name, width); - wire->port_input = port_input; - wire->port_output = port_output; - - for (int i = 0; i < width; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); - RTLIL::Wire *other_wire = module->wire(other_name); - if (other_wire) { - other_wire->port_input = false; - other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i)); - else - module->connect(SigSpec(wire, i), other_wire); - } - } - } - - module->fixup_ports(); - design->add(module); - - Pass::call(design, "clean"); - - for (auto cell : module->cells().to_vector()) { - if (cell->type != "$lut") continue; - auto y_port = cell->getPort("\\Y").as_bit(); - if (y_port.wire->width == 1) - module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); - else - module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); - } + post_process(); } void AigerReader::parse_aiger_ascii() @@ -849,6 +602,164 @@ void AigerReader::parse_aiger_binary() } } +void AigerReader::post_process() +{ + dict wideports_cache; + + if (!map_filename.empty()) { + std::ifstream mf(map_filename); + std::string type, symbol; + int variable, index; + while (mf >> type >> variable >> index >> symbol) { + RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); + if (type == "input") { + log_assert(static_cast(variable) < inputs.size()); + RTLIL::Wire* wire = inputs[variable]; + log_assert(wire); + log_assert(wire->port_input); + + if (index == 0) { + // Cope with the fact that a CI might be identical + // to a PI (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_s); + if (!existing) + module->rename(wire, escaped_s); + else { + wire->port_input = false; + module->connect(wire, existing); + } + } + else if (index > 0) { + std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } + else { + module->connect(wire, existing); + wire->port_input = false; + } + } + } + else if (type == "output") { + log_assert(static_cast(variable) < outputs.size()); + RTLIL::Wire* wire = outputs[variable]; + log_assert(wire); + log_assert(wire->port_output); + if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { + wire->port_output = false; + continue; + } + + if (index == 0) { + // Cope with the fact that a CO might be identical + // to a PO (necessary due to ABC); in those cases + // simply connect the latter to the former + RTLIL::Wire* existing = module->wire(escaped_s); + if (!existing) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else + module->rename(wire, escaped_s); + } + else { + wire->port_output = false; + module->connect(wire, existing); + } + } + else if (index > 0) { + std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index); + RTLIL::Wire* existing = module->wire(indexed_name); + if (!existing) { + if (escaped_s.ends_with("$inout.out")) { + wire->port_output = false; + RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index)); + log_assert(in_wire); + log_assert(in_wire->port_input && !in_wire->port_output); + in_wire->port_output = true; + module->connect(in_wire, wire); + } + else { + module->rename(wire, indexed_name); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); + } + } + else { + module->connect(wire, existing); + wire->port_output = false; + } + } + } + else + log_error("Symbol type '%s' not recognised.\n", type.c_str()); + } + } + + for (auto &wp : wideports_cache) { + auto name = wp.first; + int width = wp.second + 1; + + RTLIL::Wire *wire = module->wire(name); + if (wire) + module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0))); + + // Do not make ports with a mix of input/output into + // wide ports + bool port_input = false, port_output = false; + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + port_input = port_input || other_wire->port_input; + port_output = port_output || other_wire->port_output; + } + } + if ((port_input && port_output) || (!port_input && !port_output)) + continue; + + wire = module->addWire(name, width); + wire->port_input = port_input; + wire->port_output = port_output; + + for (int i = 0; i < width; i++) { + RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + RTLIL::Wire *other_wire = module->wire(other_name); + if (other_wire) { + other_wire->port_input = false; + other_wire->port_output = false; + if (wire->port_input) + module->connect(other_wire, SigSpec(wire, i)); + else + module->connect(SigSpec(wire, i), other_wire); + } + } + } + + module->fixup_ports(); + design->add(module); + + Pass::call(design, "clean"); + + for (auto cell : module->cells().to_vector()) { + if (cell->type != "$lut") continue; + auto y_port = cell->getPort("\\Y").as_bit(); + if (y_port.wire->width == 1) + module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str())); + else + module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset)); + } +} + struct AigerFrontend : public Frontend { AigerFrontend() : Frontend("aiger", "read AIGER file") { } void help() YS_OVERRIDE diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 39757545f..8c9f3a0c9 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -47,6 +47,7 @@ struct AigerReader void parse_xaiger(); void parse_aiger_ascii(); void parse_aiger_binary(); + void post_process(); }; YOSYS_NAMESPACE_END From bfd71e09906096c72039beebb1b3b6a79dd6b36c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: [PATCH 226/514] Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ tests/simple_abc9/abc9.v | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..504a66086 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -133,6 +133,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -151,8 +153,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -338,10 +342,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -354,7 +360,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -750,7 +758,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index eca340693..f37d975ff 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -104,3 +104,41 @@ always @(io or oe) assign io[3:0] = oe ? ~latch[3:0] : 4'bz; assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; endmodule + +module abc9_test015(input a, output b, input c); +assign b = ~a; +(* keep *) wire d; +assign d = ~c; +endmodule + +module abc9_test016(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c <= ~a; +endmodule + +module abc9_test017(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c = b; +endmodule + +module abc9_test018(input a, output b, output c); +assign b = ~a; +(* keep *) wire [1:0] d; +assign c = &d; +endmodule + +module abc9_test019(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +reg d; +always @* d <= &c; +endmodule + +module abc9_test020(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +(* keep *) reg d; +always @* d <= &c; +endmodule From ac2aff9e28a087a9a2697cd6ccf754af738903a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: [PATCH 227/514] Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ tests/simple_abc9/abc9.v | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..7126002f6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -134,6 +134,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -152,8 +154,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -365,10 +369,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -381,7 +387,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -820,7 +828,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index eca340693..f37d975ff 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -104,3 +104,41 @@ always @(io or oe) assign io[3:0] = oe ? ~latch[3:0] : 4'bz; assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz; endmodule + +module abc9_test015(input a, output b, input c); +assign b = ~a; +(* keep *) wire d; +assign d = ~c; +endmodule + +module abc9_test016(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c <= ~a; +endmodule + +module abc9_test017(input a, output b); +assign b = ~a; +(* keep *) reg c; +always @* c = b; +endmodule + +module abc9_test018(input a, output b, output c); +assign b = ~a; +(* keep *) wire [1:0] d; +assign c = &d; +endmodule + +module abc9_test019(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +reg d; +always @* d <= &c; +endmodule + +module abc9_test020(input a, output b); +assign b = ~a; +(* keep *) reg [1:0] c; +(* keep *) reg d; +always @* d <= &c; +endmodule From f96d82a5f1982ea86cf02182b33abe91c015b10d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 24 Apr 2019 16:46:41 -0700 Subject: [PATCH 228/514] Add -nocarry option to synth_xilinx --- techlibs/xilinx/synth_xilinx.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 04b0dabca..9e4a86a84 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -63,6 +63,9 @@ struct SynthXilinxPass : public Pass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); + log(" -nocarry\n"); + log(" disable inference of carry chains\n"); + log("\n"); log(" -nobram\n"); log(" disable inference of block rams\n"); log("\n"); @@ -118,7 +121,7 @@ struct SynthXilinxPass : public Pass log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); - log(" techmap -map +/xilinx/arith_map.v\n"); + log(" techmap -map +/xilinx/arith_map.v (without '-nocarry' only)\n"); log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); @@ -161,6 +164,7 @@ struct SynthXilinxPass : public Pass bool flatten = false; bool retime = false; bool vpr = false; + bool nocarry = false; bool nobram = false; bool nodram = false; bool nosrl = false; @@ -201,6 +205,10 @@ struct SynthXilinxPass : public Pass vpr = true; continue; } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } if (args[argidx] == "-nobram") { nobram = true; continue; @@ -284,10 +292,11 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - if (vpr) { - Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - } else { - Pass::call(design, "techmap -map +/xilinx/arith_map.v"); + if (!nocarry) { + if (vpr) + Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + else + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); } Pass::call(design, "hierarchy -check"); From eec314e2621d3d055d7810f4b7e573a99e0239b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 24 Apr 2019 21:06:53 -0700 Subject: [PATCH 229/514] Remove topo sort no-loop assertion, with test --- backends/aiger/xaiger.cc | 13 ------- tests/simple_abc9/abc.box | 2 + tests/simple_abc9/abc9.v | 73 +++++++++++++++++++++++++++++++++++ tests/simple_abc9/run-test.sh | 2 +- 4 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 tests/simple_abc9/abc.box diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 504a66086..f9d874e2d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -294,20 +294,7 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); -#ifndef NDEBUG - toposort.analyze_loops = true; -#endif toposort.sort(); -#ifndef NDEBUG - for (auto &it : toposort.loops) { - log(" loop"); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); - } -#endif - log_assert(!toposort.found_loops); - for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); diff --git a/tests/simple_abc9/abc.box b/tests/simple_abc9/abc.box new file mode 100644 index 000000000..a8801d807 --- /dev/null +++ b/tests/simple_abc9/abc.box @@ -0,0 +1,2 @@ +MUXF8 1 0 3 1 +1 1 1 diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index f37d975ff..fb5b759fb 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -142,3 +142,76 @@ assign b = ~a; (* keep *) reg d; always @* d <= &c; endmodule + +module abc9_test021(clk, rst, s_eth_hdr_valid, s_eth_hdr_ready, s_eth_dest_mac, s_eth_src_mac, s_eth_type, s_eth_payload_axis_tdata, s_eth_payload_axis_tkeep, s_eth_payload_axis_tvalid, s_eth_payload_axis_tready, s_eth_payload_axis_tlast, s_eth_payload_axis_tid, s_eth_payload_axis_tdest, s_eth_payload_axis_tuser, m_eth_hdr_valid, m_eth_hdr_ready, m_eth_dest_mac, m_eth_src_mac, m_eth_type, m_eth_payload_axis_tdata, m_eth_payload_axis_tkeep, m_eth_payload_axis_tvalid, m_eth_payload_axis_tready, m_eth_payload_axis_tlast, m_eth_payload_axis_tid, m_eth_payload_axis_tdest, m_eth_payload_axis_tuser); + input clk; + output [47:0] m_eth_dest_mac; + input m_eth_hdr_ready; + output m_eth_hdr_valid; + output [7:0] m_eth_payload_axis_tdata; + output [7:0] m_eth_payload_axis_tdest; + output [7:0] m_eth_payload_axis_tid; + output m_eth_payload_axis_tkeep; + output m_eth_payload_axis_tlast; + input m_eth_payload_axis_tready; + output m_eth_payload_axis_tuser; + output m_eth_payload_axis_tvalid; + output [47:0] m_eth_src_mac; + output [15:0] m_eth_type; + input rst; + input [191:0] s_eth_dest_mac; + output [3:0] s_eth_hdr_ready; + input [3:0] s_eth_hdr_valid; + input [31:0] s_eth_payload_axis_tdata; + input [31:0] s_eth_payload_axis_tdest; + input [31:0] s_eth_payload_axis_tid; + input [3:0] s_eth_payload_axis_tkeep; + input [3:0] s_eth_payload_axis_tlast; + output [3:0] s_eth_payload_axis_tready; + input [3:0] s_eth_payload_axis_tuser; + input [3:0] s_eth_payload_axis_tvalid; + input [191:0] s_eth_src_mac; + input [63:0] s_eth_type; + (* keep *) + wire [0:0] grant, request; + wire a; + not u0 ( + a, + grant[0] + ); + and u1 ( + request[0], + s_eth_hdr_valid[0], + a + ); + (* keep *) + MUXF8 u2 ( + .I0(1'bx), + .I1(1'bx), + .O(o), + .S(1'bx) + ); + arbiter arb_inst ( + .acknowledge(acknowledge), + .clk(clk), + .grant(grant), + .grant_encoded(grant_encoded), + .grant_valid(grant_valid), + .request(request), + .rst(rst) + ); +endmodule + +module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encoded); + input [3:0] acknowledge; + input clk; + output [3:0] grant; + output [1:0] grant_encoded; + output grant_valid; + input [3:0] request; + input rst; +endmodule + +(* abc_box_id=1 *) +module MUXF8(input I0, I1, S, output O); +endmodule diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 97f284378..4935d41ad 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -19,4 +19,4 @@ fi cp ../simple/*.v . DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; opt -full; techmap; abc9 -lut 4 -box ../abc.box; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" From feff9764540cbf1152459cb377fc68d8e10c7153 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 17:11:18 -0700 Subject: [PATCH 230/514] synth_xilinx to call bitblast_shiftx --- techlibs/xilinx/synth_xilinx.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 9e4a86a84..d787687aa 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -126,6 +126,7 @@ struct SynthXilinxPass : public Pass log("\n"); log(" map_cells:\n"); log(" pmux2shiftx (without '-nosrl' and '-nomux' only)\n"); + log(" bitblast_shiftx (without '-nosrl' and '-nomux' only)\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); @@ -309,8 +310,10 @@ struct SynthXilinxPass : public Pass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!nosrl || !nomux) + if (!nosrl || !nomux) { Pass::call(design, "pmux2shiftx"); + Pass::call(design, "bitblast_shiftx"); + } if (!nosrl) { // shregmap operates on bit-level flops, not word-level, From 8d00b9ef7e3455a84c45441287d9a884c922ee20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 17:23:46 -0700 Subject: [PATCH 231/514] Make pmgen support files more generic --- passes/pmgen/.gitignore | 2 +- passes/pmgen/Makefile.inc | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index c9263057e..52dfd93f3 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1 +1 @@ -/ice40_dsp_pm.h +*_pm.h diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index e0609d9ba..5669bd3d1 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,8 +1,11 @@ -OBJS += passes/pmgen/ice40_dsp.o +PMG_SRC = $(wildcard passes/pmgen/*.pmg) +PMG_OBJS += $(patsubst %.pmg, %.o, $(PMG_SRC)) +OBJS += $(PMG_OBJS) -passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h -EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h -.SECONDARY: passes/pmgen/ice40_dsp_pm.h +$(PMG_OBJS): %.o: %_pm.h -passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg +EXTRA_OBJS += $(patsubst %.pmg, %_pm.h, $(PMG_SRC)) +.SECONDARY: $(EXTRA_OBJS) + +%_pm.h: passes/pmgen/pmgen.py %.pmg $(P) mkdir -p passes/pmgen && python3 $^ $@ From ccd0729456e1ec105c43007a8392777893ac7d99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 17:23:59 -0700 Subject: [PATCH 232/514] Add split_shiftx command --- passes/pmgen/split_shiftx.cc | 78 +++++++++++++++++++++++++++++++++++ passes/pmgen/split_shiftx.pmg | 56 +++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 passes/pmgen/split_shiftx.cc create mode 100644 passes/pmgen/split_shiftx.pmg diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc new file mode 100644 index 000000000..71fb4e9ef --- /dev/null +++ b/passes/pmgen/split_shiftx.cc @@ -0,0 +1,78 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include "passes/pmgen/split_shiftx_pm.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void create_split_shiftx(split_shiftx_pm &pm) +{ + if (pm.st.shiftxB.empty()) + return; + log_assert(pm.st.shiftx); + SigSpec A = pm.st.shiftx->getPort("\\A"); + SigSpec Y = pm.st.shiftx->getPort("\\Y"); + const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int(); + const int Y_WIDTH = pm.st.shiftx->getParam("\\Y_WIDTH").as_int(); + log_assert(Y_WIDTH > 1); + std::vector bits; + bits.resize(A_WIDTH / Y_WIDTH); + for (int i = 0; i < Y_WIDTH; ++i) { + for (int j = 0; j < A_WIDTH/Y_WIDTH; ++j) + bits[j] = A[j*Y_WIDTH + i]; + pm.module->addShiftx(NEW_ID, bits, pm.st.shiftxB, Y[i]); + } + pm.st.shiftx->unsetPort("\\Y"); + + pm.autoremove(pm.st.shiftx); + pm.autoremove(pm.st.macc); +} + +struct BitblastShiftxPass : public Pass { + BitblastShiftxPass() : Pass("split_shiftx", "Split up multi-bit $shiftx cells") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" split_shiftx [selection]\n"); + log("\n"); + log("Split up $shiftx cells where Y_WIDTH > 1, with consideration for any $macc\n"); + log("cells that may be driving their B inputs.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing SPLIT_SHIFTX pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + split_shiftx_pm(module, module->selected_cells()).run(create_split_shiftx); + } +} BitblastShiftxPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/split_shiftx.pmg b/passes/pmgen/split_shiftx.pmg new file mode 100644 index 000000000..11b19bfe4 --- /dev/null +++ b/passes/pmgen/split_shiftx.pmg @@ -0,0 +1,56 @@ +state shiftxB + +match shiftx + select shiftx->type == $shiftx + select param(shiftx, \Y_WIDTH).as_int() > 1 +endmatch + +code shiftxB + shiftxB = port(shiftx, \B); + const int b_width = param(shiftx, \B_WIDTH).as_int(); + if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0) + shiftxB = shiftxB.extract(0, b_width-1); +endcode + +match macc + select macc->type == $macc + select param(macc, \B_WIDTH).as_int() == 0 + index port(macc, \Y) === shiftxB + optional +endmatch + +code shiftxB + if (macc) { + Const config = param(macc, \CONFIG); + const int config_width = param(macc, \CONFIG_WIDTH).as_int(); + const int num_bits = config.extract(0, 4).as_int(); + const int num_ports = (config_width - 4) / (2 + 2*num_bits); + if (num_ports != 1) { + shiftxB = nullptr; + reject; + } + // IS_SIGNED? + if (config[4] == 1) { + shiftxB = nullptr; + reject; + } + // DO_SUBTRACT? + if (config[5] == 1) { + shiftxB = nullptr; + reject; + } + const int port_size_A = config.extract(6, num_bits).as_int(); + const int port_size_B = config.extract(6 + num_bits, num_bits).as_int(); + const SigSpec port_B = port(macc, \A).extract(port_size_A, port_size_B); + if (!port_B.is_fully_const()) { + shiftxB = nullptr; + reject; + } + const int multiply_factor = port_B.as_int(); + if (multiply_factor != param(shiftx, \Y_WIDTH).as_int()) { + shiftxB = nullptr; + reject; + } + shiftxB = port(macc, \A).extract(0, port_size_A); + } +endcode From af3c374a3589994c41ebd5fcfc75f292dbd7e602 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 17:35:39 -0700 Subject: [PATCH 233/514] Elaborate on help message --- passes/pmgen/split_shiftx.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc index 71fb4e9ef..6eee88886 100644 --- a/passes/pmgen/split_shiftx.cc +++ b/passes/pmgen/split_shiftx.cc @@ -56,7 +56,8 @@ struct BitblastShiftxPass : public Pass { log(" split_shiftx [selection]\n"); log("\n"); log("Split up $shiftx cells where Y_WIDTH > 1, with consideration for any $macc\n"); - log("cells that may be driving their B inputs.\n"); + log("cells -- configured as a constant multiplier equal to Y_WIDTH -- that may be\n"); + log("driving their B inputs.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From 0eb7150a5706e81ff36a6a57d8c0c6a2fda05e07 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 18:08:05 -0700 Subject: [PATCH 234/514] Add test --- tests/various/split_shiftx.v | 118 ++++++++++++++++++++++++++++++++++ tests/various/split_shiftx.ys | 21 ++++++ 2 files changed, 139 insertions(+) create mode 100644 tests/various/split_shiftx.v create mode 100644 tests/various/split_shiftx.ys diff --git a/tests/various/split_shiftx.v b/tests/various/split_shiftx.v new file mode 100644 index 000000000..dfcea3880 --- /dev/null +++ b/tests/various/split_shiftx.v @@ -0,0 +1,118 @@ +module split_shiftx_test01(i, s, o); + wire [3:0] _0_; + input [8:0] i; + output [2:0] o; + input [1:0] s; + \$macc #( + .A_WIDTH(32'd4), + .B_WIDTH(32'd0), + .CONFIG(10'h282), + .CONFIG_WIDTH(32'd10), + .Y_WIDTH(32'd4) + ) _1_ ( + .A({ 2'h3, s }), + .B(), + .Y(_0_) + ); + \$shiftx #( + .A_SIGNED(32'd0), + .A_WIDTH(32'd9), + .B_SIGNED(32'd1), + .B_WIDTH(32'd5), + .Y_WIDTH(32'd3) + ) _2_ ( + .A(i), + .B({ 1'h0, _0_ }), + .Y(o) + ); +endmodule + +// Sign bit is 1 +module split_shiftx_test02(i, s, o); + wire [3:0] _0_; + input [8:0] i; + output [2:0] o; + input [1:0] s; + \$macc #( + .A_WIDTH(32'd4), + .B_WIDTH(32'd0), + .CONFIG(10'h282), + .CONFIG_WIDTH(32'd10), + .Y_WIDTH(32'd4) + ) _1_ ( + .A({ 2'h3, s }), + .B(), + .Y(_0_) + ); + \$shiftx #( + .A_SIGNED(32'd0), + .A_WIDTH(32'd9), + .B_SIGNED(32'd1), + .B_WIDTH(32'd5), + .Y_WIDTH(32'd3) + ) _2_ ( + .A(i), + .B({ 1'h1, _0_ }), + .Y(o) + ); +endmodule + +// Non constant $macc +module split_shiftx_test03(i, s, o); + wire [3:0] _0_; + input [8:0] i; + output [2:0] o; + input [1:0] s; + \$macc #( + .A_WIDTH(32'd4), + .B_WIDTH(32'd0), + .CONFIG(10'h282), + .CONFIG_WIDTH(32'd10), + .Y_WIDTH(32'd4) + ) _1_ ( + .A({ s, s }), + .B(), + .Y(_0_) + ); + \$shiftx #( + .A_SIGNED(32'd0), + .A_WIDTH(32'd9), + .B_SIGNED(32'd1), + .B_WIDTH(32'd5), + .Y_WIDTH(32'd3) + ) _2_ ( + .A(i), + .B({ 1'h0, _0_ }), + .Y(o) + ); +endmodule + +// Wrong constant $macc +module split_shiftx_test04(i, s, o); + wire [3:0] _0_; + input [8:0] i; + output [2:0] o; + input [1:0] s; + \$macc #( + .A_WIDTH(32'd4), + .B_WIDTH(32'd0), + .CONFIG(10'h282), + .CONFIG_WIDTH(32'd10), + .Y_WIDTH(32'd4) + ) _1_ ( + .A({ 2'h2, s }), + .B(), + .Y(_0_) + ); + \$shiftx #( + .A_SIGNED(32'd0), + .A_WIDTH(32'd9), + .B_SIGNED(32'd1), + .B_WIDTH(32'd5), + .Y_WIDTH(32'd3) + ) _2_ ( + .A(i), + .B({ 1'h0, _0_ }), + .Y(o) + ); +endmodule diff --git a/tests/various/split_shiftx.ys b/tests/various/split_shiftx.ys new file mode 100644 index 000000000..810348aa3 --- /dev/null +++ b/tests/various/split_shiftx.ys @@ -0,0 +1,21 @@ +read_verilog -icells split_shiftx.v +split_shiftx + +cd split_shiftx_test01 +select -assert-count 3 t:$shiftx +select -assert-count 0 t: t:$shiftx %n %i + +cd split_shiftx_test02 +select -assert-count 1 t:$shiftx +select -assert-count 1 t:$macc +select -assert-count 0 t: t:$shiftx t:$macc %u %n %i + +cd split_shiftx_test03 +select -assert-count 1 t:$shiftx +select -assert-count 1 t:$macc +select -assert-count 0 t: t:$shiftx t:$macc %u %n %i + +cd split_shiftx_test04 +select -assert-count 1 t:$shiftx +select -assert-count 1 t:$macc +select -assert-count 0 t: t:$shiftx t:$macc %u %n %i From ece2c49e929cb6f6ac70cccdd84efc2bb1550a39 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 18:39:13 -0700 Subject: [PATCH 235/514] In order to indicate a failed pattern, blacklist? --- passes/pmgen/split_shiftx.cc | 4 ++-- passes/pmgen/split_shiftx.pmg | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc index 6eee88886..672478959 100644 --- a/passes/pmgen/split_shiftx.cc +++ b/passes/pmgen/split_shiftx.cc @@ -26,9 +26,9 @@ PRIVATE_NAMESPACE_BEGIN void create_split_shiftx(split_shiftx_pm &pm) { - if (pm.st.shiftxB.empty()) - return; log_assert(pm.st.shiftx); + if (pm.blacklist_cells.count(pm.st.shiftx)) + return; SigSpec A = pm.st.shiftx->getPort("\\A"); SigSpec Y = pm.st.shiftx->getPort("\\Y"); const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int(); diff --git a/passes/pmgen/split_shiftx.pmg b/passes/pmgen/split_shiftx.pmg index 11b19bfe4..c9e0ff995 100644 --- a/passes/pmgen/split_shiftx.pmg +++ b/passes/pmgen/split_shiftx.pmg @@ -5,50 +5,51 @@ match shiftx select param(shiftx, \Y_WIDTH).as_int() > 1 endmatch -code shiftxB - shiftxB = port(shiftx, \B); - const int b_width = param(shiftx, \B_WIDTH).as_int(); - if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0) - shiftxB = shiftxB.extract(0, b_width-1); -endcode - match macc select macc->type == $macc select param(macc, \B_WIDTH).as_int() == 0 - index port(macc, \Y) === shiftxB optional endmatch code shiftxB if (macc) { + shiftxB = port(shiftx, \B); + const int b_width = param(shiftx, \B_WIDTH).as_int(); + if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0) + shiftxB = shiftxB.extract(0, b_width-1); + if (port(macc, \Y) != shiftxB) { + blacklist(shiftx); + reject; + } + Const config = param(macc, \CONFIG); const int config_width = param(macc, \CONFIG_WIDTH).as_int(); const int num_bits = config.extract(0, 4).as_int(); const int num_ports = (config_width - 4) / (2 + 2*num_bits); if (num_ports != 1) { - shiftxB = nullptr; + blacklist(shiftx); reject; } // IS_SIGNED? if (config[4] == 1) { - shiftxB = nullptr; + blacklist(shiftx); reject; } // DO_SUBTRACT? if (config[5] == 1) { - shiftxB = nullptr; + blacklist(shiftx); reject; } const int port_size_A = config.extract(6, num_bits).as_int(); const int port_size_B = config.extract(6 + num_bits, num_bits).as_int(); const SigSpec port_B = port(macc, \A).extract(port_size_A, port_size_B); if (!port_B.is_fully_const()) { - shiftxB = nullptr; + blacklist(shiftx); reject; } const int multiply_factor = port_B.as_int(); if (multiply_factor != param(shiftx, \Y_WIDTH).as_int()) { - shiftxB = nullptr; + blacklist(shiftx); reject; } shiftxB = port(macc, \A).extract(0, port_size_A); From fb4348f8409f038656c4ece79a43485baf34dd7f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 19:38:19 -0700 Subject: [PATCH 236/514] Fix for when B_WIDTH has trailing zeroes --- passes/pmgen/split_shiftx.cc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc index 672478959..2af0ebecf 100644 --- a/passes/pmgen/split_shiftx.cc +++ b/passes/pmgen/split_shiftx.cc @@ -30,16 +30,20 @@ void create_split_shiftx(split_shiftx_pm &pm) if (pm.blacklist_cells.count(pm.st.shiftx)) return; SigSpec A = pm.st.shiftx->getPort("\\A"); + SigSpec B = pm.st.shiftx->getPort("\\B"); SigSpec Y = pm.st.shiftx->getPort("\\Y"); const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int(); + const int B_WIDTH = pm.st.shiftx->getParam("\\B_WIDTH").as_int(); const int Y_WIDTH = pm.st.shiftx->getParam("\\Y_WIDTH").as_int(); - log_assert(Y_WIDTH > 1); + int trailing_zeroes = 0; + for (; B[trailing_zeroes] == RTLIL::S0; ++trailing_zeroes) ; + const int WIDTH = trailing_zeroes > 0 ? 1 << trailing_zeroes : Y_WIDTH; std::vector bits; - bits.resize(A_WIDTH / Y_WIDTH); + bits.resize(A_WIDTH / WIDTH); for (int i = 0; i < Y_WIDTH; ++i) { - for (int j = 0; j < A_WIDTH/Y_WIDTH; ++j) - bits[j] = A[j*Y_WIDTH + i]; - pm.module->addShiftx(NEW_ID, bits, pm.st.shiftxB, Y[i]); + for (int j = 0; j < A_WIDTH/WIDTH; ++j) + bits[j] = A[j*WIDTH + i]; + pm.module->addShiftx(NEW_ID, bits, B.extract(trailing_zeroes, B_WIDTH-trailing_zeroes), Y[i]); } pm.st.shiftx->unsetPort("\\Y"); From 019c48b5083f065d3485b5c9e5c8d4b4554f3af3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 19:38:35 -0700 Subject: [PATCH 237/514] bitblast_shiftx -> split_shiftx --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index d787687aa..f65ae87f5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -126,7 +126,7 @@ struct SynthXilinxPass : public Pass log("\n"); log(" map_cells:\n"); log(" pmux2shiftx (without '-nosrl' and '-nomux' only)\n"); - log(" bitblast_shiftx (without '-nosrl' and '-nomux' only)\n"); + log(" split_shiftx (without '-nosrl' and '-nomux' only)\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); @@ -312,7 +312,7 @@ struct SynthXilinxPass : public Pass // Also: wide multiplexer inference benefits from this too if (!nosrl || !nomux) { Pass::call(design, "pmux2shiftx"); - Pass::call(design, "bitblast_shiftx"); + Pass::call(design, "split_shiftx"); } if (!nosrl) { From f14d7f0df65c6892b911c74e1674a94ad3e556db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 19:43:41 -0700 Subject: [PATCH 238/514] Cleanup superseded --- techlibs/xilinx/cells_map.v | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 4275c03e6..c814f3a96 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -167,17 +167,7 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else if (Y_WIDTH > 1) begin - for (i = 0; i < Y_WIDTH; i++) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); - end - // If the LSB of B is constant zero (and Y_WIDTH is 1) then - // we can optimise by removing every other entry from A - // and popping the constant zero from B - else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin - wire [(A_WIDTH+1)/2-1:0] A_i; - for (i = 0; i < (A_WIDTH+1)/2; i++) - assign A_i[i] = A[i*2]; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + wire _TECHMAP_FAIL_ = 1; end else if (B_WIDTH < 3 || A_WIDTH <= 4) begin wire _TECHMAP_FAIL_ = 1; From 976d8030dce8cd242401933ac8ea6c8ffe8af224 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 25 Apr 2019 19:59:33 -0700 Subject: [PATCH 239/514] Actually use pm.st.shiftxB --- passes/pmgen/split_shiftx.cc | 5 +++-- passes/pmgen/split_shiftx.pmg | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc index 2af0ebecf..3cbabcd76 100644 --- a/passes/pmgen/split_shiftx.cc +++ b/passes/pmgen/split_shiftx.cc @@ -30,10 +30,11 @@ void create_split_shiftx(split_shiftx_pm &pm) if (pm.blacklist_cells.count(pm.st.shiftx)) return; SigSpec A = pm.st.shiftx->getPort("\\A"); - SigSpec B = pm.st.shiftx->getPort("\\B"); + SigSpec B = pm.st.shiftxB; + log_assert(!B.empty()); SigSpec Y = pm.st.shiftx->getPort("\\Y"); const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int(); - const int B_WIDTH = pm.st.shiftx->getParam("\\B_WIDTH").as_int(); + const int B_WIDTH = GetSize(pm.st.shiftxB); const int Y_WIDTH = pm.st.shiftx->getParam("\\Y_WIDTH").as_int(); int trailing_zeroes = 0; for (; B[trailing_zeroes] == RTLIL::S0; ++trailing_zeroes) ; diff --git a/passes/pmgen/split_shiftx.pmg b/passes/pmgen/split_shiftx.pmg index c9e0ff995..3aafe1975 100644 --- a/passes/pmgen/split_shiftx.pmg +++ b/passes/pmgen/split_shiftx.pmg @@ -12,11 +12,13 @@ match macc endmatch code shiftxB + shiftxB = port(shiftx, \B); + if (macc) { - shiftxB = port(shiftx, \B); const int b_width = param(shiftx, \B_WIDTH).as_int(); if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0) shiftxB = shiftxB.extract(0, b_width-1); + if (port(macc, \Y) != shiftxB) { blacklist(shiftx); reject; From 4473fd15020cc186fde71eadc2325f69c92ae7ac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 11:14:33 -0700 Subject: [PATCH 240/514] Add -undef option to equiv_opt, passed to equiv_induct --- passes/equiv/equiv_opt.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc index e5dda9c24..3596dfd7b 100644 --- a/passes/equiv/equiv_opt.cc +++ b/passes/equiv/equiv_opt.cc @@ -44,7 +44,10 @@ struct EquivOptPass:public ScriptPass log(" useful for handling architecture-specific primitives.\n"); log("\n"); log(" -assert\n"); - log(" produce an error if the circuits are not equivalent\n"); + log(" produce an error if the circuits are not equivalent.\n"); + log("\n"); + log(" -undef\n"); + log(" enable modelling of undef states during equiv_induct.\n"); log("\n"); log("The following commands are executed by this verification command:\n"); help_script(); @@ -52,13 +55,14 @@ struct EquivOptPass:public ScriptPass } std::string command, techmap_opts; - bool assert; + bool assert, undef; void clear_flags() YS_OVERRIDE { command = ""; techmap_opts = ""; assert = false; + undef = false; } void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE @@ -84,6 +88,10 @@ struct EquivOptPass:public ScriptPass assert = true; continue; } + if (args[argidx] == "-undef") { + undef = true; + continue; + } break; } @@ -139,7 +147,12 @@ struct EquivOptPass:public ScriptPass if (check_label("prove")) { run("equiv_make gold gate equiv"); - run("equiv_induct equiv"); + if (help_mode) + run("equiv_induct [-undef] equiv"); + else if (undef) + run("equiv_induct -undef equiv"); + else + run("equiv_induct equiv"); if (help_mode) run("equiv_status [-assert] equiv"); else if (assert) From 8469d9fe9ff0a819c6b67aa6121cfd01cd1d0665 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 14:51:37 -0700 Subject: [PATCH 241/514] Missing newline --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f65ae87f5..b6b22284c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -139,7 +139,7 @@ struct SynthXilinxPass : public Pass log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); log(" clean\n"); log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n"); - log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); + log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v\n"); log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n"); log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); log("\n"); From dcc8a13e481c058f17b98ea900f9feb9192ea5ae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 15:32:02 -0700 Subject: [PATCH 242/514] Revert "Merge branch 'eddie/split_shiftx' into xc7mux" This reverts commit 3042d5833041021bb45252b0cc862e9eff3d27d3, reversing changes made to feff9764540cbf1152459cb377fc68d8e10c7153. --- README.md | 6 +-- kernel/cellaigs.cc | 2 +- kernel/celltypes.h | 2 +- passes/opt/wreduce.cc | 2 + passes/pmgen/.gitignore | 2 +- passes/pmgen/Makefile.inc | 13 +++--- passes/pmgen/README.md | 2 +- passes/pmgen/split_shiftx.cc | 84 ----------------------------------- passes/pmgen/split_shiftx.pmg | 59 ------------------------ 9 files changed, 14 insertions(+), 158 deletions(-) delete mode 100644 passes/pmgen/split_shiftx.cc delete mode 100644 passes/pmgen/split_shiftx.pmg diff --git a/README.md b/README.md index 913777f2e..46bed4242 100644 --- a/README.md +++ b/README.md @@ -370,7 +370,7 @@ Verilog Attributes and non-standard features - When defining a macro with `define, all text between triple double quotes is interpreted as macro body, even if it contains unescaped newlines. The - triple double quotes are removed from the macro body. For example: + tipple double quotes are removed from the macro body. For example: `define MY_MACRO(a, b) """ assign a = 23; @@ -457,7 +457,7 @@ Non-standard or SystemVerilog features for formal verification supported in any clocked block. - The syntax ``@($global_clock)`` can be used to create FFs that have no - explicit clock input (``$ff`` cells). The same can be achieved by using + explicit clock input ($ff cells). The same can be achieved by using ``@(posedge )`` or ``@(negedge )`` when ```` is marked with the ``(* gclk *)`` Verilog attribute. @@ -470,7 +470,7 @@ from SystemVerilog: - The ``assert`` statement from SystemVerilog is supported in its most basic form. In module context: ``assert property ();`` and within an - always block: ``assert();``. It is transformed to an ``$assert`` cell. + always block: ``assert();``. It is transformed to a $assert cell. - The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are also supported. The same limitations as with the ``assert`` statement apply. diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc index 26c625f89..5fd76afe5 100644 --- a/kernel/cellaigs.cc +++ b/kernel/cellaigs.cc @@ -453,7 +453,7 @@ Aig::Aig(Cell *cell) int B = mk.inport("\\B"); int C = mk.inport("\\C"); int D = mk.inport("\\D"); - int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D)); + int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D)); mk.outport(Y, "\\Y"); goto optimize; } diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 0da78c313..ae88f4aaf 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -464,7 +464,7 @@ struct CellTypes if (cell->type == "$_AOI4_") return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); if (cell->type == "$_OAI4_") - return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1)); + return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); log_assert(arg4.bits.size() == 0); return eval(cell, arg1, arg2, arg3, errp); diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 68e077cf9..52245ce3e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -462,10 +462,12 @@ struct WreduceWorker SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) { + log_dump(initsig[i], remove_init_bits.count(initsig[i])); if (!remove_init_bits.count(initsig[i])) new_initval[i] = initval[i]; } w->attributes.at("\\init") = new_initval; + log_dump(w->name, initval, new_initval); } } } diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index 52dfd93f3..c9263057e 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1 +1 @@ -*_pm.h +/ice40_dsp_pm.h diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 5669bd3d1..e0609d9ba 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,11 +1,8 @@ -PMG_SRC = $(wildcard passes/pmgen/*.pmg) -PMG_OBJS += $(patsubst %.pmg, %.o, $(PMG_SRC)) -OBJS += $(PMG_OBJS) +OBJS += passes/pmgen/ice40_dsp.o -$(PMG_OBJS): %.o: %_pm.h +passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h +EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h +.SECONDARY: passes/pmgen/ice40_dsp_pm.h -EXTRA_OBJS += $(patsubst %.pmg, %_pm.h, $(PMG_SRC)) -.SECONDARY: $(EXTRA_OBJS) - -%_pm.h: passes/pmgen/pmgen.py %.pmg +passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg $(P) mkdir -p passes/pmgen && python3 $^ $@ diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 320e95a77..7a46558b1 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -220,5 +220,5 @@ But in some cases it is more natural to utilize the implicit branch statement: portAB = \B; endcode -There is an implicit `code..endcode` block at the end of each `.pmg` file +There is an implicit `code..endcode` block at the end of each `.pgm` file that just accepts everything that gets all the way there. diff --git a/passes/pmgen/split_shiftx.cc b/passes/pmgen/split_shiftx.cc deleted file mode 100644 index 3cbabcd76..000000000 --- a/passes/pmgen/split_shiftx.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" -#include "passes/pmgen/split_shiftx_pm.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -void create_split_shiftx(split_shiftx_pm &pm) -{ - log_assert(pm.st.shiftx); - if (pm.blacklist_cells.count(pm.st.shiftx)) - return; - SigSpec A = pm.st.shiftx->getPort("\\A"); - SigSpec B = pm.st.shiftxB; - log_assert(!B.empty()); - SigSpec Y = pm.st.shiftx->getPort("\\Y"); - const int A_WIDTH = pm.st.shiftx->getParam("\\A_WIDTH").as_int(); - const int B_WIDTH = GetSize(pm.st.shiftxB); - const int Y_WIDTH = pm.st.shiftx->getParam("\\Y_WIDTH").as_int(); - int trailing_zeroes = 0; - for (; B[trailing_zeroes] == RTLIL::S0; ++trailing_zeroes) ; - const int WIDTH = trailing_zeroes > 0 ? 1 << trailing_zeroes : Y_WIDTH; - std::vector bits; - bits.resize(A_WIDTH / WIDTH); - for (int i = 0; i < Y_WIDTH; ++i) { - for (int j = 0; j < A_WIDTH/WIDTH; ++j) - bits[j] = A[j*WIDTH + i]; - pm.module->addShiftx(NEW_ID, bits, B.extract(trailing_zeroes, B_WIDTH-trailing_zeroes), Y[i]); - } - pm.st.shiftx->unsetPort("\\Y"); - - pm.autoremove(pm.st.shiftx); - pm.autoremove(pm.st.macc); -} - -struct BitblastShiftxPass : public Pass { - BitblastShiftxPass() : Pass("split_shiftx", "Split up multi-bit $shiftx cells") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" split_shiftx [selection]\n"); - log("\n"); - log("Split up $shiftx cells where Y_WIDTH > 1, with consideration for any $macc\n"); - log("cells -- configured as a constant multiplier equal to Y_WIDTH -- that may be\n"); - log("driving their B inputs.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing SPLIT_SHIFTX pass.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - split_shiftx_pm(module, module->selected_cells()).run(create_split_shiftx); - } -} BitblastShiftxPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/split_shiftx.pmg b/passes/pmgen/split_shiftx.pmg deleted file mode 100644 index 3aafe1975..000000000 --- a/passes/pmgen/split_shiftx.pmg +++ /dev/null @@ -1,59 +0,0 @@ -state shiftxB - -match shiftx - select shiftx->type == $shiftx - select param(shiftx, \Y_WIDTH).as_int() > 1 -endmatch - -match macc - select macc->type == $macc - select param(macc, \B_WIDTH).as_int() == 0 - optional -endmatch - -code shiftxB - shiftxB = port(shiftx, \B); - - if (macc) { - const int b_width = param(shiftx, \B_WIDTH).as_int(); - if (param(shiftx, \B_SIGNED) != 0 && shiftxB[b_width-1] == RTLIL::S0) - shiftxB = shiftxB.extract(0, b_width-1); - - if (port(macc, \Y) != shiftxB) { - blacklist(shiftx); - reject; - } - - Const config = param(macc, \CONFIG); - const int config_width = param(macc, \CONFIG_WIDTH).as_int(); - const int num_bits = config.extract(0, 4).as_int(); - const int num_ports = (config_width - 4) / (2 + 2*num_bits); - if (num_ports != 1) { - blacklist(shiftx); - reject; - } - // IS_SIGNED? - if (config[4] == 1) { - blacklist(shiftx); - reject; - } - // DO_SUBTRACT? - if (config[5] == 1) { - blacklist(shiftx); - reject; - } - const int port_size_A = config.extract(6, num_bits).as_int(); - const int port_size_B = config.extract(6 + num_bits, num_bits).as_int(); - const SigSpec port_B = port(macc, \A).extract(port_size_A, port_size_B); - if (!port_B.is_fully_const()) { - blacklist(shiftx); - reject; - } - const int multiply_factor = port_B.as_int(); - if (multiply_factor != param(shiftx, \Y_WIDTH).as_int()) { - blacklist(shiftx); - reject; - } - shiftxB = port(macc, \A).extract(0, port_size_A); - } -endcode From 6b9ca7cd6d14ac5e3ebf8354849a5c31d9a3a49b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 15:32:58 -0700 Subject: [PATCH 243/514] Remove split_shiftx call --- techlibs/xilinx/synth_xilinx.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b6b22284c..1320673e5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -126,7 +126,6 @@ struct SynthXilinxPass : public Pass log("\n"); log(" map_cells:\n"); log(" pmux2shiftx (without '-nosrl' and '-nomux' only)\n"); - log(" split_shiftx (without '-nosrl' and '-nomux' only)\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); @@ -310,10 +309,8 @@ struct SynthXilinxPass : public Pass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!nosrl || !nomux) { + if (!nosrl || !nomux) Pass::call(design, "pmux2shiftx"); - Pass::call(design, "split_shiftx"); - } if (!nosrl) { // shregmap operates on bit-level flops, not word-level, From e31e21766d3bf323ce61754a28ac58ec7118b9c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 16:09:54 -0700 Subject: [PATCH 244/514] Try a different approach with 'muxcover' --- techlibs/xilinx/cells_map.v | 82 ++++++--------------------------- techlibs/xilinx/synth_xilinx.cc | 44 +++++++++--------- 2 files changed, 37 insertions(+), 89 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index c814f3a96..258b6c3de 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -143,75 +143,23 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endmodule `ifndef NO_MUXFN -module \$shiftx (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; +module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); + input A, B, C, D, E, F, G, H, S, T, U; + output Y; - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; + wire [1:0] Z; + assign Z = T ? (S ? {D,H} : {C,G}) : + (S ? {B,F} : {A,E}); + MUXF7 fpga_muxf7 (.I0(Z[0]), .I1(Z[1]), .S(U), .O(Y)); +endmodule - parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; +module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); + input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; + output Y; - generate - genvar i, j; - if (B_SIGNED) begin - if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); - else - wire _TECHMAP_FAIL_ = 1; - end - else if (Y_WIDTH > 1) begin - wire _TECHMAP_FAIL_ = 1; - end - else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - wire _TECHMAP_FAIL_ = 1; - end - else if (B_WIDTH == 3) begin - localparam a_width0 = 2 ** 2; - localparam a_widthN = A_WIDTH - a_width0; - wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); - end - else if (B_WIDTH == 4) begin - localparam a_width0 = 2 ** 2; - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [4-1:0] T; - wire T0, T1; - for (i = 0; i < 4; i++) - if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = 1'bx; - MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); - MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); - MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); - end - else begin - localparam a_width0 = 2 ** 4; - localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) - if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - end - else - assign T[i] = 1'bx; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); - end - endgenerate + wire [1:0] Z; + \$_MUX8_ fpga_mux8_0 (.A(A), .B(B), .C(C), .D(D), .E(E), .F(F), .G(G), .H(H), .S(S), .T(T), .U(U), .Y(Z[0])); + \$_MUX8_ fpga_mux8_1 (.A(I), .B(J), .C(K), .D(L), .E(M), .F(N), .G(O), .H(P), .S(S), .T(T), .U(U), .Y(Z[1])); + MUXF8 fpga_muxf8 (.I0(Z[0]), .I1(Z[1]), .S(V), .O(Y)); endmodule `endif // NO_MUXFN diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 524c54d3b..5652806f7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -292,18 +292,6 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - if (!nocarry) { - if (vpr) - Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - else - Pass::call(design, "techmap -map +/xilinx/arith_map.v"); - } - - Pass::call(design, "opt -fast"); - } - - if (check_label(active, run_from, run_to, "map_cells")) - { // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former @@ -311,17 +299,30 @@ struct SynthXilinxPass : public Pass if (!nosrl || !nomux) Pass::call(design, "pmux2shiftx"); - if (!nosrl) { - // shregmap operates on bit-level flops, not word-level, - // so break those down here - Pass::call(design, "simplemap t:$dff t:$dffe"); - // pmux2shiftx can leave behind a $pmux with a single entry - // -- need this to clean that up before shregmap - Pass::call(design, "opt_expr -mux_undef"); - // shregmap with '-tech xilinx' infers variable length shift regs - Pass::call(design, "shregmap -tech xilinx -minlen 3"); + Pass::call(design, "opt -full"); + if (!nocarry) { + if (vpr) + Pass::call(design, "techmap -map +/techmap.v -D _EXPLICIT_CARRY -map +/xilinx/arith_map.v"); + else + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); } + else { + Pass::call(design, "techmap"); + } + Pass::call(design, "opt -fast"); + // shregmap with '-tech xilinx' infers variable length shift regs + if (!nosrl) + Pass::call(design, "shregmap -tech xilinx -minlen 3"); + + if (!nomux) + Pass::call(design, "muxcover -mux8 -mux16"); + + Pass::call(design, "opt -fast"); + } + + if (check_label(active, run_from, run_to, "map_cells")) + { std::string define; if (nomux) define += " -D NO_MUXFN"; @@ -331,7 +332,6 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); if (abc == "abc9") Pass::call(design, abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box" + string(retime ? " -dff" : "")); From ccc283737d99cb0f4d5742692d5d86c4ad9396c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 16:28:48 -0700 Subject: [PATCH 245/514] Apparently, this reduces number of MUXCY/XORCY --- techlibs/xilinx/synth_xilinx.cc | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 5652806f7..4ec115bec 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -287,11 +287,18 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "opt -fast"); + Pass::call(design, "opt -fast -full"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); + if (!nocarry) { + if (vpr) + Pass::call(design, "techmap -D _EXPLICIT_CARRY -map +/xilinx/arith_map.v"); + else + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); + } + // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former @@ -300,15 +307,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "pmux2shiftx"); Pass::call(design, "opt -full"); - if (!nocarry) { - if (vpr) - Pass::call(design, "techmap -map +/techmap.v -D _EXPLICIT_CARRY -map +/xilinx/arith_map.v"); - else - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); - } - else { - Pass::call(design, "techmap"); - } + Pass::call(design, "techmap"); Pass::call(design, "opt -fast"); // shregmap with '-tech xilinx' infers variable length shift regs From 0f1ba949243aa7ccc7c6b42738a60a09be7a209e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 19:45:47 -0700 Subject: [PATCH 246/514] Remove split_shiftx tests --- tests/various/split_shiftx.v | 118 ---------------------------------- tests/various/split_shiftx.ys | 21 ------ 2 files changed, 139 deletions(-) delete mode 100644 tests/various/split_shiftx.v delete mode 100644 tests/various/split_shiftx.ys diff --git a/tests/various/split_shiftx.v b/tests/various/split_shiftx.v deleted file mode 100644 index dfcea3880..000000000 --- a/tests/various/split_shiftx.v +++ /dev/null @@ -1,118 +0,0 @@ -module split_shiftx_test01(i, s, o); - wire [3:0] _0_; - input [8:0] i; - output [2:0] o; - input [1:0] s; - \$macc #( - .A_WIDTH(32'd4), - .B_WIDTH(32'd0), - .CONFIG(10'h282), - .CONFIG_WIDTH(32'd10), - .Y_WIDTH(32'd4) - ) _1_ ( - .A({ 2'h3, s }), - .B(), - .Y(_0_) - ); - \$shiftx #( - .A_SIGNED(32'd0), - .A_WIDTH(32'd9), - .B_SIGNED(32'd1), - .B_WIDTH(32'd5), - .Y_WIDTH(32'd3) - ) _2_ ( - .A(i), - .B({ 1'h0, _0_ }), - .Y(o) - ); -endmodule - -// Sign bit is 1 -module split_shiftx_test02(i, s, o); - wire [3:0] _0_; - input [8:0] i; - output [2:0] o; - input [1:0] s; - \$macc #( - .A_WIDTH(32'd4), - .B_WIDTH(32'd0), - .CONFIG(10'h282), - .CONFIG_WIDTH(32'd10), - .Y_WIDTH(32'd4) - ) _1_ ( - .A({ 2'h3, s }), - .B(), - .Y(_0_) - ); - \$shiftx #( - .A_SIGNED(32'd0), - .A_WIDTH(32'd9), - .B_SIGNED(32'd1), - .B_WIDTH(32'd5), - .Y_WIDTH(32'd3) - ) _2_ ( - .A(i), - .B({ 1'h1, _0_ }), - .Y(o) - ); -endmodule - -// Non constant $macc -module split_shiftx_test03(i, s, o); - wire [3:0] _0_; - input [8:0] i; - output [2:0] o; - input [1:0] s; - \$macc #( - .A_WIDTH(32'd4), - .B_WIDTH(32'd0), - .CONFIG(10'h282), - .CONFIG_WIDTH(32'd10), - .Y_WIDTH(32'd4) - ) _1_ ( - .A({ s, s }), - .B(), - .Y(_0_) - ); - \$shiftx #( - .A_SIGNED(32'd0), - .A_WIDTH(32'd9), - .B_SIGNED(32'd1), - .B_WIDTH(32'd5), - .Y_WIDTH(32'd3) - ) _2_ ( - .A(i), - .B({ 1'h0, _0_ }), - .Y(o) - ); -endmodule - -// Wrong constant $macc -module split_shiftx_test04(i, s, o); - wire [3:0] _0_; - input [8:0] i; - output [2:0] o; - input [1:0] s; - \$macc #( - .A_WIDTH(32'd4), - .B_WIDTH(32'd0), - .CONFIG(10'h282), - .CONFIG_WIDTH(32'd10), - .Y_WIDTH(32'd4) - ) _1_ ( - .A({ 2'h2, s }), - .B(), - .Y(_0_) - ); - \$shiftx #( - .A_SIGNED(32'd0), - .A_WIDTH(32'd9), - .B_SIGNED(32'd1), - .B_WIDTH(32'd5), - .Y_WIDTH(32'd3) - ) _2_ ( - .A(i), - .B({ 1'h0, _0_ }), - .Y(o) - ); -endmodule diff --git a/tests/various/split_shiftx.ys b/tests/various/split_shiftx.ys deleted file mode 100644 index 810348aa3..000000000 --- a/tests/various/split_shiftx.ys +++ /dev/null @@ -1,21 +0,0 @@ -read_verilog -icells split_shiftx.v -split_shiftx - -cd split_shiftx_test01 -select -assert-count 3 t:$shiftx -select -assert-count 0 t: t:$shiftx %n %i - -cd split_shiftx_test02 -select -assert-count 1 t:$shiftx -select -assert-count 1 t:$macc -select -assert-count 0 t: t:$shiftx t:$macc %u %n %i - -cd split_shiftx_test03 -select -assert-count 1 t:$shiftx -select -assert-count 1 t:$macc -select -assert-count 0 t: t:$shiftx t:$macc %u %n %i - -cd split_shiftx_test04 -select -assert-count 1 t:$shiftx -select -assert-count 1 t:$macc -select -assert-count 0 t: t:$shiftx t:$macc %u %n %i From 4aca928033874e8e35ecc4a18f22475c00bebad9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 19:46:34 -0700 Subject: [PATCH 247/514] Fix spacing --- techlibs/xilinx/cells_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 258b6c3de..6c280e0f1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -147,7 +147,7 @@ module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); input A, B, C, D, E, F, G, H, S, T, U; output Y; - wire [1:0] Z; + wire [1:0] Z; assign Z = T ? (S ? {D,H} : {C,G}) : (S ? {B,F} : {A,E}); MUXF7 fpga_muxf7 (.I0(Z[0]), .I1(Z[1]), .S(U), .O(Y)); @@ -157,9 +157,9 @@ module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y) input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; output Y; - wire [1:0] Z; - \$_MUX8_ fpga_mux8_0 (.A(A), .B(B), .C(C), .D(D), .E(E), .F(F), .G(G), .H(H), .S(S), .T(T), .U(U), .Y(Z[0])); - \$_MUX8_ fpga_mux8_1 (.A(I), .B(J), .C(K), .D(L), .E(M), .F(N), .G(O), .H(P), .S(S), .T(T), .U(U), .Y(Z[1])); + wire [1:0] Z; + \$_MUX8_ fpga_mux8_0 (.A(A), .B(B), .C(C), .D(D), .E(E), .F(F), .G(G), .H(H), .S(S), .T(T), .U(U), .Y(Z[0])); + \$_MUX8_ fpga_mux8_1 (.A(I), .B(J), .C(K), .D(L), .E(M), .F(N), .G(O), .H(P), .S(S), .T(T), .U(U), .Y(Z[1])); MUXF8 fpga_muxf8 (.I0(Z[0]), .I1(Z[1]), .S(V), .O(Y)); endmodule `endif // NO_MUXFN From 3b5e8c86a4516c202e877ee5ca154062682e15b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 11:00:49 -0700 Subject: [PATCH 248/514] Fix -nocarry --- techlibs/xilinx/synth_xilinx.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index bde95c638..a0e77021a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -241,10 +241,10 @@ struct SynthXilinxPass : public ScriptPass run("dff2dffe"); run("opt -full"); - if (!vpr || help_mode) - run("techmap -map +/xilinx/arith_map.v"); - else + if (vpr && !nocarry && !help_mode) run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + else if (!nocarry || help_mode) + run("techmap -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, From d05ac7257e437466db0ce7f4c3264d8ad8e18fcd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 11:14:28 -0700 Subject: [PATCH 249/514] Missing help_mode --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a0e77021a..dd8b51818 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -232,7 +232,7 @@ struct SynthXilinxPass : public ScriptPass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!nosrl || !nomux) + if (!nosrl || !nomux || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); run("opt -fast -full"); From 95867109ea4201d77a95a22f51cd3c4309ff8240 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 11:25:10 -0700 Subject: [PATCH 250/514] Revert to pre-muxcover approach --- techlibs/xilinx/cells_map.v | 98 ++++++++++++++++++++++++++------- techlibs/xilinx/synth_xilinx.cc | 13 ++--- 2 files changed, 84 insertions(+), 27 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index a80988480..0ec72b6a4 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -150,24 +150,84 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule -`ifndef NO_MUXFN -module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); - input A, B, C, D, E, F, G, H, S, T, U; - output Y; +module \$shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; - wire [1:0] Z; - assign Z = T ? (S ? {D,H} : {C,G}) : - (S ? {B,F} : {A,E}); - MUXF7 fpga_muxf7 (.I0(Z[0]), .I1(Z[1]), .S(U), .O(Y)); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + generate + genvar i, j; + if (B_SIGNED) begin + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + end + else if (Y_WIDTH > 1) begin + for (i = 0; i < Y_WIDTH; i++) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); + end + // If the LSB of B is constant zero (and Y_WIDTH is 1) then + // we can optimise by removing every other entry from A + // and popping the constant zero from B + else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin + wire [(A_WIDTH+1)/2-1:0] A_i; + for (i = 0; i < (A_WIDTH+1)/2; i++) + assign A_i[i] = A[i*2]; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + end + else if (B_WIDTH < 3 || A_WIDTH <= 4) begin + wire _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH == 3) begin + localparam a_width0 = 2 ** 2; + localparam a_widthN = A_WIDTH - a_width0; + wire T0, T1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + end + else if (B_WIDTH == 4) begin + localparam a_width0 = 2 ** 2; + localparam num_mux8 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; + wire [4-1:0] T; + wire T0, T1; + for (i = 0; i < 4; i++) + if (i < num_mux8) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + else if (i == num_mux8 && a_widthN > 0) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = 1'bx; + MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); + MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); + MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); + end + else begin + localparam a_width0 = 2 ** 4; + localparam num_mux16 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux16*a_width0; + wire [(2**(B_WIDTH-4))-1:0] T; + for (i = 0; i < 2 ** (B_WIDTH-4); i++) + if (i < num_mux16) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + else if (i == num_mux16 && a_widthN > 0) begin + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + end + else + assign T[i] = 1'bx; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + end + endgenerate endmodule - -module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); - input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; - output Y; - - wire [1:0] Z; - \$_MUX8_ fpga_mux8_0 (.A(A), .B(B), .C(C), .D(D), .E(E), .F(F), .G(G), .H(H), .S(S), .T(T), .U(U), .Y(Z[0])); - \$_MUX8_ fpga_mux8_1 (.A(I), .B(J), .C(K), .D(L), .E(M), .F(N), .G(O), .H(P), .S(S), .T(T), .U(U), .Y(Z[1])); - MUXF8 fpga_muxf8 (.I0(Z[0]), .I1(Z[1]), .S(V), .O(Y)); -endmodule -`endif // NO_MUXFN diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index dd8b51818..7d7a05616 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -232,7 +232,7 @@ struct SynthXilinxPass : public ScriptPass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!nosrl || !nomux || help_mode) + if ((!nosrl && !nomux) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); run("opt -fast -full"); @@ -254,18 +254,15 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } + if (!nomux || help_mode) + run("techmap -map +/xilinx/cells_map.v"); + run("techmap"); run("opt -fast"); - - if (!nomux || help_mode) - run("muxcover -mux8 -mux16"); } if (check_label("map_cells")) { - std::string define; - if (nomux) - define += " -D NO_MUXFN"; - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v" + define); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } From d80445e0492c67b63435880b3bca4ccbf6f3db43 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 11:35:57 -0700 Subject: [PATCH 251/514] Use new peepopt from #969 --- techlibs/xilinx/synth_xilinx.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7d7a05616..a1c4acf7e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -211,6 +211,18 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { run("synth -run coarse"); + + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifying variable-length shift registers, + // so attempt to convert $pmux-es to the former + // Also: wide multiplexer inference benefits from this too + if ((!nosrl && !nomux) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); + + // Run a number of peephole optimisations, including one + // that optimises $mul cells driving $shiftx's B input + // and that aids wide mux analysis + run("peepopt"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -228,13 +240,6 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifying variable-length shift registers, - // so attempt to convert $pmux-es to the former - // Also: wide multiplexer inference benefits from this too - if ((!nosrl && !nomux) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); - run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); @@ -246,6 +251,9 @@ struct SynthXilinxPass : public ScriptPass else if (!nocarry || help_mode) run("techmap -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); + if (!nomux || help_mode) + run("techmap -map +/xilinx/cells_map.v"); + if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here @@ -254,9 +262,6 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - if (!nomux || help_mode) - run("techmap -map +/xilinx/cells_map.v"); - run("techmap"); run("opt -fast"); } From fc72f07efdfbc1b87c4838af6138cdaa3cfd97ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 15:01:37 -0700 Subject: [PATCH 252/514] Add don't care optimisation --- techlibs/xilinx/cells_map.v | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 0ec72b6a4..ecfbe2555 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -161,11 +161,14 @@ module \$shiftx (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate genvar i, j; + // TODO: Check if this opt still necessary if (B_SIGNED) begin if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) // Optimisation to remove B_SIGNED if sign bit of B is constant-0 @@ -186,6 +189,14 @@ module \$shiftx (A, B, Y); assign A_i[i] = A[i*2]; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end + // If upper half of A input is all constant 1'bx then + // chop this $shiftx in half + else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1:2**(B_WIDTH-1)] == {A_WIDTH-2**(B_WIDTH-1){1'b1}} && _TECHMAP_CONSTVAL_A_[A_WIDTH-1:2**(B_WIDTH-1)] === {A_WIDTH-2**(B_WIDTH-1){1'bx}}) begin + if (B_WIDTH > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-1)), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[2**(B_WIDTH-1)-1:0]), .B(B[B_WIDTH-2:0]), .Y(Y)); + else + assign Y = A[0]; + end else if (B_WIDTH < 3 || A_WIDTH <= 4) begin wire _TECHMAP_FAIL_ = 1; end From 283e33ba5aad3a66bd14c30e1f52361c5f4c9789 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 16:02:37 -0700 Subject: [PATCH 253/514] Trim off leading 1'bx in A --- techlibs/xilinx/cells_map.v | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index ecfbe2555..729cda139 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -166,6 +166,20 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + function integer compute_num_leading_X_in_A; + integer i, c; + begin + compute_num_leading_X_in_A = 0; + c = 1; + for (i = A_WIDTH-1; i >= 0; i=i-1) begin + if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx) + c = 0; + compute_num_leading_X_in_A = compute_num_leading_X_in_A + c; + end + end + endfunction + localparam num_leading_X_in_A = compute_num_leading_X_in_A(); + generate genvar i, j; // TODO: Check if this opt still necessary @@ -176,6 +190,7 @@ module \$shiftx (A, B, Y); else wire _TECHMAP_FAIL_ = 1; end + // Bit-blast else if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); @@ -189,13 +204,11 @@ module \$shiftx (A, B, Y); assign A_i[i] = A[i*2]; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end - // If upper half of A input is all constant 1'bx then - // chop this $shiftx in half - else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1:2**(B_WIDTH-1)] == {A_WIDTH-2**(B_WIDTH-1){1'b1}} && _TECHMAP_CONSTVAL_A_[A_WIDTH-1:2**(B_WIDTH-1)] === {A_WIDTH-2**(B_WIDTH-1){1'bx}}) begin - if (B_WIDTH > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-1)), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[2**(B_WIDTH-1)-1:0]), .B(B[B_WIDTH-2:0]), .Y(Y)); - else - assign Y = A[0]; + // Trim off any leading 1'bx -es in A, and resize B accordingly + else if (num_leading_X_in_A > 0) begin + localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; + localparam B_WIDTH_new = $clog2(A_WIDTH_new); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); end else if (B_WIDTH < 3 || A_WIDTH <= 4) begin wire _TECHMAP_FAIL_ = 1; From 36a219063ad7b4e70581bf83a00365db764737bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 14:31:19 -0700 Subject: [PATCH 254/514] Modify LUT area cost to be same as old abc --- techlibs/xilinx/abc.lut | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc.lut index c6bc7b1f7..c53cd50a1 100644 --- a/techlibs/xilinx/abc.lut +++ b/techlibs/xilinx/abc.lut @@ -1,12 +1,11 @@ -# Max delays from https://pastebin.com/v2hrcksd -# from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # K area delay -1 11 624 -2 12 624 -3 13 624 -4 14 624 -5 15 624 -6 20 724 -7 40 1020 -8 80 1293 +1 1 624 +2 2 624 +3 3 624 +4 3 624 +5 3 624 +6 5 724 +7 10 1020 +8 20 1293 From 0f094fba08b69baa2329e749daf19f41a624a0a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 16:19:23 -0700 Subject: [PATCH 255/514] Pad all boxes so that all input/output connections specified --- backends/aiger/xaiger.cc | 91 ++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f9d874e2d..676311440 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -301,6 +301,35 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Fully pad all unused input connections of this box cell with S0 + // Fully pad all undriven output connections of thix box cell with anonymous wires + for (const auto w : box_module->wires()) { + if (w->port_input) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + } + if (w->port_output) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); + } + } + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { @@ -646,37 +675,53 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); + log_assert(holes_module); + dict> box_io; for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + RTLIL::Module* box_module = module->design->module(cell->type); + int box_id = box_module->attributes.at("\\abc_box_id").as_int(); Cell *holes_cell = nullptr; - if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + int box_inputs = 0, box_outputs = 0; + + auto it = box_io.find(cell->type); + if (it == box_io.end()) { holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - RTLIL::Wire *holes_wire; - // NB: cell->connections_ already sorted from before - for (const auto &c : cell->connections()) { - log_assert(c.second.size() == 1); - if (cell->input(c.first)) { - box_inputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; + + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + } + port_wire.append(holes_wire); } - holes_cell->setPort(c.first, holes_wire); - } - } - if (cell->output(c.first)) { - box_outputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); - holes_wire->port_output = true; - holes_cell->setPort(c.first, holes_wire); + holes_cell->setPort(w->name, holes_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); + } + holes_cell->setPort(w->name, holes_wire); } } + box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } + else + std::tie(box_inputs,box_outputs) = it->second; + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id); From ee8435b820bbea4a4ceb2c46a81de9d03d4aa44c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 16:19:45 -0700 Subject: [PATCH 256/514] Instead of MUXCY/XORCY use CARRY4 (with timing) --- techlibs/xilinx/abc.box | 22 +++++++++++++++------- techlibs/xilinx/arith_map.v | 4 ++-- techlibs/xilinx/cells_sim.v | 3 +-- techlibs/xilinx/synth_xilinx.cc | 2 ++ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index d572817df..57ea1670c 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -1,5 +1,4 @@ -# Max delays from https://pastebin.com/v2hrcksd -# from https://github.com/SymbiFlow/prjxray/pull/706#issuecomment-479380321 +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # F7BMUX slower than F7AMUX # Inputs: I0 I1 S0 @@ -12,8 +11,17 @@ F7BMUX 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -MUXCY 3 1 3 1 -1 1 1 - -XORCY 4 1 2 1 -1 1 +# CARRY4 + CARRY4_[ABCD]X +# Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 +# Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3 +CARRY4 3 1 10 8 +271 157 228 114 222 334 239 313 +536 494 592 580 482 598 584 642 +379 465 540 526 - 407 556 615 +- 445 520 507 - - 537 596 +- - 356 398 - - - 438 +- - - 385 - - - - +340 433 512 508 223 400 523 582 +- 469 548 528 - 205 558 618 +- - 292 376 - - 226 330 +- - - 380 - - - 227 diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v index 09a5f07e8..5c848d4e6 100644 --- a/techlibs/xilinx/arith_map.v +++ b/techlibs/xilinx/arith_map.v @@ -180,7 +180,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); // First one if (i == 0) begin - CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part + CARRY4 carry4_1st_part ( .CYINIT(CI), .CI (1'd0), @@ -207,7 +207,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); // First one if (i == 0) begin - CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full + CARRY4 carry4_1st_full ( .CYINIT(CI), .CI (1'd0), diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 8b231480f..9db52b67a 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -155,7 +155,6 @@ module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5); assign O5 = I0 ? s5_1[1] : s5_1[0]; endmodule -(* abc_box_id = 3, lib_whitebox *) module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule @@ -170,11 +169,11 @@ module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule -(* abc_box_id = 4, lib_whitebox *) module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule +(* abc_box_id = 3, lib_whitebox *) module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e9a3b53a0..ec7768ffe 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -261,6 +261,8 @@ struct SynthXilinxPass : public ScriptPass if (vpr && !nocarry && !help_mode) run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + else if (abc == "abc9" && !nocarry && !help_mode) + run("techmap -map +/xilinx/arith_map.v -D _CLB_CARRY", "(skip if '-nocarry')"); else if (!nocarry || help_mode) run("techmap -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); From 9b1078b9bde70141514488acd01bb32b5422f9bd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 18:50:02 -0700 Subject: [PATCH 257/514] Fix/workaround symptom unveiled by #1023 --- techlibs/xilinx/cells_map.v | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f566a8584..af6414667 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -220,7 +220,10 @@ module \$shiftx (A, B, Y); localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + else + assign T1 = A[A_WIDTH-1]; MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); end else if (B_WIDTH == 4) begin @@ -232,8 +235,12 @@ module \$shiftx (A, B, Y); for (i = 0; i < 4; i++) if (i < num_mux8) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 0) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else if (i == num_mux8 && a_widthN > 0) begin + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end else assign T[i] = 1'bx; MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); @@ -249,7 +256,10 @@ module \$shiftx (A, B, Y); if (i < num_mux16) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; end else assign T[i] = 1'bx; From 4f44e3399ba6c959c830943c44c4ad728be895fa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 May 2019 02:36:28 -0700 Subject: [PATCH 258/514] shift register inference before mux --- techlibs/xilinx/synth_xilinx.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ec7768ffe..3cee81a7b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -266,9 +266,6 @@ struct SynthXilinxPass : public ScriptPass else if (!nocarry || help_mode) run("techmap -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); - if (!nomux || help_mode) - run("techmap -map +/xilinx/cells_map.v"); - if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here @@ -277,6 +274,9 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } + if (!nomux || help_mode) + run("techmap -map +/xilinx/cells_map.v"); + run("techmap"); run("opt -fast"); } From ae89e6ab26d2d87a604e20ebc14dcda8c9901585 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 May 2019 08:58:57 -0700 Subject: [PATCH 259/514] Add whitebox support to DRAM --- techlibs/xilinx/abc.box | 14 ++++++++++++++ techlibs/xilinx/cells_sim.v | 10 ++++++++-- techlibs/xilinx/cells_xtra.sh | 4 ++-- techlibs/xilinx/cells_xtra.v | 18 ------------------ techlibs/xilinx/synth_xilinx.cc | 4 ++-- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index 57ea1670c..92ea5537b 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -25,3 +25,17 @@ CARRY4 3 1 10 8 - 469 548 528 - 205 558 618 - - 292 376 - - 226 330 - - - 380 - - - 227 + +# SLICEM/A6LUT +# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE +# Outputs: DPO SPO +RAM64X1D 4 1 15 2 +- - - - - - - 124 124 124 124 124 124 - - +124 124 124 124 124 124 - - - - - - 124 - - + +# SLICEM/A6LUT + F7[AB]MUX +# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE +# Outputs: DPO SPO +RAM128X1D 5 1 17 2 +- - - - - - - - 314 314 314 314 314 314 292 - - +347 347 347 347 347 347 296 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 9db52b67a..29c79f689 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,8 +281,9 @@ module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule +(* abc_box_id = 4, lib_whitebox *) module RAM64X1D ( - (* abc_flop_q *) output DPO, SPO, + output DPO, SPO, input D, WCLK, WE, input A0, A1, A2, A3, A4, A5, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 @@ -294,12 +295,15 @@ module RAM64X1D ( reg [63:0] mem = INIT; assign SPO = mem[a]; assign DPO = mem[dpra]; +`ifndef _ABC wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[a] <= D; +`endif endmodule +(* abc_box_id = 5, lib_whitebox *) module RAM128X1D ( - (* abc_flop_q *) output DPO, SPO, + output DPO, SPO, input D, WCLK, WE, input [6:0] A, DPRA ); @@ -308,8 +312,10 @@ module RAM128X1D ( reg [127:0] mem = INIT; assign SPO = mem[A]; assign DPO = mem[DPRA]; +`ifndef _ABC wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[A] <= D; +`endif endmodule module SRL16E ( diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 8e39b440d..e3b847c36 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -116,7 +116,7 @@ function xtract_cell_decl() xtract_cell_decl PS7 "(* keep *)" xtract_cell_decl PULLDOWN xtract_cell_decl PULLUP - xtract_cell_decl RAM128X1D + #xtract_cell_decl RAM128X1D xtract_cell_decl RAM128X1S xtract_cell_decl RAM256X1S xtract_cell_decl RAM32M @@ -125,7 +125,7 @@ function xtract_cell_decl() xtract_cell_decl RAM32X1S_1 xtract_cell_decl RAM32X2S xtract_cell_decl RAM64M - xtract_cell_decl RAM64X1D + x#tract_cell_decl RAM64X1D xtract_cell_decl RAM64X1S xtract_cell_decl RAM64X1S_1 xtract_cell_decl RAM64X2S diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index fbcc74682..0ec3d0df0 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -3655,17 +3655,6 @@ module PULLUP (...); output O; endmodule -module RAM128X1D (...); - parameter [127:0] INIT = 128'h00000000000000000000000000000000; - parameter [0:0] IS_WCLK_INVERTED = 1'b0; - output DPO, SPO; - input [6:0] A; - input [6:0] DPRA; - input D; - input WCLK; - input WE; -endmodule - module RAM128X1S (...); parameter [127:0] INIT = 128'h00000000000000000000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; @@ -3756,13 +3745,6 @@ module RAM64M (...); input WE; endmodule -module RAM64X1D (...); - parameter [63:0] INIT = 64'h0000000000000000; - parameter [0:0] IS_WCLK_INVERTED = 1'b0; - output DPO, SPO; - input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE; -endmodule - module RAM64X1S (...); parameter [63:0] INIT = 64'h0000000000000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3cee81a7b..ecfb94610 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -203,9 +203,9 @@ struct SynthXilinxPass : public ScriptPass { if (check_label("begin")) { if (vpr) - run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + run("read_verilog -lib -D_ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); else - run("read_verilog -lib +/xilinx/cells_sim.v"); + run("read_verilog -lib -D_ABC +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_xtra.v"); From 60af2ca94de482f09aaaa7d6eed66c299248f8f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 14:09:15 -0700 Subject: [PATCH 260/514] Transpose CARRY4 delays --- techlibs/xilinx/abc.box | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index 92ea5537b..9653fe5b8 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -15,16 +15,14 @@ MUXF8 2 1 3 1 # Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 # Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3 CARRY4 3 1 10 8 -271 157 228 114 222 334 239 313 -536 494 592 580 482 598 584 642 -379 465 540 526 - 407 556 615 -- 445 520 507 - - 537 596 -- - 356 398 - - - 438 -- - - 385 - - - - -340 433 512 508 223 400 523 582 -- 469 548 528 - 205 558 618 -- - 292 376 - - 226 330 -- - - 380 - - - 227 +271 536 379 - - - 340 - - - +157 494 465 445 - - 433 469 - - +228 592 540 520 356 - 512 548 292 - +114 580 526 507 398 385 508 528 378 380 +222 482 - - - - 223 - - - +334 598 407 - - - 400 205 - - +239 584 556 537 - - 523 558 226 - +313 642 615 596 438 - 582 618 330 227 # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE From 6ad09bfcea4711eaff609a4e804e29fa888d4b14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 15:10:18 -0700 Subject: [PATCH 261/514] Add &fraig and &mfs back --- passes/techmap/abc9.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3cee5a586..9f3d2287b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,8 +25,7 @@ #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; &if; &mfs; &ps" -#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m" +#define ABC_COMMAND_LUT "&st; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" #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" From ca5774ed40db8dafe3696deb9fe9827d7196d7bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 20:39:55 -0700 Subject: [PATCH 262/514] Try new LUT delays --- techlibs/xilinx/abc.lut | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc.lut index c53cd50a1..438ed0368 100644 --- a/techlibs/xilinx/abc.lut +++ b/techlibs/xilinx/abc.lut @@ -1,11 +1,14 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # K area delay -1 1 624 -2 2 624 -3 3 624 -4 3 624 -5 3 624 -6 5 724 -7 10 1020 -8 20 1293 +1 1 248 +2 2 248 372 +3 3 248 372 496 +4 3 248 372 496 620 +5 3 248 372 496 620 744 +6 5 124 248 372 496 620 744 + # F7BMUX +7 10 296 420 544 668 792 916 1040 + # F8MUX + # F8MUX+F7BMUX +8 20 273 569 693 817 941 1065 1189 1313 From 01684643b6edd4290701b2e08114cb731db5f446 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 25 May 2019 22:34:50 -0700 Subject: [PATCH 263/514] Fix "write_xaiger", and to write each box contents into holes --- backends/aiger/xaiger.cc | 103 ++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 676311440..7e674cb87 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -385,8 +385,9 @@ struct XAigerWriter // Do some CI/CO post-processing: // Erase all POs that are undriven - for (auto bit : undriven_bits) - output_bits.erase(bit); + if (!holes_mode) + for (auto bit : undriven_bits) + output_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); @@ -676,55 +677,45 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); - dict> box_io; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); - int box_id = box_module->attributes.at("\\abc_box_id").as_int(); - Cell *holes_cell = nullptr; int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = holes_module->addCell(cell->name, cell->type); - auto it = box_io.find(cell->type); - if (it == box_io.end()) { - holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - - RTLIL::Wire *holes_wire; - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { - RTLIL::SigSpec port_wire; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - } - port_wire.append(holes_wire); + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; } - holes_cell->setPort(w->name, holes_wire); - } - if (w->port_output) { - box_outputs += GetSize(w); - for (int i = 0; i < GetSize(w); i++) { - if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); - else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); - holes_wire->port_output = true; - port_wire.append(holes_wire); - } - holes_cell->setPort(w->name, holes_wire); + port_wire.append(holes_wire); } + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); + } + holes_cell->setPort(w->name, port_wire); } - box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } - else - std::tie(box_inputs,box_outputs) = it->second; write_h_buffer(box_inputs); write_h_buffer(box_outputs); - write_h_buffer(box_id); + write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); write_h_buffer(0 /* OldBoxNum */); } @@ -746,7 +737,16 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); + + Pass::call(holes_module->design, "flatten -wb;"); + + // TODO: Should techmap all lib_whitebox-es once + Pass::call(holes_module->design, "techmap;"); + + Pass::call(holes_module->design, "aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -766,6 +766,29 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } + + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(0); + + f << "r"; + buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); From 32a4c10c0df7e82c69b0d96a63be0c5267d33257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 02:44:36 -0700 Subject: [PATCH 264/514] Fix "a" extension --- backends/aiger/xaiger.cc | 26 ++++++++++++++++++-------- passes/techmap/abc9.cc | 4 +++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e674cb87..3d275214b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -681,9 +681,12 @@ struct XAigerWriter for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = holes_module->addCell(cell->name, cell->type); + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) + holes_cell = holes_module->addCell(cell->name, cell->type); RTLIL::Wire *holes_wire; + // TODO: Only sort once box_module->wires_.sort(RTLIL::sort_by_id_str()); for (const auto w : box_module->wires()) { RTLIL::SigSpec port_wire; @@ -695,9 +698,11 @@ struct XAigerWriter holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } if (w->port_output) { box_outputs += GetSize(w); @@ -707,9 +712,13 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, RTLIL::S0); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -741,12 +750,13 @@ struct XAigerWriter // each box type once... Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb;"); + Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - Pass::call(holes_module->design, "techmap;"); + //Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap; clean -purge"); + Pass::call(holes_module->design, "aigmap"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 9f3d2287b..3c0132135 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,9 @@ #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; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" +//#define ABC_COMMAND_LUT "&st; &sweep -v; &ps -l -m; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" +#define ABC_COMMAND_LUT "&st; "/*"&sweep; "*/"&scorr; "/*"dc2; "*/"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" +//#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" #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" From 823153e418e743852ee927f797c3cc5bb81d19c9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 02:47:06 -0700 Subject: [PATCH 265/514] Combine ABC_COMMAND_LUT --- passes/techmap/abc9.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3c0132135..118bdf37b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,8 +25,7 @@ #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 -v; &ps -l -m; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" -#define ABC_COMMAND_LUT "&st; "/*"&sweep; "*/"&scorr; "/*"dc2; "*/"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" +#define ABC_COMMAND_LUT "&st; "/*"&sweep -v; "*/"&scorr; "/*"dc2; "*/"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" //#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" #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" From 66701c5fcc399d83e736e83064a39466361763ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 02:52:48 -0700 Subject: [PATCH 266/514] Muck about with LUT delays some more --- techlibs/xilinx/abc.lut | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc.lut index 438ed0368..5550a4039 100644 --- a/techlibs/xilinx/abc.lut +++ b/techlibs/xilinx/abc.lut @@ -1,11 +1,11 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # K area delay -1 1 248 -2 2 248 372 -3 3 248 372 496 -4 3 248 372 496 620 -5 3 248 372 496 620 744 +1 1 124 +2 2 124 248 +3 3 124 248 372 +4 3 124 248 372 496 +5 3 124 248 372 496 620 6 5 124 248 372 496 620 744 # F7BMUX 7 10 296 420 544 668 792 916 1040 From 086b6560b463878c543f9c9f981515b3b9409528 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 03:17:20 -0700 Subject: [PATCH 267/514] Typo --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 118bdf37b..513630a9a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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 -v; "*/"&scorr; "/*"dc2; "*/"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" +#define ABC_COMMAND_LUT "&st; "/*"&sweep -v; "*/"&scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" //#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" #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" From 67f7c64a778e46882f884fd7058dc7bc07c5ca1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 11:26:38 -0700 Subject: [PATCH 268/514] Fix padding, remove CIs from undriven_bits before erasing undriven POs --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d275214b..618a6500d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -302,16 +302,13 @@ struct XAigerWriter continue; // Fully pad all unused input connections of this box cell with S0 - // Fully pad all undriven output connections of thix box cell with anonymous wires + // Fully pad all undriven output connections of this box cell with anonymous wires for (const auto w : box_module->wires()) { if (w->port_input) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); @@ -319,11 +316,8 @@ struct XAigerWriter if (w->port_output) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); @@ -384,13 +378,13 @@ struct XAigerWriter } // Do some CI/CO post-processing: + // CIs cannot be undriven + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) output_bits.erase(bit); - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); From 3981eba999e1116f8f065451c6a71b8d3686b1bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 11:31:35 -0700 Subject: [PATCH 269/514] ABC9 to call &sweep --- passes/techmap/abc9.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 513630a9a..8341741fa 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,8 +25,7 @@ #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 -v; "*/"&scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l -m; &if; &ps -l -m" -//#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps -l -m" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if; &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" From 4311b9b583488817aaae0019f6ebc47deb030644 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 11:32:02 -0700 Subject: [PATCH 270/514] Blackboxes --- techlibs/xilinx/abc.box | 10 +++++----- techlibs/xilinx/cells_sim.v | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index 9653fe5b8..4d907c7e2 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -3,18 +3,18 @@ # F7BMUX slower than F7AMUX # Inputs: I0 I1 S0 # Outputs: O -F7BMUX 1 1 3 1 +F7BMUX 1 0 3 1 217 223 296 # Inputs: I0 I1 S0 # Outputs: O -MUXF8 2 1 3 1 +MUXF8 2 0 3 1 104 94 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 # Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3 -CARRY4 3 1 10 8 +CARRY4 3 0 10 8 271 536 379 - - - 340 - - - 157 494 465 445 - - 433 469 - - 228 592 540 520 356 - 512 548 292 - @@ -27,13 +27,13 @@ CARRY4 3 1 10 8 # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO -RAM64X1D 4 1 15 2 +RAM64X1D 4 0 15 2 - - - - - - - 124 124 124 124 124 124 - - 124 124 124 124 124 124 - - - - - - 124 - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO -RAM128X1D 5 1 17 2 +RAM128X1D 5 0 17 2 - - - - - - - - 314 314 314 314 314 314 292 - - 347 347 347 347 347 347 296 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 29c79f689..db47b4230 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -159,12 +159,12 @@ module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule -(* abc_box_id = 1, lib_whitebox *) +(* abc_box_id = 1 /*, lib_whitebox*/ *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule -(* abc_box_id = 2, lib_whitebox *) +(* abc_box_id = 2 /*, lib_whitebox*/ *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule @@ -173,7 +173,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, lib_whitebox *) +(* abc_box_id = 3 /*, lib_whitebox*/ *) module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; @@ -281,7 +281,7 @@ module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4, lib_whitebox *) +(* abc_box_id = 4 /*, lib_whitebox*/ *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -301,7 +301,7 @@ module RAM64X1D ( `endif endmodule -(* abc_box_id = 5, lib_whitebox *) +(* abc_box_id = 5 /*, lib_whitebox*/ *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 3c8368454f5f9643425bab0065158587b03e2716 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 14:14:13 -0700 Subject: [PATCH 271/514] Fix "a" connectivity --- backends/aiger/xaiger.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 618a6500d..6cf0cb026 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -398,8 +398,25 @@ struct XAigerWriter } init_map.sort(); - input_bits.sort(); - output_bits.sort(); + if (holes_mode) { +#ifndef NDEBUG + RTLIL::SigBit last_bit; + for (auto bit : input_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } + last_bit = RTLIL::SigBit(); + for (auto bit : output_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } +#endif + } + else { + input_bits.sort(); + output_bits.sort(); + } + not_map.sort(); ff_map.sort(); and_map.sort(); @@ -415,7 +432,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -672,6 +689,7 @@ struct XAigerWriter holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); + int port_id = 1; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -691,6 +709,8 @@ struct XAigerWriter if (!holes_wire) { holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); } if (holes_cell) port_wire.append(holes_wire); @@ -706,6 +726,8 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); if (holes_cell) port_wire.append(holes_wire); else @@ -734,7 +756,9 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - holes_module->fixup_ports(); + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); holes_module->design->selection_stack.emplace_back(false); RTLIL::Selection& sel = holes_module->design->selection_stack.back(); @@ -750,7 +774,8 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + //TODO: clean will mess up port_ids + //Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); From 03b289a851c62eb2a7e3592432876bfa8a56770b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 11:38:52 -0700 Subject: [PATCH 272/514] Add 'cinput' and 'coutput' to symbols file for boxes --- backends/aiger/xaiger.cc | 58 +++++++++++++++-------------------- frontends/aiger/aigerparse.cc | 35 +++++++++++++++++++++ passes/techmap/abc9.cc | 25 ++++++++++----- 3 files changed, 77 insertions(+), 41 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6cf0cb026..582e8e076 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -49,7 +49,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; //pool initstate_bits; - vector> ci_bits, co_bits; + vector> ci_bits; + vector> co_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -327,6 +328,7 @@ struct XAigerWriter // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { + int offset = 0; for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); @@ -335,11 +337,11 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.emplace_back(b, 0); + co_bits.emplace_back(b, cell, c.first, offset++, 0); } if (is_output) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, cell, c.first, offset++); } } } @@ -380,7 +382,7 @@ struct XAigerWriter // Do some CI/CO post-processing: // CIs cannot be undriven for (const auto &c : ci_bits) - undriven_bits.erase(c.first); + undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) @@ -399,18 +401,13 @@ struct XAigerWriter init_map.sort(); if (holes_mode) { -#ifndef NDEBUG - RTLIL::SigBit last_bit; - for (auto bit : input_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } - last_bit = RTLIL::SigBit(); - for (auto bit : output_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } -#endif + 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()); } else { input_bits.sort(); @@ -431,8 +428,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; - c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[std::get<0>(c)] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -496,9 +492,9 @@ struct XAigerWriter // aig_latchin.push_back(1); for (auto &c : co_bits) { - RTLIL::SigBit bit = c.first; - c.second = aig_o++; - ordered_outputs[bit] = c.second; + RTLIL::SigBit bit = std::get<0>(c); + std::get<4>(c) = aig_o++; + ordered_outputs[bit] = std::get<4>(c); aig_outputs.push_back(bit2aig(bit)); } @@ -774,8 +770,7 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - //TODO: clean will mess up port_ids - //Pass::call(holes_module->design, "clean -purge"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -880,22 +875,17 @@ struct XAigerWriter } for (const auto &c : ci_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int i = b.offset; + RTLIL::SigBit b = std::get<0>(c); + int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } for (const auto &c : co_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int o = c.second; - if (wire) - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); - else - output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); + int i = std::get<3>(c); + int o = std::get<4>(c); + output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } input_lines.sort(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 94bfdfa3e..2441ee937 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -704,6 +704,41 @@ void AigerReader::post_process() } } } + else if (type == "cinput" || type == "coutput") { + RTLIL::Wire* wire; + if (type == "cinput") { + log_assert(static_cast(variable) < inputs.size()); + wire = inputs[variable]; + log_assert(wire); + log_assert(wire->port_input); + } + else if (type == "coutput") { + log_assert(static_cast(variable) < outputs.size()); + wire = outputs[variable]; + log_assert(wire); + log_assert(wire->port_output); + } + else log_abort(); + + std::string port; + mf >> port; + RTLIL::IdString cell_name = RTLIL::escape_id(symbol); + RTLIL::IdString cell_port = RTLIL::escape_id(port); + + RTLIL::Cell* cell = module->cell(cell_name); + if (!cell) + cell = module->addCell(cell_name, "$__blackbox__"); + wire->port_input = false; + wire->port_output = false; + if (cell->hasPort(cell_port)) { + log_assert(index == GetSize(cell->getPort(cell_port))); + cell->connections_[cell_port].append(wire); + } + else { + log_assert(index == 0); + cell->setPort(cell_port, wire); + } + } else log_error("Symbol type '%s' not recognised.\n", type.c_str()); } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8341741fa..89e3eb948 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -786,14 +786,24 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; } - if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { - SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; - SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; - module->connect(my_y, my_a); - continue; + RTLIL::Cell* cell; + if (c->type == "$lut") { + if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { + SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; + SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; + module->connect(my_y, my_a); + continue; + } + else { + cell = module->addCell(remap_name(c->name), c->type); + } + } + else { + cell = module->cell(c->name); + log_assert(cell); + log_assert(c->type == "$__blackbox__"); } - RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->parameters = c->parameters; for (auto &conn : c->connections()) { @@ -802,7 +812,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (c.width == 0) continue; //log_assert(c.width == 1); - c.wire = module->wires_[remap_name(c.wire->name)]; + if (c.wire) + c.wire = module->wires_[remap_name(c.wire->name)]; newsig.append(c); } cell->setPort(conn.first, newsig); From 234156c01a4086a69ff9ac9f6ae668d64734d525 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:16:10 -0700 Subject: [PATCH 273/514] Instantiate cell type (from sym file) otherwise 'clean' warnings --- backends/aiger/xaiger.cc | 6 ++++-- frontends/aiger/aigerparse.cc | 9 ++++++--- passes/techmap/abc9.cc | 12 +++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582e8e076..3c96f6c9e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -879,13 +879,15 @@ struct XAigerWriter int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } for (const auto &c : co_bits) { int i = std::get<3>(c); int o = std::get<4>(c); - output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } input_lines.sort(); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 2441ee937..6c174871b 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -720,14 +720,17 @@ void AigerReader::post_process() } else log_abort(); - std::string port; - mf >> port; + std::string port, type; + mf >> port >> type; RTLIL::IdString cell_name = RTLIL::escape_id(symbol); RTLIL::IdString cell_port = RTLIL::escape_id(port); + RTLIL::IdString cell_type = RTLIL::escape_id(type); RTLIL::Cell* cell = module->cell(cell_name); if (!cell) - cell = module->addCell(cell_name, "$__blackbox__"); + cell = module->addCell(cell_name, cell_type); + else + log_assert(cell->type == cell_type); wire->port_input = false; wire->port_output = false; if (cell->hasPort(cell_port)) { diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 89e3eb948..475508e02 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -535,18 +535,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); bool builtin_lib = liberty_file.empty(); - RTLIL::Design *mapped_design = new RTLIL::Design; //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); - AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); + log_assert(!design->module("$__abc9__")); + AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); reader.parse_xaiger(); ifs.close(); log_header(design, "Re-integrating ABC9 results.\n"); - RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; + RTLIL::Module *mapped_mod = design->module("$__abc9__"); if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `netlist'.\n"); + log_error("ABC output file does not contain a module `$__abc9__'.\n"); pool output_bits; for (auto &it : mapped_mod->wires_) { @@ -801,7 +801,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri else { cell = module->cell(c->name); log_assert(cell); - log_assert(c->type == "$__blackbox__"); + log_assert(c->type == cell->type); } if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; @@ -937,8 +937,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); log("ABC RESULTS: output signals: %8d\n", out_wires); - - delete mapped_design; } //else //{ From bf3b8d5e45771a543c2481dee5b1b3a9aba0881e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:19:21 -0700 Subject: [PATCH 274/514] Remove mapped_mod when done --- passes/techmap/abc9.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 475508e02..acbab959e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -937,6 +937,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); log("ABC RESULTS: output signals: %8d\n", out_wires); + + design->remove(mapped_mod); } //else //{ From 75bd41eaeb43ec7a25f0b27ff0cdf3be361446f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:22:05 -0700 Subject: [PATCH 275/514] Parse without wideports --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index acbab959e..a2948548d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -538,7 +538,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //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 */, true /* wideports */); + AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */); reader.parse_xaiger(); ifs.close(); From e115e736fa58ff1b3acc5e97897f09efbe112823 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:34:17 -0700 Subject: [PATCH 276/514] parse_xaiger to not parse symbol table --- frontends/aiger/aigerparse.cc | 64 ----------------------------------- 1 file changed, 64 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 6c174871b..a70db6c76 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -219,9 +219,6 @@ void AigerReader::parse_xaiger() unsigned l1; std::string s; bool comment_seen = false; - std::vector> deferred_renames; - std::vector> deferred_inouts; - deferred_renames.reserve(inputs.size() + latches.size() + outputs.size()); for (int c = f.peek(); c != EOF; c = f.peek()) { if (comment_seen || c == 'c') { if (!comment_seen) { @@ -281,71 +278,10 @@ void AigerReader::parse_xaiger() break; } } - else if (c == 'i' || c == 'l' || c == 'o') { - f.ignore(1); - if (!(f >> l1 >> s)) - log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); - - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %u has invalid symbol position!\n", line_count); - - RTLIL::Wire* wire; - if (c == 'i') wire = inputs[l1]; - else if (c == 'l') wire = latches[l1]; - else if (c == 'o') wire = outputs[l1]; - else log_abort(); - - RTLIL::IdString escaped_s = RTLIL::escape_id(s); - - if (escaped_s.ends_with("$inout.out")) { - deferred_inouts.emplace_back(wire, escaped_s.substr(0, escaped_s.size()-10)); - goto next_line; - } - else if (wideports && (wire->port_input || wire->port_output)) { - RTLIL::IdString wide_symbol; - int index; - std::tie(wide_symbol,index) = wideports_split(escaped_s.str()); - if (wide_symbol.ends_with("$inout.out")) { - deferred_inouts.emplace_back(wire, stringf("%s[%d]", wide_symbol.substr(0, wide_symbol.size()-10).c_str(), index)); - goto next_line; - } - } - deferred_renames.emplace_back(wire, escaped_s); - -next_line: - std::getline(f, line); // Ignore up to start of next line - ++line_count; - } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); } - dict wideports_cache; - for (const auto &i : deferred_renames) { - RTLIL::Wire *wire = i.first; - - module->rename(wire, i.second); - - if (wideports && (wire->port_input || wire->port_output)) { - RTLIL::IdString escaped_symbol; - int index; - std::tie(escaped_symbol,index) = wideports_split(wire->name.str()); - if (index > 0) - wideports_cache[escaped_symbol] = std::max(wideports_cache[escaped_symbol], index); - } - } - - for (const auto &i : deferred_inouts) { - RTLIL::Wire *out_wire = i.first; - log_assert(out_wire->port_output); - out_wire->port_output = false; - RTLIL::Wire *wire = module->wire(i.second); - log_assert(wire); - log_assert(wire->port_input && !wire->port_output); - wire->port_output = true; - module->connect(wire, out_wire); - } - post_process(); } From 428d7c8e11db3aa4d65b0509946a47b005f87988 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 13:49:42 -0700 Subject: [PATCH 277/514] Remove unused function --- frontends/aiger/aigerparse.cc | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a70db6c76..66b27fdd8 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -162,29 +162,6 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } -static std::pair 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::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1)); - -failed: - return std::pair(name, 0); -} - void AigerReader::parse_xaiger() { std::string header; From 4df37c77fdb709e67528cf6fe1a2cf52b004c156 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 19:40:27 -0700 Subject: [PATCH 278/514] Disconnect all ABC boxes too --- passes/techmap/abc9.cc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a2948548d..10c795525 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -867,21 +867,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - // Go through all AND and NOT output connections, - // and for those output ports driving wires - // also driven by mapped_mod, disconnect them + // Go through all AND, NOT, and ABC box instances, + // and disconnect their output connections in + // preparation for stitching mapped_mod in for (auto cell : module->cells()) { - if (!cell->type.in("$_AND_", "$_NOT_")) - continue; + if (!cell->type.in("$_AND_", "$_NOT_")) { + RTLIL::Module* cell_module = design->module(cell->type); + if (!cell_module || !cell_module->attributes.count("\\abc_box_id")) + continue; + } for (auto &it : cell->connections_) { auto port_name = it.first; if (!cell->output(port_name)) continue; - auto &signal = it.second; - auto bits = signal.bits(); - for (auto &b : bits) - if (output_bits.count(b)) - b = module->addWire(NEW_ID); - signal = std::move(bits); + it.second = RTLIL::SigSpec(); } } // Do the same for module connections From 54e28eb3ea8bd79c55397d2f53771991039c7eed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:08:55 -0700 Subject: [PATCH 279/514] Re-enable lib_whitebox --- techlibs/xilinx/cells_sim.v | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index db47b4230..29c79f689 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -159,12 +159,12 @@ module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule -(* abc_box_id = 1 /*, lib_whitebox*/ *) +(* abc_box_id = 1, lib_whitebox *) module MUXF7(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule -(* abc_box_id = 2 /*, lib_whitebox*/ *) +(* abc_box_id = 2, lib_whitebox *) module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule @@ -173,7 +173,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3 /*, lib_whitebox*/ *) +(* abc_box_id = 3, lib_whitebox *) module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; @@ -281,7 +281,7 @@ module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4 /*, lib_whitebox*/ *) +(* abc_box_id = 4, lib_whitebox *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -301,7 +301,7 @@ module RAM64X1D ( `endif endmodule -(* abc_box_id = 5 /*, lib_whitebox*/ *) +(* abc_box_id = 5, lib_whitebox *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From e032e5bcde1c9e975c6947c27495b3049cd51737 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:09:06 -0700 Subject: [PATCH 280/514] Make MUXF{7,8} and CARRY4 whitebox --- techlibs/xilinx/abc.box | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index 4d907c7e2..b3972ddb3 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -3,18 +3,18 @@ # F7BMUX slower than F7AMUX # Inputs: I0 I1 S0 # Outputs: O -F7BMUX 1 0 3 1 +F7BMUX 1 1 3 1 217 223 296 # Inputs: I0 I1 S0 # Outputs: O -MUXF8 2 0 3 1 +MUXF8 2 1 3 1 104 94 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 # Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3 -CARRY4 3 0 10 8 +CARRY4 3 1 10 8 271 536 379 - - - 340 - - - 157 494 465 445 - - 433 469 - - 228 592 540 520 356 - 512 548 292 - From 3f60061615a8b5df3ad05b997407f195c8197754 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:10:59 -0700 Subject: [PATCH 281/514] Map file to include boxes not CI/CO --- backends/aiger/xaiger.cc | 83 ++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3c96f6c9e..2bc059dc5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -304,48 +304,52 @@ struct XAigerWriter // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires - for (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + auto it = cell->connections_.find(port_name); if (w->port_input) { - auto it = cell->connections_.find(w->name); + RTLIL::SigSpec rhs; if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + cell->setPort(port_name, rhs); + } + + int offset = 0; + for (const auto &b : rhs.bits()) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, cell, port_name, offset++, 0); } - else - cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); } if (w->port_output) { + RTLIL::SigSpec rhs; auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + rhs = module->addWire(NEW_ID, GetSize(w)); + cell->setPort(port_name, rhs); } - else - cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); - } - } - // Box ordering is alphabetical - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - int offset = 0; - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - co_bits.emplace_back(b, cell, c.first, offset++, 0); - } - if (is_output) { + int offset = 0; + for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, c.first, offset++); + ci_bits.emplace_back(O, cell, port_name, offset++); } } } - box_list.emplace_back(cell); } @@ -686,6 +690,7 @@ struct XAigerWriter log_assert(holes_module); int port_id = 1; + int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -737,7 +742,7 @@ struct XAigerWriter write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(0 /* OldBoxNum */); + write_h_buffer(box_count++); } f << "h"; @@ -844,7 +849,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); continue; } @@ -874,35 +879,23 @@ struct XAigerWriter } } - for (const auto &c : ci_bits) { - RTLIL::SigBit b = std::get<0>(c); - int i = std::get<3>(c); - int a = bit2aig(b); - log_assert((a & 1) == 0); - RTLIL::Cell* cell = std::get<1>(c); - input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - - for (const auto &c : co_bits) { - int i = std::get<3>(c); - int o = std::get<4>(c); - RTLIL::Cell* cell = std::get<1>(c); - output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - input_lines.sort(); for (auto &it : input_lines) f << it.second; - log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); + log_assert(input_lines.size() == input_bits.size()); init_lines.sort(); for (auto &it : init_lines) f << it.second; + int box_count = 0; + for (auto cell : box_list) + f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); + output_lines.sort(); for (auto &it : output_lines) f << it.second; - log_assert(output_lines.size() == output_bits.size() + co_bits.size()); + log_assert(output_lines.size() == output_bits.size()); if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; From 3eec100748c195eb60efcbd789b94d915d5cc260 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:11:21 -0700 Subject: [PATCH 282/514] Parse "a" extension and boxes from map file --- frontends/aiger/aigerparse.cc | 101 ++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 66b27fdd8..e8a355671 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -192,8 +192,15 @@ void AigerReader::parse_xaiger() else log_abort(); + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find("\\abc_box_id"); + if (it == m->attributes.end()) + continue; + box_lookup[it->second.as_int()] = m->name; + } + // Parse footer (symbol table, comments, etc.) - unsigned l1; std::string s; bool comment_seen = false; for (int c = f.peek(); c != EOF; c = f.peek()) { @@ -247,7 +254,21 @@ void AigerReader::parse_xaiger() f >> s; log_debug("n: '%s'\n", s.c_str()); } - else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') { + else if (c == 'h') { + f.ignore(sizeof(uint32_t)); + uint32_t version = parse_xaiger_literal(f); + log_assert(version == 1); + f.ignore(4*sizeof(uint32_t)); + uint32_t boxNum = parse_xaiger_literal(f); + for (unsigned i = 0; i < boxNum; i++) { + f.ignore(2*sizeof(uint32_t)); + uint32_t boxUniqueId = parse_xaiger_literal(f); + log_assert(boxUniqueId > 0); + uint32_t oldBoxNum = parse_xaiger_literal(f); + module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + } + } + else if (c == 'a' || c == 'i' || c == 'o') { uint32_t dataSize = parse_xaiger_literal(f); f.ignore(dataSize); } @@ -471,7 +492,7 @@ void AigerReader::parse_aiger_binary() log_debug("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? wire = module->wire(wire_name); if (!wire) wire = createWireIfNotExists(module, l1); @@ -527,6 +548,7 @@ void AigerReader::post_process() std::ifstream mf(map_filename); std::string type, symbol; int variable, index; + int pi_count = 0, ci_count = 0, co_count = 0; while (mf >> type >> variable >> index >> symbol) { RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); if (type == "input") { @@ -534,6 +556,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = inputs[variable]; log_assert(wire); log_assert(wire->port_input); + pi_count++; if (index == 0) { // Cope with the fact that a CI might be identical @@ -562,8 +585,8 @@ void AigerReader::post_process() } } else if (type == "output") { - log_assert(static_cast(variable) < outputs.size()); - RTLIL::Wire* wire = outputs[variable]; + log_assert(static_cast(variable + co_count) < outputs.size()); + RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { @@ -617,42 +640,38 @@ void AigerReader::post_process() } } } - else if (type == "cinput" || type == "coutput") { - RTLIL::Wire* wire; - if (type == "cinput") { - log_assert(static_cast(variable) < inputs.size()); - wire = inputs[variable]; - log_assert(wire); - log_assert(wire->port_input); - } - else if (type == "coutput") { - log_assert(static_cast(variable) < outputs.size()); - wire = outputs[variable]; - log_assert(wire); - log_assert(wire->port_output); - } - else log_abort(); - - std::string port, type; - mf >> port >> type; - RTLIL::IdString cell_name = RTLIL::escape_id(symbol); - RTLIL::IdString cell_port = RTLIL::escape_id(port); - RTLIL::IdString cell_type = RTLIL::escape_id(type); - - RTLIL::Cell* cell = module->cell(cell_name); - if (!cell) - cell = module->addCell(cell_name, cell_type); - else - log_assert(cell->type == cell_type); - wire->port_input = false; - wire->port_output = false; - if (cell->hasPort(cell_port)) { - log_assert(index == GetSize(cell->getPort(cell_port))); - cell->connections_[cell_port].append(wire); - } - else { - log_assert(index == 0); - cell->setPort(cell_port, wire); + else if (type == "box") { + RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); + if (cell) { + module->rename(cell, escaped_s); + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (auto port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + RTLIL::SigSpec rhs; + for (int i = 0; i < GetSize(w); i++) { + if (w->port_input) { + log_assert(static_cast(co_count) < outputs.size()); + RTLIL::Wire* wire = outputs[co_count++]; + log_assert(wire); + log_assert(wire->port_output); + wire->port_output = false; + rhs.append(wire); + } + if (w->port_output) { + log_assert(static_cast(pi_count + ci_count) < inputs.size()); + RTLIL::Wire* wire = inputs[pi_count + ci_count++]; + log_assert(wire); + log_assert(wire->port_input); + wire->port_input = false; + rhs.append(wire); + } + } + cell->setPort(port_name, rhs); + } } } else From 89bd6b85045b371c1088004d8e4af0dd78a3981d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:12:21 -0700 Subject: [PATCH 283/514] If driver not found, use LUT2 --- passes/techmap/abc9.cc | 56 ++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 10c795525..1b45085be 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -588,30 +588,34 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); if (!lut_costs.empty() || !lut_file.empty()) { + RTLIL::Cell* driving_lut = nullptr; // ABC can return NOT gates that drive POs - if (a_bit.wire->port_input) { - // If it's a NOT gate that comes from a primary input directly - // then implement it using a LUT - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - 1); - } - else { - // Otherwise, clone the driving LUT to guarantee that we - // won't increase the max logic depth + if (!a_bit.wire->port_input) { + // If it's not a NOT gate that that comes from a PI directly, + // find the driving LUT and clone that to guarantee that we won't + // increase the max logic depth // (TODO: Optimise by not cloning unless will increase depth) RTLIL::IdString driver_name; if (GetSize(a_bit.wire) == 1) driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); else driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - RTLIL::Cell* driver = mapped_mod->cell(driver_name); - log_assert(driver); - auto driver_a = driver->getPort("\\A").chunks(); + driving_lut = mapped_mod->cell(driver_name); + } + + if (!driving_lut) { + // If a driver couldn't be found (could be from PI, + // or from a box) then implement using a LUT + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + 1); + } + else { + auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - RTLIL::Const driver_lut = driver->getParam("\\LUT"); + RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); for (auto &b : driver_lut.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; @@ -867,20 +871,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - // Go through all AND, NOT, and ABC box instances, - // and disconnect their output connections in - // preparation for stitching mapped_mod in - for (auto cell : module->cells()) { - if (!cell->type.in("$_AND_", "$_NOT_")) { - RTLIL::Module* cell_module = design->module(cell->type); - if (!cell_module || !cell_module->attributes.count("\\abc_box_id")) - continue; - } - for (auto &it : cell->connections_) { - auto port_name = it.first; - if (!cell->output(port_name)) continue; - it.second = RTLIL::SigSpec(); - } + // Remove all AND, NOT, instances + // in preparation for stitching mapped_mod in + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { + RTLIL::Cell* cell = it->second; + if (cell->type.in("$_AND_", "$_NOT_")) + it = module->cells_.erase(it); + else + ++it; } // Do the same for module connections for (auto &it : module->connections_) { From 4a76b425cc0588ef5a8e46c06eecbfab869a35d9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 08:44:59 -0700 Subject: [PATCH 284/514] Misspell --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1b45085be..328f0e3c3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -567,7 +567,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // Attempt another wideports_split here because there // exists the possibility that different bits of a port - // could be an input and output, therefore parse_xiager() + // 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); From f745727de5af085412b2e5f8161aa1018cc5e276 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 08:45:10 -0700 Subject: [PATCH 285/514] read_aiger to only clean own design --- frontends/aiger/aigerparse.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e8a355671..8d7588f88 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -722,8 +722,14 @@ void AigerReader::post_process() module->fixup_ports(); design->add(module); + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + Pass::call(design, "clean"); + design->selection_stack.pop_back(); + for (auto cell : module->cells().to_vector()) { if (cell->type != "$lut") continue; auto y_port = cell->getPort("\\Y").as_bit(); From 6931a3a47da5119ac44449ef117f3985e2fda417 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:32:18 -0700 Subject: [PATCH 286/514] Update README.md from master --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e6be0f37e..19306cda3 100644 --- a/README.md +++ b/README.md @@ -366,7 +366,7 @@ Verilog Attributes and non-standard features - When defining a macro with `define, all text between triple double quotes is interpreted as macro body, even if it contains unescaped newlines. The - tipple double quotes are removed from the macro body. For example: + triple double quotes are removed from the macro body. For example: `define MY_MACRO(a, b) """ assign a = 23; @@ -459,7 +459,7 @@ Non-standard or SystemVerilog features for formal verification supported in any clocked block. - The syntax ``@($global_clock)`` can be used to create FFs that have no - explicit clock input ($ff cells). The same can be achieved by using + explicit clock input (``$ff`` cells). The same can be achieved by using ``@(posedge )`` or ``@(negedge )`` when ```` is marked with the ``(* gclk *)`` Verilog attribute. @@ -472,7 +472,7 @@ from SystemVerilog: - The ``assert`` statement from SystemVerilog is supported in its most basic form. In module context: ``assert property ();`` and within an - always block: ``assert();``. It is transformed to a $assert cell. + always block: ``assert();``. It is transformed to an ``$assert`` cell. - The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are also supported. The same limitations as with the ``assert`` statement apply. From 914074a07c14709523cc72084e1673bd3c2eaf30 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:35:45 -0700 Subject: [PATCH 287/514] Update from master --- backends/json/json.cc | 115 ++++++++++++++++++++---------------------- kernel/cellaigs.cc | 2 +- kernel/celltypes.h | 2 +- passes/opt/wreduce.cc | 2 - passes/sat/expose.cc | 2 +- 5 files changed, 59 insertions(+), 64 deletions(-) diff --git a/backends/json/json.cc b/backends/json/json.cc index b4f82a3fe..f5c687981 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -130,75 +130,72 @@ struct JsonWriter f << stringf(" }"); first = false; } - f << stringf("\n }"); + f << stringf("\n },\n"); - if (!module->get_blackbox_attribute()) { - f << stringf(",\n \"cells\": {"); - first = true; - for (auto c : module->cells()) { - if (use_selection && !module->selected(c)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); - f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); - if (aig_mode) { - Aig aig(c); - if (!aig.name.empty()) { - f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); - aig_models.insert(aig); - } + f << stringf(" \"cells\": {"); + first = true; + for (auto c : module->cells()) { + if (use_selection && !module->selected(c)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type).c_str()); + if (aig_mode) { + Aig aig(c); + if (!aig.name.empty()) { + f << stringf(" \"model\": \"%s\",\n", aig.name.c_str()); + aig_models.insert(aig); } - f << stringf(" \"parameters\": {"); - write_parameters(c->parameters); - f << stringf("\n },\n"); - f << stringf(" \"attributes\": {"); - write_parameters(c->attributes); - f << stringf("\n },\n"); - if (c->known()) { - f << stringf(" \"port_directions\": {"); - bool first2 = true; - for (auto &conn : c->connections()) { - string direction = "output"; - if (c->input(conn.first)) - direction = c->output(conn.first) ? "inout" : "input"; - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); - first2 = false; - } - f << stringf("\n },\n"); - } - f << stringf(" \"connections\": {"); + } + f << stringf(" \"parameters\": {"); + write_parameters(c->parameters); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(c->attributes); + f << stringf("\n },\n"); + if (c->known()) { + f << stringf(" \"port_directions\": {"); bool first2 = true; for (auto &conn : c->connections()) { + string direction = "output"; + if (c->input(conn.first)) + direction = c->output(conn.first) ? "inout" : "input"; f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str()); first2 = false; } - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf("\n },\n"); } - f << stringf("\n },\n"); - - f << stringf(" \"netnames\": {"); - first = true; - for (auto w : module->wires()) { - if (use_selection && !module->selected(w)) - continue; - f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(w->name).c_str()); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); - f << stringf(" \"attributes\": {"); - write_parameters(w->attributes); - f << stringf("\n }\n"); - f << stringf(" }"); - first = false; + f << stringf(" \"connections\": {"); + bool first2 = true; + for (auto &conn : c->connections()) { + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str()); + first2 = false; } - f << stringf("\n }"); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; } - f << stringf("\n"); + f << stringf("\n },\n"); + + f << stringf(" \"netnames\": {"); + first = true; + for (auto w : module->wires()) { + if (use_selection && !module->selected(w)) + continue; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": %s,\n", get_bits(w).c_str()); + f << stringf(" \"attributes\": {"); + write_parameters(w->attributes); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + f << stringf("\n }\n"); f << stringf(" }"); } diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc index 5fd76afe5..26c625f89 100644 --- a/kernel/cellaigs.cc +++ b/kernel/cellaigs.cc @@ -453,7 +453,7 @@ Aig::Aig(Cell *cell) int B = mk.inport("\\B"); int C = mk.inport("\\C"); int D = mk.inport("\\D"); - int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D)); + int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D)); mk.outport(Y, "\\Y"); goto optimize; } diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 89df36222..4e91eddda 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -469,7 +469,7 @@ struct CellTypes if (cell->type == "$_AOI4_") return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); if (cell->type == "$_OAI4_") - return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); + return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1)); log_assert(arg4.bits.size() == 0); return eval(cell, arg1, arg2, arg3, errp); diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index cfe4b4067..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -465,12 +465,10 @@ struct WreduceWorker SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) { - log_dump(initsig[i], remove_init_bits.count(initsig[i])); if (!remove_init_bits.count(initsig[i])) new_initval[i] = initval[i]; } w->attributes.at("\\init") = new_initval; - log_dump(w->name, initval, new_initval); } } } diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 50ab38063..71ce1683d 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -42,7 +42,7 @@ struct dff_map_bit_info_t { bool consider_wire(RTLIL::Wire *wire, std::map &dff_dq_map) { - if (/*wire->name[0] == '$' ||*/ dff_dq_map.count(wire->name)) + if (wire->name[0] == '$' || dff_dq_map.count(wire->name)) return false; if (wire->port_input) return false; From f228621b80d727b4dc1d7a9b3b934c1fbc170642 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:36:01 -0700 Subject: [PATCH 288/514] Typo --- techlibs/xilinx/cells_xtra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index e3b847c36..2b384f405 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -125,7 +125,7 @@ function xtract_cell_decl() xtract_cell_decl RAM32X1S_1 xtract_cell_decl RAM32X2S xtract_cell_decl RAM64M - x#tract_cell_decl RAM64X1D + #xtract_cell_decl RAM64X1D xtract_cell_decl RAM64X1S xtract_cell_decl RAM64X1S_1 xtract_cell_decl RAM64X2S From cdedf51c326122a3154a587e3784bbf5a5b4e727 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:37:50 -0700 Subject: [PATCH 289/514] From master --- passes/pmgen/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index d0711c730..2f0b1fd5a 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -232,5 +232,5 @@ But in some cases it is more natural to utilize the implicit branch statement: portAB = \B; endcode -There is an implicit `code..endcode` block at the end of each `.pgm` file +There is an implicit `code..endcode` block at the end of each `.pmg` file that just accepts everything that gets all the way there. From 5f39c262c278f90f6bbb55d5969b970230876ef5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 09:38:58 -0700 Subject: [PATCH 290/514] From master --- tests/tools/autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 1825990a9..920474a84 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -132,13 +132,13 @@ do fn=$(basename $fn) bn=$(basename $bn) + rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} else "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} frontend="verilog -noblackbox" fi - rm -f ${bn}_ref.fir if [ ! -f ../${bn}_tb.v ]; then "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v From 13e233217cd0caceeb5d30d2eefa5238ffc5bfc9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 11:29:59 -0700 Subject: [PATCH 291/514] Small improvement --- backends/aiger/xaiger.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2bc059dc5..5919b2302 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -328,6 +328,7 @@ struct XAigerWriter if (I != b) alias_map[b] = I; co_bits.emplace_back(b, cell, port_name, offset++, 0); + unused_bits.erase(b); } } if (w->port_output) { @@ -347,6 +348,7 @@ struct XAigerWriter for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); ci_bits.emplace_back(O, cell, port_name, offset++); + undriven_bits.erase(O); } } } @@ -383,10 +385,6 @@ struct XAigerWriter } } - // Do some CI/CO post-processing: - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) From b4321a31bbd9f215e753563d5d031b2c24f1b371 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 12:42:17 -0700 Subject: [PATCH 292/514] Fix for abc9_test022 --- backends/aiger/xaiger.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5919b2302..2ffd460dd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -277,8 +277,10 @@ struct XAigerWriter } } if (is_output) { + input_bits.insert(b); SigBit O = sigmap(b); - input_bits.insert(O); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } @@ -346,8 +348,10 @@ struct XAigerWriter int offset = 0; for (const auto &b : rhs.bits()) { + ci_bits.emplace_back(b, cell, port_name, offset++); SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, port_name, offset++); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } From 92197326b8fa406e94c952cfcb778611642a3e00 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 12:43:07 -0700 Subject: [PATCH 293/514] Add abc9_test022 --- tests/simple_abc9/abc9.v | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index fb5b759fb..e666d1a6a 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -143,6 +143,7 @@ assign b = ~a; always @* d <= &c; endmodule +// Citation: https://github.com/alexforencich/verilog-ethernet module abc9_test021(clk, rst, s_eth_hdr_valid, s_eth_hdr_ready, s_eth_dest_mac, s_eth_src_mac, s_eth_type, s_eth_payload_axis_tdata, s_eth_payload_axis_tkeep, s_eth_payload_axis_tvalid, s_eth_payload_axis_tready, s_eth_payload_axis_tlast, s_eth_payload_axis_tid, s_eth_payload_axis_tdest, s_eth_payload_axis_tuser, m_eth_hdr_valid, m_eth_hdr_ready, m_eth_dest_mac, m_eth_src_mac, m_eth_type, m_eth_payload_axis_tdata, m_eth_payload_axis_tkeep, m_eth_payload_axis_tvalid, m_eth_payload_axis_tready, m_eth_payload_axis_tlast, m_eth_payload_axis_tid, m_eth_payload_axis_tdest, m_eth_payload_axis_tuser); input clk; output [47:0] m_eth_dest_mac; @@ -215,3 +216,24 @@ endmodule (* abc_box_id=1 *) module MUXF8(input I0, I1, S, output O); endmodule + +// Citation: https://github.com/alexforencich/verilog-ethernet +// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test022" abc9.v -q +// returns before b4321a31 +// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [7] is used but has no +// driver. +// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [3] is used but has no +// driver. +module abc9_test022 +( + input wire clk, + input wire i, + output wire [7:0] m_eth_payload_axis_tkeep +); + +reg [7:0] m_eth_payload_axis_tkeep_reg = 8'd0; +assign m_eth_payload_axis_tkeep = m_eth_payload_axis_tkeep_reg; +always @(posedge clk) + m_eth_payload_axis_tkeep_reg <= i ? 8'hff : 8'h0f; + +endmodule From ecaa7856e96dad8de5ef162bb1c9c5814de5254f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:21:41 -0700 Subject: [PATCH 294/514] Add some debug to abc9 --- passes/techmap/abc9.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 328f0e3c3..41ab9abea 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -423,6 +423,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); +#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 + design->selection_stack.pop_back(); // Now 'unexpose' those wires by undoing @@ -540,9 +555,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_assert(!design->module("$__abc9__")); AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */); reader.parse_xaiger(); - ifs.close(); +#if 0 + Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "output.v")); +#endif + log_header(design, "Re-integrating ABC9 results.\n"); RTLIL::Module *mapped_mod = design->module("$__abc9__"); if (mapped_mod == NULL) From 1423384367d4fa31f09c6c7b69c1b89edc3dd066 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:24:09 -0700 Subject: [PATCH 295/514] Fix abc_test024 --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2ffd460dd..bf696bfd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,10 +152,11 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - if (wire->port_input) - input_bits.insert(bit); - else if (keep) + if (wire->port_input || keep) { + if (bit != wirebit) + alias_map[bit] = wirebit; input_bits.insert(wirebit); + } if (wire->port_output || keep) { if (bit != wirebit) @@ -166,7 +167,7 @@ struct XAigerWriter } for (auto bit : input_bits) - undriven_bits.erase(bit); + undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) if (!bit.wire->port_input) From aa2380c17a7c97d4c3835cd6d78310cf4961c4f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:24:38 -0700 Subject: [PATCH 296/514] Add abc_test024 --- tests/simple_abc9/abc9.v | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index e666d1a6a..7af2ace01 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -230,10 +230,23 @@ module abc9_test022 input wire i, output wire [7:0] m_eth_payload_axis_tkeep ); - -reg [7:0] m_eth_payload_axis_tkeep_reg = 8'd0; -assign m_eth_payload_axis_tkeep = m_eth_payload_axis_tkeep_reg; -always @(posedge clk) - m_eth_payload_axis_tkeep_reg <= i ? 8'hff : 8'h0f; - + reg [7:0] m_eth_payload_axis_tkeep_reg = 8'd0; + assign m_eth_payload_axis_tkeep = m_eth_payload_axis_tkeep_reg; + always @(posedge clk) + m_eth_payload_axis_tkeep_reg <= i ? 8'hff : 8'h0f; +endmodule + +// Citation: https://github.com/riscv/riscv-bitmanip +// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test024" abc9.v -q +// returns before 14233843 +// Warning: Wire abc9_test024.\dout [1] is used but has no driver. +module abc9_test024 #( + parameter integer N = 2, + parameter integer M = 2 +) ( + input [7:0] din, + output [M-1:0] dout +); + wire [2*M-1:0] mask = {M{1'b1}}; + assign dout = (mask << din[N-1:0]) >> M; endmodule From 25befbf5425458cf8cc5ee89635ad7e5f42d5778 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:26:33 -0700 Subject: [PATCH 297/514] Rename to #23 --- tests/simple_abc9/abc9.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 7af2ace01..2752ff8cc 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -237,10 +237,10 @@ module abc9_test022 endmodule // Citation: https://github.com/riscv/riscv-bitmanip -// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test024" abc9.v -q +// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test023" abc9.v -q // returns before 14233843 -// Warning: Wire abc9_test024.\dout [1] is used but has no driver. -module abc9_test024 #( +// Warning: Wire abc9_test023.\dout [1] is used but has no driver. +module abc9_test023 #( parameter integer N = 2, parameter integer M = 2 ) ( From 5e75abf8706971e115166cdc82435201d7a59b1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 16:34:43 -0700 Subject: [PATCH 298/514] Bump ABC --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 05b28f33d..377a5f6b5 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ OBJS = kernel/version_$(GIT_REV).o # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 3709744 +ABCREV = 62487de ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 From b955344ecd01bdeb5d3e4fbb26f274e4bf9bc125 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 16:34:52 -0700 Subject: [PATCH 299/514] Call &if with -W 250 --- passes/techmap/abc9.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 41ab9abea..732fc59d7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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; &ps -l" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if -W 250 -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" @@ -1172,6 +1172,11 @@ struct Abc9Pass : public Pass { vector lut_costs; markgroups = false; +#if 0 + cleanup = false; + show_tempdir = true; +#endif + map_mux4 = false; map_mux8 = false; map_mux16 = false; From 854557814ee2cd3902e5871cb0b559ee375e81c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 19:17:36 -0700 Subject: [PATCH 300/514] Erase all boxes before stitching --- passes/techmap/abc9.cc | 57 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 732fc59d7..2cd599edc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -596,6 +596,33 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + // Remove all AND, NOT, and ABC box instances + // in preparation for stitching mapped_mod in + pool erased_boxes; + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { + RTLIL::Cell* cell = it->second; + if (cell->type.in("$_AND_", "$_NOT_")) { + it = module->cells_.erase(it); + continue; + } + RTLIL::Module* box_module = design->module(cell->type); + if (box_module && box_module->attributes.count("\\abc_box_id")) { + erased_boxes.insert(it->first); + it = module->cells_.erase(it); + continue; + } + ++it; + } + // Do the same for module connections + for (auto &it : module->connections_) { + auto &signal = it.first; + auto bits = signal.bits(); + for (auto &b : bits) + if (output_bits.count(b)) + b = module->addWire(NEW_ID); + signal = std::move(bits); + } + std::map cell_stats; for (auto c : mapped_mod->cells()) { @@ -816,16 +843,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->connect(my_y, my_a); continue; } - else { - cell = module->addCell(remap_name(c->name), c->type); - } - } - else { - cell = module->cell(c->name); - log_assert(cell); - log_assert(c->type == cell->type); } + else + log_assert(erased_boxes.count(c->name)); + cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->parameters = c->parameters; for (auto &conn : c->connections()) { @@ -889,25 +911,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // module->connect(conn); // } - // Remove all AND, NOT, instances - // in preparation for stitching mapped_mod in - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; - if (cell->type.in("$_AND_", "$_NOT_")) - it = module->cells_.erase(it); - else - ++it; - } - // Do the same for module connections - for (auto &it : module->connections_) { - auto &signal = it.first; - auto bits = signal.bits(); - for (auto &b : bits) - if (output_bits.count(b)) - b = module->addWire(NEW_ID); - signal = std::move(bits); - } - // Stitch in mapped_mod's inputs/outputs into module for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; From 276f5f8b811953e79923fe30e85bc34ced88b748 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 22:55:34 -0700 Subject: [PATCH 301/514] Some more realistic delays... --- techlibs/xilinx/abc.lut | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc.lut index 5550a4039..3a7dc268d 100644 --- a/techlibs/xilinx/abc.lut +++ b/techlibs/xilinx/abc.lut @@ -2,13 +2,13 @@ # K area delay 1 1 124 -2 2 124 248 -3 3 124 248 372 -4 3 124 248 372 496 -5 3 124 248 372 496 620 -6 5 124 248 372 496 620 744 +2 2 124 235 +3 3 124 235 399 +4 3 124 235 399 490 +5 3 124 235 399 490 620 +6 5 124 235 399 490 620 632 # F7BMUX -7 10 296 420 544 668 792 916 1040 +7 10 296 420 531 695 756 916 928 # F8MUX # F8MUX+F7BMUX -8 20 273 569 693 817 941 1065 1189 1313 +8 20 273 569 693 804 968 1029 1189 1201 From 2560f92f29af409d69297a3743ade368832e7bfd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 23:01:46 -0700 Subject: [PATCH 302/514] Reduce -W to 160 --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2cd599edc..427aff1b8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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 250 -v; &ps -l" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if -W 160 -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" From 8c58c728a79954603289abf3520139da0a9bbb26 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 00:42:41 -0700 Subject: [PATCH 303/514] Re-enable &dc2 --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 427aff1b8..8966b5c27 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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 160 -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" From fdfc18be91123e2939f134dafc12e1e0c1a82f7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 01:23:36 -0700 Subject: [PATCH 304/514] Carry in/out to be the last input/output for chains to be preserved --- backends/aiger/xaiger.cc | 38 +++++++++++++++++++++++++++++++++++ frontends/aiger/aigerparse.cc | 38 +++++++++++++++++++++++++++++++++++ techlibs/xilinx/abc.box | 23 ++++++++++++--------- techlibs/xilinx/cells_sim.v | 4 ++-- 4 files changed, 91 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf696bfd6..25de7daba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -298,6 +298,8 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); + pool abc_carry_modules; + toposort.sort(); for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); @@ -305,6 +307,42 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; + RTLIL::Wire* last_in = nullptr, *last_out = nullptr; + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_input) { + if (w->attributes.count("\\abc_carry_in")) { + log_assert(!carry_in); + carry_in = w; + } + log_assert(!last_in || last_in->port_id < w->port_id); + last_in = w; + } + if (w->port_output) { + if (w->attributes.count("\\abc_carry_out")) { + log_assert(!carry_out); + carry_out = w; + } + log_assert(!last_out || last_out->port_id < w->port_id); + last_out = w; + } + } + + if (carry_in) { + log_assert(last_in); + std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); + std::swap(carry_in->port_id, last_in->port_id); + } + if (carry_out) { + log_assert(last_out); + std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); + std::swap(carry_out->port_id, last_out->port_id); + } + } + // Fully pad all unused input connections of this box cell with S0 // Fully pad all undriven output connections of this box cell with anonymous wires // NB: Assume box_module->ports are sorted alphabetically diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8d7588f88..915c53a1b 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -549,6 +549,7 @@ void AigerReader::post_process() std::string type, symbol; int variable, index; int pi_count = 0, ci_count = 0, co_count = 0; + pool abc_carry_modules; while (mf >> type >> variable >> index >> symbol) { RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); if (type == "input") { @@ -646,6 +647,43 @@ void AigerReader::post_process() module->rename(cell, escaped_s); RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); + + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; + RTLIL::Wire* last_in = nullptr, *last_out = nullptr; + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_input) { + if (w->attributes.count("\\abc_carry_in")) { + log_assert(!carry_in); + carry_in = w; + } + log_assert(!last_in || last_in->port_id < w->port_id); + last_in = w; + } + if (w->port_output) { + if (w->attributes.count("\\abc_carry_out")) { + log_assert(!carry_out); + carry_out = w; + } + log_assert(!last_out || last_out->port_id < w->port_id); + last_out = w; + } + } + + if (carry_in != last_in) { + std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]); + std::swap(carry_in->port_id, last_in->port_id); + } + if (carry_out != last_out) { + log_assert(last_out); + std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]); + std::swap(carry_out->port_id, last_out->port_id); + } + } + + // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index b3972ddb3..6e9e1faf6 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -12,17 +12,20 @@ MUXF8 2 1 3 1 104 94 273 # CARRY4 + CARRY4_[ABCD]X -# Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 -# Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3 +# Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI +# Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 +# (NB: carry chain input/output must be last input/output, +# swapped with what normally would have been the last +# output, here: CI <-> S, CO <-> O CARRY4 3 1 10 8 -271 536 379 - - - 340 - - - -157 494 465 445 - - 433 469 - - -228 592 540 520 356 - 512 548 292 - -114 580 526 507 398 385 508 528 378 380 -222 482 - - - - 223 - - - -334 598 407 - - - 400 205 - - -239 584 556 537 - - 523 558 226 - -313 642 615 596 438 - 582 618 330 227 +223 - - - 482 - - - - 222 +400 205 - - 598 407 - - - 334 +523 558 226 - 584 556 537 - - 239 +582 618 330 227 642 615 596 438 - 313 +340 - - - 536 379 - - - 271 +433 469 - - 494 465 445 - - 157 +512 548 292 - 592 540 520 356 - 228 +508 528 378 380 580 526 507 398 385 114 # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 29c79f689..120370860 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -173,8 +173,8 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, lib_whitebox *) -module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); +(* abc_box_id = 3, lib_whitebox, abc_carry *) +module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; assign CO[1] = S[1] ? CO[0] : DI[1]; From 0800846e73b6502cfaa2000ea433faa5f1f75a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 11:32:14 -0700 Subject: [PATCH 305/514] Do not double count LUT1s --- passes/techmap/abc9.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8966b5c27..b1bd167a4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -670,7 +670,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); } - cell_stats["$lut"]++; } else { cell = module->addCell(remap_name(c->name), "$_NOT_"); From a44fe3a632f6beafe0ba2831bba06bf855d7e89d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 11:41:50 -0700 Subject: [PATCH 306/514] Revert "Re-enable &dc2" This reverts commit 8c58c728a79954603289abf3520139da0a9bbb26. --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b1bd167a4..82f149c8c 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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 160 -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" From c6fa4faa371ad3dbefe4c57bd758942e461869da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 12:25:21 -0700 Subject: [PATCH 307/514] Remove whitespace --- frontends/aiger/aigerparse.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 915c53a1b..7adfacb53 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -683,7 +683,6 @@ void AigerReader::post_process() } } - // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { From e3c8132d7acaae328adeb8d4db1857275b5e8323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 12:26:51 -0700 Subject: [PATCH 308/514] Do not re-sort box_module ports --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25de7daba..efdd1844b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -739,10 +739,12 @@ struct XAigerWriter if (box_module->get_bool_attribute("\\whitebox")) holes_cell = holes_module->addCell(cell->name, cell->type); - RTLIL::Wire *holes_wire; - // TODO: Only sort once - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; RTLIL::SigSpec port_wire; if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { From 1ad33c3b5ac91fc4e6cb6e2ff4b606a693838c2b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 13:07:29 -0700 Subject: [PATCH 309/514] Remove whitebox attribute from DRAMs for now --- techlibs/xilinx/cells_sim.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 120370860..7337e0ea7 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,7 +281,7 @@ module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4, lib_whitebox *) +(* abc_box_id = 4 /*, lib_whitebox*/ *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -301,7 +301,7 @@ module RAM64X1D ( `endif endmodule -(* abc_box_id = 5, lib_whitebox *) +(* abc_box_id = 5 /*, lib_whitebox*/ *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 4a6b9af227cb22e89fd463c665016544060d2acd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 15:50:47 -0700 Subject: [PATCH 310/514] Fix spelling --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 82f149c8c..4bda388de 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -924,7 +924,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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_xiager() + // 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); From a41553a86125d58a0811975aa8636388615ba239 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 16:02:40 -0700 Subject: [PATCH 311/514] read_xaiger() to name box signals --- frontends/aiger/aigerparse.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7adfacb53..399e46737 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -689,23 +689,27 @@ void AigerReader::post_process() RTLIL::Wire* w = box_module->wire(port_name); log_assert(w); RTLIL::SigSpec rhs; + RTLIL::Wire* wire = nullptr; for (int i = 0; i < GetSize(w); i++) { if (w->port_input) { log_assert(static_cast(co_count) < outputs.size()); - RTLIL::Wire* wire = outputs[co_count++]; + wire = outputs[co_count++]; log_assert(wire); log_assert(wire->port_output); wire->port_output = false; - rhs.append(wire); } if (w->port_output) { log_assert(static_cast(pi_count + ci_count) < inputs.size()); - RTLIL::Wire* wire = inputs[pi_count + ci_count++]; + wire = inputs[pi_count + ci_count++]; log_assert(wire); log_assert(wire->port_input); wire->port_input = false; - rhs.append(wire); } + rhs.append(wire); + if (GetSize(w) == 1) + module->rename(wire, RTLIL::escape_id(stringf("%s.%s", log_id(cell), log_id(port_name)))); + else + module->rename(wire, RTLIL::escape_id(stringf("%s.%s[%d]", log_id(cell), log_id(port_name), i))); } cell->setPort(port_name, rhs); } From 887c31f33b82e5cb3f50523873d41ceb0cb8e7f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 16:03:22 -0700 Subject: [PATCH 312/514] Fix issue where keep signal became PI, but also box was adding CI driver --- backends/aiger/xaiger.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index efdd1844b..cd15b6160 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -392,6 +392,12 @@ struct XAigerWriter if (O != b) alias_map[O] = b; undriven_bits.erase(O); + + auto jt = input_bits.find(b); + if (jt != input_bits.end()) { + log_assert(b.wire->attributes.count("\\keep")); + input_bits.erase(b); + } } } } @@ -409,9 +415,10 @@ struct XAigerWriter if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { log_assert(input_bits.count(bit) && output_bits.count(bit)); - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; + RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); if (not_map.count(bit)) @@ -468,12 +475,15 @@ struct XAigerWriter for (auto bit : input_bits) { aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } for (auto &c : ci_bits) { + RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - aig_map[std::get<0>(c)] = 2*aig_m; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -538,8 +548,7 @@ struct XAigerWriter for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = aig_o++; - ordered_outputs[bit] = std::get<4>(c); + std::get<4>(c) = ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -720,10 +729,15 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", num_outputs + co_bits.size()); write_h_buffer(num_outputs + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", num_outputs); write_h_buffer(num_outputs); + log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; From a379234f56753c3d72a6966c380ac6f83fde789c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 12:50:11 -0700 Subject: [PATCH 313/514] Throw out unused code inherited from abc --- passes/techmap/abc9.cc | 215 +---------------------------------------- 1 file changed, 3 insertions(+), 212 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 4bda388de..f14828745 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -467,48 +467,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri { log_header(design, "Executing ABC9.\n"); - std::string buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); - f = fopen(buffer.c_str(), "wt"); - if (f == NULL) - log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); - fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); - fprintf(f, "GATE ONE 1 Y=CONST1;\n"); - fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); - fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); - if (enabled_gates.empty() || enabled_gates.count("AND")) - fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_")); - if (enabled_gates.empty() || enabled_gates.count("NAND")) - fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); - if (enabled_gates.empty() || enabled_gates.count("OR")) - fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_")); - if (enabled_gates.empty() || enabled_gates.count("NOR")) - fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); - if (enabled_gates.empty() || enabled_gates.count("XOR")) - fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); - if (enabled_gates.empty() || enabled_gates.count("XNOR")) - fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); - if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) - fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_")); - if (enabled_gates.empty() || enabled_gates.count("ORNOT")) - fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_")); - if (enabled_gates.empty() || enabled_gates.count("AOI3")) - fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); - if (enabled_gates.empty() || enabled_gates.count("OAI3")) - fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); - if (enabled_gates.empty() || enabled_gates.count("AOI4")) - fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); - if (enabled_gates.empty() || enabled_gates.count("OAI4")) - fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); - if (enabled_gates.empty() || enabled_gates.count("MUX")) - 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_")); - if (map_mux4) - fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_")); - if (map_mux8) - fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_")); - if (map_mux16) - fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); - fclose(f); - + std::string buffer; if (!lut_costs.empty()) { buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); @@ -680,161 +639,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; continue; } - - 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->getPort("\\Y").as_wire()->name)]); - conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1); - module->connect(conn); - continue; - } - if (c->type == "\\BUF") { - RTLIL::SigSig 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 == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || - c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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)])); - continue; - } - if (c->type == "\\MUX") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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)])); - continue; - } - if (c->type == "\\MUX4") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); - cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); - cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); - continue; - } - if (c->type == "\\MUX8") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); - cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); - cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); - cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); - cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); - cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); - cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); - cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); - continue; - } - if (c->type == "\\MUX16") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); - cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); - cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); - cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); - cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)])); - cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)])); - cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)])); - cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)])); - cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)])); - cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)])); - cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)])); - cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)])); - cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); - cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); - cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); - cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)])); - cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); - continue; - } - if (c->type == "\\AOI3" || c->type == "\\OAI3") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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)])); - continue; - } - if (c->type == "\\AOI4" || c->type == "\\OAI4") { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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)])); - continue; - } - if (c->type == "\\DFF") { - log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell; - if (en_sig.size() == 0) { - cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); - } else { - log_assert(en_sig.size() == 1); - cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort("\\E", en_sig); - } - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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); - continue; - } } - else - cell_stats[RTLIL::unescape_id(c->type)]++; + 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.as_wire()->name)]); - conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1); - module->connect(conn); - continue; - } - - if (c->type == "\\_dff_") { - log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell; - if (en_sig.size() == 0) { - cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); - } else { - log_assert(en_sig.size() == 1); - cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort("\\E", en_sig); - } - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - 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); - continue; - } - - RTLIL::Cell* cell; if (c->type == "$lut") { if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; @@ -846,7 +653,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri else log_assert(erased_boxes.count(c->name)); - cell = module->addCell(remap_name(c->name), c->type); + RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->parameters = c->parameters; for (auto &conn : c->connections()) { @@ -893,22 +700,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto &it : cell_stats) log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); int in_wires = 0, out_wires = 0; - //for (auto &si : signal_list) - // if (si.is_port) { - // char buffer[100]; - // snprintf(buffer, 100, "\\n%d", si.id); - // RTLIL::SigSig conn; - // 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.bit; - // in_wires++; - // } - // module->connect(conn); - // } // Stitch in mapped_mod's inputs/outputs into module for (auto &it : mapped_mod->wires_) { From 4623177655892c4aaf68757efff89aa748090c58 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 15:23:33 -0700 Subject: [PATCH 314/514] ABC9 to understand flops --- backends/aiger/xaiger.cc | 73 +++++++++++++++------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7a139f68f..90fea2db1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,7 +181,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -258,22 +257,28 @@ struct XAigerWriter // continue; //} + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + RTLIL::Wire* port = inst_module->wire(c.first); for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (is_input && port->attributes.count("\\abc_flop_d")) { d = b; + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; + if (is_output && port->attributes.count("\\abc_flop_q")) { + q = b; + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); } } } @@ -281,7 +286,6 @@ struct XAigerWriter abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); - undriven_bits.erase(q); } else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; @@ -507,8 +511,9 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; + RTLIL::SigBit bit = f.second; aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } @@ -516,12 +521,9 @@ struct XAigerWriter for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - //auto r = aig_map.insert(std::make_pair(c.first, c.second)); - //if (!r.second) { - // ff_aig_map[std::get<0>(c)] = 2*aig_m; - //} + auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); + if (!r.second) + ff_aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -597,7 +599,8 @@ struct XAigerWriter for (auto &f : ff_bits) { aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); + RTLIL::SigBit bit = f.second; + aig_outputs.push_back(ff_aig_map.at(bit)); } if (omode && output_bits.empty()) { @@ -778,8 +781,8 @@ struct XAigerWriter write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %d\n", num_outputs); - write_h_buffer(num_outputs); + log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -856,7 +859,7 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { + /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; auto write_r_buffer = [&r_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -867,6 +870,7 @@ struct XAigerWriter #endif r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) @@ -923,29 +927,6 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } - - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(0); - - f << "r"; - buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); From e3d160a9cac9f134c40a03946dc97c957ebfa930 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 18:06:36 -0700 Subject: [PATCH 315/514] parse_xaiger to cope with flops --- frontends/aiger/aigerparse.cc | 204 ++++++++++++++++++++-------------- frontends/aiger/aigerparse.h | 2 + 2 files changed, 123 insertions(+), 83 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 69404b19d..0e210c456 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -75,6 +75,8 @@ end_of_header: log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); line_count = 1; + piNum = 0; + flopNum = 0; if (header == "aag") parse_aiger_ascii(); @@ -184,6 +186,8 @@ void AigerReader::parse_xaiger() log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A); line_count = 1; + piNum = 0; + flopNum = 0; if (header == "aag") parse_aiger_ascii(); @@ -250,22 +254,10 @@ void AigerReader::parse_xaiger() } } else if (c == 'r') { - /*uint32_t dataSize =*/ parse_xaiger_literal(f); - uint32_t flopNum = parse_xaiger_literal(f); + uint32_t dataSize = parse_xaiger_literal(f); + flopNum = parse_xaiger_literal(f); + log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); f.ignore(flopNum * sizeof(uint32_t)); - log_assert(inputs.size() >= flopNum); - for (auto it = inputs.end() - flopNum; it != inputs.end(); ++it) { - log_assert((*it)->port_input); - (*it)->port_input = false; - } - inputs.erase(inputs.end() - flopNum, inputs.end()); - log_assert(outputs.size() >= flopNum); - for (auto it = outputs.end() - flopNum; it != outputs.end(); ++it) { - log_assert((*it)->port_output); - (*it)->port_output = false; - } - outputs.erase(outputs.end() - flopNum, outputs.end()); - module->fixup_ports(); } else if (c == 'n') { parse_xaiger_literal(f); @@ -276,14 +268,23 @@ void AigerReader::parse_xaiger() f.ignore(sizeof(uint32_t)); uint32_t version = parse_xaiger_literal(f); log_assert(version == 1); - f.ignore(4*sizeof(uint32_t)); + uint32_t ciNum = parse_xaiger_literal(f); + log_debug("ciNum = %u\n", ciNum); + uint32_t coNum = parse_xaiger_literal(f); + log_debug("coNum = %u\n", coNum); + piNum = parse_xaiger_literal(f); + log_debug("piNum = %u\n", piNum); + uint32_t poNum = parse_xaiger_literal(f); + log_debug("poNum = %u\n", poNum); uint32_t boxNum = parse_xaiger_literal(f); + log_debug("boxNum = %u\n", poNum); for (unsigned i = 0; i < boxNum; i++) { f.ignore(2*sizeof(uint32_t)); uint32_t boxUniqueId = parse_xaiger_literal(f); log_assert(boxUniqueId > 0); uint32_t oldBoxNum = parse_xaiger_literal(f); - module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId)); + boxes.emplace_back(cell); } } else if (c == 'a' || c == 'i' || c == 'o') { @@ -560,14 +561,100 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { + pool abc_carry_modules; + unsigned ci_count = 0, co_count = 0, flop_count = 0; + for (auto cell : boxes) { + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; + RTLIL::Wire* last_in = nullptr, *last_out = nullptr; + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_input) { + if (w->attributes.count("\\abc_carry_in")) { + log_assert(!carry_in); + carry_in = w; + } + log_assert(!last_in || last_in->port_id < w->port_id); + last_in = w; + } + if (w->port_output) { + if (w->attributes.count("\\abc_carry_out")) { + log_assert(!carry_out); + carry_out = w; + } + log_assert(!last_out || last_out->port_id < w->port_id); + last_out = w; + } + } + + if (carry_in != last_in) { + std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]); + std::swap(carry_in->port_id, last_in->port_id); + } + if (carry_out != last_out) { + log_assert(last_out); + std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]); + std::swap(carry_out->port_id, last_out->port_id); + } + } + + bool flop = box_module->attributes.count("\\abc_flop"); + log_assert(!flop || flop_count < flopNum); + + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (auto port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + RTLIL::SigSpec rhs; + RTLIL::Wire* wire = nullptr; + for (int i = 0; i < GetSize(w); i++) { + if (w->port_input) { + log_assert(co_count < outputs.size()); + wire = outputs[co_count++]; + log_assert(wire); + log_assert(wire->port_output); + wire->port_output = false; + + if (flop && w->attributes.count("\\abc_flop_d")) { + RTLIL::Wire* d = outputs[outputs.size() - flopNum + flop_count]; + log_assert(d); + log_assert(d->port_output); + d->port_output = false; + } + } + if (w->port_output) { + log_assert((piNum + ci_count) < inputs.size()); + wire = inputs[piNum + ci_count++]; + log_assert(wire); + log_assert(wire->port_input); + wire->port_input = false; + + if (flop && w->attributes.count("\\abc_flop_q")) { + wire = inputs[piNum - flopNum + flop_count]; + log_assert(wire); + log_assert(wire->port_input); + wire->port_input = false; + } + } + rhs.append(wire); + } + cell->setPort(port_name, rhs); + } + + if (flop) flop_count++; + } + dict wideports_cache; if (!map_filename.empty()) { std::ifstream mf(map_filename); std::string type, symbol; int variable, index; - int pi_count = 0, ci_count = 0, co_count = 0; - pool abc_carry_modules; while (mf >> type >> variable >> index >> symbol) { RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); if (type == "input") { @@ -575,7 +662,6 @@ void AigerReader::post_process() RTLIL::Wire* wire = inputs[variable]; log_assert(wire); log_assert(wire->port_input); - pi_count++; if (index == 0) { // Cope with the fact that a CI might be identical @@ -661,75 +747,27 @@ void AigerReader::post_process() } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); - if (cell) { + if (cell) { // ABC could have optimised this box away module->rename(cell, escaped_s); RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { - RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - RTLIL::Wire* last_in = nullptr, *last_out = nullptr; - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - if (w->port_input) { - if (w->attributes.count("\\abc_carry_in")) { - log_assert(!carry_in); - carry_in = w; - } - log_assert(!last_in || last_in->port_id < w->port_id); - last_in = w; - } - if (w->port_output) { - if (w->attributes.count("\\abc_carry_out")) { - log_assert(!carry_out); - carry_out = w; - } - log_assert(!last_out || last_out->port_id < w->port_id); - last_out = w; + for (const auto &i : cell->connections()) { + RTLIL::IdString port_name = i.first; + RTLIL::SigSpec rhs = i.second; + int index = 0; + for (auto bit : rhs.bits()) { + RTLIL::Wire* wire = bit.wire; + RTLIL::IdString escaped_s = RTLIL::escape_id(stringf("%s.%s", log_id(cell), log_id(port_name))); + if (index == 0) + module->rename(wire, escaped_s); + else if (index > 0) { + module->rename(wire, stringf("%s[%d]", escaped_s.c_str(), index)); + if (wideports) + wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); } + index++; } - - if (carry_in != last_in) { - std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]); - std::swap(carry_in->port_id, last_in->port_id); - } - if (carry_out != last_out) { - log_assert(last_out); - std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]); - std::swap(carry_out->port_id, last_out->port_id); - } - } - - // NB: Assume box_module->ports are sorted alphabetically - // (as RTLIL::Module::fixup_ports() would do) - for (auto port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - RTLIL::SigSpec rhs; - RTLIL::Wire* wire = nullptr; - for (int i = 0; i < GetSize(w); i++) { - if (w->port_input) { - log_assert(static_cast(co_count) < outputs.size()); - wire = outputs[co_count++]; - log_assert(wire); - log_assert(wire->port_output); - wire->port_output = false; - } - if (w->port_output) { - log_assert(static_cast(pi_count + ci_count) < inputs.size()); - wire = inputs[pi_count + ci_count++]; - log_assert(wire); - log_assert(wire->port_input); - wire->port_input = false; - } - rhs.append(wire); - if (GetSize(w) == 1) - module->rename(wire, RTLIL::escape_id(stringf("%s.%s", log_id(cell), log_id(port_name)))); - else - module->rename(wire, RTLIL::escape_id(stringf("%s.%s[%d]", log_id(cell), log_id(port_name), i))); - } - cell->setPort(port_name, rhs); } } } diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 8c9f3a0c9..28f40279b 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -37,10 +37,12 @@ struct AigerReader unsigned M, I, L, O, A; unsigned B, C, J, F; // Optional in AIGER 1.9 unsigned line_count; + uint32_t piNum, flopNum; std::vector inputs; std::vector latches; std::vector outputs; + std::vector boxes; AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); From dea36d4366109441e84e2e84afcfd8eb0223c902 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 18:10:25 -0700 Subject: [PATCH 316/514] Techmap flops before ABC again --- techlibs/xilinx/synth_xilinx.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index cc667b919..97464ffe4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,7 +282,9 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v "); + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); } @@ -299,9 +301,7 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); - run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); + run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"); run("clean"); } From 01f71085f281d4721386018c90d3f95b2864df5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 18:11:24 -0700 Subject: [PATCH 317/514] Add FD*E_1 -> FD*E techmap rules --- techlibs/xilinx/cells_sim.v | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 7337e0ea7..cce03980d 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -173,7 +173,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, lib_whitebox, abc_carry *) +(* abc_box_id = 3, abc_carry, lib_whitebox *) module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; @@ -205,56 +205,82 @@ endmodule `endif -module FDRE ((* abc_flop_q *) output reg Q, input C, CE, input D, R); +(* abc_box_id = 6, abc_flop /*, lib_whitebox */ *) +module FDRE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; +`ifndef _ABC generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate +`else + always @* if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; +`endif endmodule -module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S); +(* abc_box_id = 7, abc_flop /*, lib_whitebox*/ *) +module FDSE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input S); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; +`ifndef _ABC generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate +`else + always @* if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; +`endif endmodule -module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); +(* abc_box_id = 8, abc_flop /*, lib_whitebox*/ *) +module FDCE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) +`ifndef _ABC 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate +`else + generate case (|IS_CLR_INVERTED) + 1'b0: always @* if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @* if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +`endif endmodule -module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); +(* abc_box_id = 9, abc_flop /*, lib_whitebox*/ *) +module FDPE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_q *) input D, input PRE); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; +`ifndef _ABC generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate +`else + generate case (|IS_PRE_INVERTED) + 1'b0: always @* if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @* if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +`endif endmodule module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R); From 2228cef62f8550f85b203752681e2abeef1197ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 18:11:46 -0700 Subject: [PATCH 318/514] Add flops as blackboxes --- techlibs/xilinx/abc.box | 20 ++++++++++++++++++++ techlibs/xilinx/ff_map.v | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index 6e9e1faf6..a4182ed63 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -40,3 +40,23 @@ RAM64X1D 4 0 15 2 RAM128X1D 5 0 17 2 - - - - - - - - 314 314 314 314 314 314 292 - - 347 347 347 347 347 347 296 - - - - - - - - - - + +# Inputs: C CE D R +# Outputs: Q +FDRE 6 0 4 1 +- - - - + +# Inputs: C CE D S +# Outputs: Q +FDSE 7 0 4 1 +- - - - + +# Inputs: C CE CLR D +# Outputs: Q +FDCE 8 0 4 1 +- - 404 - + +# Inputs: C CE D PRE +# Outputs: Q +FDPE 9 0 4 1 +- - - 404 diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index 13beaa6ae..7c837814a 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -38,5 +38,12 @@ module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPL module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +`ifndef DEPRECATED +module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; FDRE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .R(R), .Q(Q)); endmodule +module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; FDSE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .S(S), .Q(Q)); endmodule +module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; FDCE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q)); endmodule +module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; FDPE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q)); endmodule +`endif + `endif From 9f44a7171528b90e85b2f33ef8823660fbd95609 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 09:23:43 -0700 Subject: [PATCH 319/514] Consistent with xilinx --- techlibs/ice40/abc_hx.box | 2 +- techlibs/ice40/cells_sim.v | 2 +- techlibs/ice40/synth_ice40.cc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index 994f3091d..9ebdae18b 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 1 2 1 +SB_DFF 1 0 2 1 - - # Inputs: C D E diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index b5e10fb20..6897aeeb4 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -145,7 +145,7 @@ endmodule (* abc_box_id = 1, abc_flop, lib_whitebox *) module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); -`ifndef ABC_MODEL +`ifndef _ABC always @(posedge C) Q <= D; `else diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 168161a90..5afa042b0 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v"); + run("read_verilog -lib -D_ABC +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } @@ -334,7 +334,7 @@ struct SynthIce40Pass : public ScriptPass if (abc == "abc9") run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); else - run(abc + " -lut 4", "(skip if -noabc)"); + run(abc + " -dress -lut 4", "(skip if -noabc)"); } run("clean"); if (relut || help_mode) { From 4da25c76b365b7c90a368c36def81d1122434b95 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 09:33:42 -0700 Subject: [PATCH 320/514] Ooopsie --- techlibs/ice40/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 287c48b11..759549e30 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -53,7 +53,7 @@ module \$lut (A, Y); end else if (WIDTH == 4) begin localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]}; - SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; From 257f7ff5f63635f0a754f34cf8af93ed06632b5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:30:54 -0700 Subject: [PATCH 321/514] When creating new holes cell, inherit parameters too --- backends/aiger/xaiger.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 90fea2db1..818caebba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -796,8 +796,10 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) + if (box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) From a54822b1bc02773168717f9c0e221344f570ac23 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:31:23 -0700 Subject: [PATCH 322/514] Skip internal modules when generating box_unique_id --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0e210c456..c951e1fbb 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -198,6 +198,7 @@ void AigerReader::parse_xaiger() dict box_lookup; for (auto m : design->modules()) { + if (m->name[0] == '$') continue; auto it = m->attributes.find("\\abc_box_id"); if (it == m->attributes.end()) continue; From 295bd8d0bf81dcb4ad07b1798e021dddcb5dfdc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:32:20 -0700 Subject: [PATCH 323/514] Remove dupe --- passes/techmap/abc9.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 01842dbf2..06a638558 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -552,7 +552,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // Remove all AND, NOT, and ABC box instances // in preparation for stitching mapped_mod in - pool erased_boxes; + dict erased_boxes; for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { RTLIL::Cell* cell = it->second; if (cell->type.in("$_AND_", "$_NOT_")) { @@ -561,7 +561,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } RTLIL::Module* box_module = design->module(cell->type); if (box_module && box_module->attributes.count("\\abc_box_id")) { - erased_boxes.insert(it->first); + erased_boxes.insert(std::make_pair(it->first, std::move(cell->parameters))); it = module->cells_.erase(it); continue; } @@ -645,8 +645,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; } } - else - log_assert(erased_boxes.count(c->name)); + else { + 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; @@ -1226,9 +1229,6 @@ struct Abc9Pass : public Pass { continue; } - if (mod->attributes.count("\\abc_box_id")) - continue; - assign_map.set(mod); signal_init.clear(); From d018cd9fe3f65187b7f8a878994dfbc37308d653 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:33:47 -0700 Subject: [PATCH 324/514] Assert that box_unique_id is indeed unique --- frontends/aiger/aigerparse.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c951e1fbb..95335a029 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -198,11 +198,12 @@ void AigerReader::parse_xaiger() dict box_lookup; for (auto m : design->modules()) { - if (m->name[0] == '$') continue; auto it = m->attributes.find("\\abc_box_id"); if (it == m->attributes.end()) continue; - box_lookup[it->second.as_int()] = m->name; + if (m->name[0] == '$') continue; + auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name)); + log_assert(r.second); } // Parse footer (symbol table, comments, etc.) From 00927703177d01ad27559aad827b72068b80b12a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:34:55 -0700 Subject: [PATCH 325/514] Make SB_LUT4 a whitebox, SB_DFF a blackbox (for now) --- techlibs/ice40/abc_hx.box | 2 +- techlibs/ice40/abc_lp.box | 4 ++-- techlibs/ice40/abc_u.box | 4 ++-- techlibs/ice40/cells_sim.v | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index 9ebdae18b..a0655643d 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 0 4 1 +SB_LUT4 22 1 4 1 449 400 379 316 diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index 002b7bba4..dbc98d0c4 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 1 2 1 +SB_DFF 1 0 2 1 - - # Inputs: C D E @@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 0 4 1 +SB_LUT4 22 1 4 1 465 558 589 661 diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index cb336181c..3b5834e40 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -4,7 +4,7 @@ # Inputs: C D # Outputs: Q -SB_DFF 1 1 2 1 +SB_DFF 1 0 2 1 - - # Inputs: C D E @@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 0 4 1 +SB_LUT4 22 1 4 1 1285 1231 1205 874 diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 6897aeeb4..b9f381266 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -127,7 +127,7 @@ endmodule // SiliconBlue Logic Cells -(* abc_box_id = 22 *) +(* abc_box_id = 22, lib_whitebox *) module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; @@ -136,8 +136,8 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 21, lib_whitebox *) -module SB_CARRY (output CO, input I0, I1, CI); +(* abc_box_id = 21, abc_carry, lib_whitebox *) +module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule From ebcc85b9b86267a25e9126aa3d82ef4a0bd9f6fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:37:02 -0700 Subject: [PATCH 326/514] Fix `ifndef --- techlibs/xilinx/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index cce03980d..c8450f8d1 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -246,8 +246,8 @@ module FDCE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) `ifndef _ABC + generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; From c9a0bac5413dff55e141deb4098b63ca4c62e5b1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 19:45:56 -0700 Subject: [PATCH 327/514] IS_C_INVERTED --- techlibs/xilinx/ff_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index 7c837814a..ce465130d 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -39,10 +39,10 @@ module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPL module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule `ifndef DEPRECATED -module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; FDRE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .R(R), .Q(Q)); endmodule -module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; FDSE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .S(S), .Q(Q)); endmodule -module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; FDCE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q)); endmodule -module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; FDPE #(.INIT(INIT), .IS_CLK_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q)); endmodule +module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; FDRE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .R(R), .Q(Q)); endmodule +module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; FDSE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .S(S), .Q(Q)); endmodule +module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; FDCE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q)); endmodule +module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; FDPE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q)); endmodule `endif `endif From b6e59741ae6e4ec57affb9ab168a9d08cdb6d04f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 20:21:41 -0700 Subject: [PATCH 328/514] Typo --- techlibs/xilinx/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index c8450f8d1..16b8b4949 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -262,7 +262,7 @@ module FDCE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input endmodule (* abc_box_id = 9, abc_flop /*, lib_whitebox*/ *) -module FDPE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_q *) input D, input PRE); +module FDPE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input PRE); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; From 23a73ca6241381e7272f905d1dcbf01c49ad00a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 23:19:22 -0700 Subject: [PATCH 329/514] Merge mistake --- techlibs/xilinx/synth_xilinx.cc | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e316c268e..4269870d7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -259,13 +259,6 @@ struct SynthXilinxPass : public ScriptPass run("dff2dffe"); run("opt -full"); - if (vpr && !nocarry && !help_mode) - run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - else if (abc == "abc9" && !nocarry && !help_mode) - run("techmap -map +/xilinx/arith_map.v -D _CLB_CARRY", "(skip if '-nocarry')"); - else if (!nocarry || help_mode) - run("techmap -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); - if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here @@ -274,13 +267,12 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - if (!nomux || help_mode) - run("techmap -map +/xilinx/cells_map.v"); - - if (!vpr || help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); - else - run("techmap -map +/techmap.v +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + if (vpr && !nocarry && !help_mode) + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + else if (abc == "abc9" && !nocarry && !help_mode) + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _CLB_CARRY", "(skip if '-nocarry')"); + else if (!nocarry || help_mode) + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); run("opt -fast"); } From 5afa42432f71443e69d1095d17066ae173b7883a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 23:29:45 -0700 Subject: [PATCH 330/514] Fix pmux2shiftx logic --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4269870d7..19a19d14e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -229,7 +229,7 @@ struct SynthXilinxPass : public ScriptPass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if ((!nosrl && !nomux) || help_mode) + if (!(nosrl && nomux) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); // Run a number of peephole optimisations, including one From 09b778744dc036d54209644884e9dc9138f95771 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 23:42:30 -0700 Subject: [PATCH 331/514] Respect -nocarry --- techlibs/xilinx/synth_xilinx.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 19a19d14e..8ce552780 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -270,9 +270,11 @@ struct SynthXilinxPass : public ScriptPass if (vpr && !nocarry && !help_mode) run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); else if (abc == "abc9" && !nocarry && !help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _CLB_CARRY", "(skip if '-nocarry')"); + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _CLB_CARRY"); else if (!nocarry || help_mode) run("techmap -map +/techmap.v -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); + else + run("techmap -map +/techmap.v"); run("opt -fast"); } From 9b9bd4e19f3da363eb3c90ef27ace282716d2e06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 23:43:23 -0700 Subject: [PATCH 332/514] Move ff_map back after ABC for shregmap --- techlibs/xilinx/synth_xilinx.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8ce552780..f45126dc5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -280,9 +280,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v "); - run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } @@ -299,7 +297,9 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"); + run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); } From e260150321f3410056da64f83783b470caa89384 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 09:51:47 -0700 Subject: [PATCH 333/514] Add mux_map.v for wide mux --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/cells_map.v | 35 +++++++++------------- techlibs/xilinx/mux_map.v | 52 +++++++++++++++++++++++++++++++++ techlibs/xilinx/synth_xilinx.cc | 24 +++++++++------ 4 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 techlibs/xilinx/mux_map.v diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 296edace9..2f3945167 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,6 +30,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index af6414667..120d610bb 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -152,7 +153,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule -module \$shiftx (A, B, Y); +module \$__XILINX_MUX_ (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -184,18 +185,10 @@ module \$shiftx (A, B, Y); generate genvar i, j; - // TODO: Check if this opt still necessary - if (B_SIGNED) begin - if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); - else - wire _TECHMAP_FAIL_ = 1; - end // Bit-blast - else if (Y_WIDTH > 1) begin + if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); end // If the LSB of B is constant zero (and Y_WIDTH is 1) then // we can optimise by removing every other entry from A @@ -204,24 +197,24 @@ module \$shiftx (A, B, Y); wire [(A_WIDTH+1)/2-1:0] A_i; for (i = 0; i < (A_WIDTH+1)/2; i++) assign A_i[i] = A[i*2]; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end // Trim off any leading 1'bx -es in A, and resize B accordingly else if (num_leading_X_in_A > 0) begin localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; localparam B_WIDTH_new = $clog2(A_WIDTH_new); - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); end else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - wire _TECHMAP_FAIL_ = 1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); end else if (B_WIDTH == 3) begin localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); else assign T1 = A[A_WIDTH-1]; MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); @@ -234,10 +227,10 @@ module \$shiftx (A, B, Y); wire T0, T1; for (i = 0; i < 4; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) begin if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; end @@ -254,16 +247,16 @@ module \$shiftx (A, B, Y); wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_shiftx_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; end else assign T[i] = 1'bx; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_shiftx (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v new file mode 100644 index 000000000..2ad7f7671 --- /dev/null +++ b/techlibs/xilinx/mux_map.v @@ -0,0 +1,52 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module \$shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + generate + genvar i, j; + // TODO: Check if this opt still necessary + if (B_SIGNED) begin + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH < 3 || A_WIDTH <= 4) begin + wire _TECHMAP_FAIL_ = 1; + end + else begin + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + end + endgenerate +endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f45126dc5..360418975 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -267,15 +267,21 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - if (vpr && !nocarry && !help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - else if (abc == "abc9" && !nocarry && !help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _CLB_CARRY"); - else if (!nocarry || help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); - else - run("techmap -map +/techmap.v"); - + std::string techmap_files = " -map +/techmap.v"; + if (help_mode) + techmap_files += " [-map +/xilinx/mux_map.v]"; + else if (!nomux) + techmap_files += " -map +/xilinx/mux_map.v"; + if (help_mode) + techmap_files += " [-map +/xilinx/arith_map.v]"; + else if (!nocarry) { + techmap_files += " -map +/xilinx/arith_map.v"; + if (vpr) + techmap_files += " -D _EXPLICIT_CARRY"; + else if (abc == "abc9") + techmap_files += " -D _CLB_CARRY"; + } + run("techmap " + techmap_files); run("opt -fast"); } From 6cf092641f3e39b466f1f36617a1474f9ae36901 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 09:56:36 -0700 Subject: [PATCH 334/514] Fix name clash --- techlibs/xilinx/cells_map.v | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 120d610bb..f3422349f 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -212,12 +212,12 @@ module \$__XILINX_MUX_ (A, B, Y); localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); else assign T1 = A[A_WIDTH-1]; - MUXF7 fpga_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); end else if (B_WIDTH == 4) begin localparam a_width0 = 2 ** 2; @@ -227,18 +227,18 @@ module \$__XILINX_MUX_ (A, B, Y); wire T0, T1; for (i = 0; i < 4; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) begin if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; end else assign T[i] = 1'bx; - MUXF7 fpga_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); - MUXF7 fpga_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); - MUXF8 fpga_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); + MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); + MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); + MUXF8 fpga_hard_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; @@ -247,16 +247,16 @@ module \$__XILINX_MUX_ (A, B, Y); wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin if (a_widthN > 1) - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; end else assign T[i] = 1'bx; - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule From f0e93f33cf089a1c1924e569700792bf198b6810 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 11:53:51 -0700 Subject: [PATCH 335/514] Add (* abc_flop_q *) to brams_bb.v --- techlibs/xilinx/brams_bb.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/brams_bb.v b/techlibs/xilinx/brams_bb.v index a682ba4a7..f540d299d 100644 --- a/techlibs/xilinx/brams_bb.v +++ b/techlibs/xilinx/brams_bb.v @@ -19,10 +19,10 @@ module RAMB18E1 ( input [1:0] WEA, input [3:0] WEBWE, - output [15:0] DOADO, - output [15:0] DOBDO, - output [1:0] DOPADOP, - output [1:0] DOPBDOP + (* abc_flop_q *) output [15:0] DOADO, + (* abc_flop_q *) output [15:0] DOBDO, + (* abc_flop_q *) output [1:0] DOPADOP, + (* abc_flop_q *) output [1:0] DOPBDOP ); parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; @@ -143,10 +143,10 @@ module RAMB36E1 ( input [3:0] WEA, input [7:0] WEBWE, - output [31:0] DOADO, - output [31:0] DOBDO, - output [3:0] DOPADOP, - output [3:0] DOPBDOP + (* abc_flop_q *) output [31:0] DOADO, + (* abc_flop_q *) output [31:0] DOBDO, + (* abc_flop_q *) output [3:0] DOPADOP, + (* abc_flop_q *) output [3:0] DOPBDOP ); parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; From 82d41bc2f2460a06e153eac4f3968ef29ce5a63d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 11:54:08 -0700 Subject: [PATCH 336/514] Add space between -D and _ABC --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 360418975..e9eccfc0e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -203,9 +203,9 @@ struct SynthXilinxPass : public ScriptPass { if (check_label("begin")) { if (vpr) - run("read_verilog -lib -D_ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + run("read_verilog -lib -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); else - run("read_verilog -lib -D_ABC +/xilinx/cells_sim.v"); + run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_xtra.v"); From 1b836c93bbaa3c85d4730b0251aed64cdf207422 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 11:56:58 -0700 Subject: [PATCH 337/514] Only toposort builtin and abc types --- backends/aiger/xaiger.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 818caebba..4d45bb650 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,14 +181,17 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool known_type = yosys_celltypes.cell_known(cell->type); + bool builtin_type = yosys_celltypes.cell_known(cell->type); + bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); if (!holes_mode) { toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { + for (const auto &conn : cell->connections()) { + if (!builtin_type && !abc_type) + continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { - if (known_type) { + if (builtin_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -199,8 +202,8 @@ struct XAigerWriter RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) + continue; } } From 7b186740d33972612cfc9f2ebe31258edb0cca2b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 12:01:25 -0700 Subject: [PATCH 338/514] Add log_assert to ensure no loops --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d45bb650..bf2f9f1bc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -334,7 +334,21 @@ struct XAigerWriter pool abc_carry_modules; - toposort.sort(); +#if 0 + toposort.analyze_loops = true; +#endif + bool no_loops = toposort.sort(); +#if 0 + unsigned i = 0; + for (auto &it : toposort.loops) { + log(" loop %d", i++); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif + log_assert(no_loops); + for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); From 94a5f4e60985fc1e3fea75eec85638fa29874bea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 14:34:36 -0700 Subject: [PATCH 339/514] Rename shregmap -tech xilinx -> xilinx_dynamic --- passes/techmap/shregmap.cc | 8 ++++---- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 75eedfbcc..3e2c34c0d 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -93,12 +93,12 @@ struct ShregmapTechGreenpak4 : ShregmapTech } }; -struct ShregmapTechXilinx7 : ShregmapTech +struct ShregmapTechXilinx7Dynamic : ShregmapTech { dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; - ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} + ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : opts(opts) {} virtual void init(const Module* module, const SigMap &sigmap) override { @@ -660,11 +660,11 @@ struct ShregmapPass : public Pass { opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; } - else if (tech == "xilinx") { + else if (tech == "xilinx_dynamic") { opts.init = true; opts.params = true; enpol = "any_or_none"; - opts.tech = new ShregmapTechXilinx7(opts); + opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { argidx--; break; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e9eccfc0e..b2559d272 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -263,8 +263,8 @@ struct SynthXilinxPass : public ScriptPass // shregmap operates on bit-level flops, not word-level, // so break those down here run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); - // shregmap with '-tech xilinx' infers variable length shift regs - run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); + // shregmap to infer variable length shift regs + run("shregmap -tech xilinx_dynamic -minlen 3", "(skip if '-nosrl')"); } std::string techmap_files = " -map +/techmap.v"; From 45d1bdf83ae6d51628e917b66f1b6043c8a3baee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 10:21:57 -0700 Subject: [PATCH 340/514] shregmap -tech xilinx_dynamic to work -params and -enpol --- passes/techmap/shregmap.cc | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3e2c34c0d..3726f04fd 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -56,7 +56,7 @@ struct ShregmapOptions struct ShregmapTechGreenpak4 : ShregmapTech { - bool analyze(vector &taps, const vector &/*qbits*/) + virtual bool analyze(vector &taps, const vector &/*qbits*/) override { if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) { taps.clear(); @@ -71,7 +71,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - bool fixup(Cell *cell, dict &taps) + virtual bool fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -212,8 +212,24 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTech newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); newcell->setParam("\\INIT", cell->getParam("\\INIT")); - newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); - newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL")); + + if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", + "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { + int param_clkpol = -1; + int param_enpol = 2; + if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; + else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; + else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + else log_abort(); + + log_assert(param_clkpol >= 0); + cell->setParam("\\CLKPOL", param_clkpol); + cell->setParam("\\ENPOL", param_enpol); + } + else log_abort(); newcell->setPort("\\C", cell->getPort("\\C")); newcell->setPort("\\D", cell->getPort("\\D")); @@ -662,8 +678,12 @@ struct ShregmapPass : public Pass { } else if (tech == "xilinx_dynamic") { opts.init = true; - opts.params = true; - enpol = "any_or_none"; + opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["$_DFFE_PP_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { argidx--; From e1e37db86073e545269ff440da77f57135e8b155 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 11:08:08 -0700 Subject: [PATCH 341/514] Refactor to ShregmapTechXilinx7Static --- passes/techmap/shregmap.cc | 132 ++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3726f04fd..add4e9e2f 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -29,7 +29,7 @@ struct ShregmapTech virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual bool fixup(Cell *cell, dict &taps) = 0; + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) = 0; }; struct ShregmapOptions @@ -71,7 +71,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual bool fixup(Cell *cell, dict &taps) override + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -89,16 +89,84 @@ struct ShregmapTechGreenpak4 : ShregmapTech } cell->setParam("\\OUTA_INVERT", 0); - return false; + return newcell; } }; -struct ShregmapTechXilinx7Dynamic : ShregmapTech +struct ShregmapTechXilinx7Static : ShregmapTech { - dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; - ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : opts(opts) {} + ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} + + virtual bool analyze(vector &taps, const vector &/*qbits*/) override + { + if (GetSize(taps) == 1) + return taps[0] >= opts.minlen-1; + + if (taps.back() < opts.minlen-1) + return false; + + return true; + } + + virtual RTLIL::Cell* fixup(Cell *cell, dict &/*taps*/) override + { + auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); + newcell->set_src_attribute(cell->get_src_attribute()); + newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); + + if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", + "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { + int param_clkpol = -1; + int param_enpol = 2; + if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; + else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; + else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + else log_abort(); + + log_assert(param_clkpol >= 0); + newcell->setParam("\\CLKPOL", param_clkpol); + newcell->setParam("\\ENPOL", param_enpol); + + if (cell->hasPort("\\E")) + newcell->setPort("\\E", cell->getPort("\\E")); + } + else if (cell->type.in("$__SHREG_FDRE_", "$__SHREG_FDSE_", "$__SHREG_FDCE_", "$__SHREG_FDPE_")) { + if (cell->getParam("\\IS_C_INVERTED").as_bool()) + newcell->setParam("\\CLKPOL", 0); + else + newcell->setParam("\\CLKPOL", 1); + newcell->setParam("\\ENPOL", 1); + + newcell->setPort("\\E", cell->getPort("\\CE")); + } + else if (cell->type.in("$__SHREG_FDRE_1_", "$__SHREG_FDSE_1_", "$__SHREG_FDCE_1_", "$__SHREG_FDPE_1_")) { + newcell->setParam("\\CLKPOL", 0); + + newcell->setPort("\\E", cell->getPort("\\CE")); + } + else log_abort(); + + newcell->setParam("\\ENPOL", 1); + + newcell->setPort("\\C", cell->getPort("\\C")); + newcell->setPort("\\D", cell->getPort("\\D")); + newcell->setPort("\\Q", cell->getPort("\\Q")); + + return newcell; + } +}; + +struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static +{ + dict> sigbit_to_shiftx_offset; + + ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : ShregmapTechXilinx7Static(opts) {} virtual void init(const Module* module, const SigMap &sigmap) override { @@ -200,7 +268,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTech return true; } - virtual bool fixup(Cell *cell, dict &taps) override + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override { const auto &tap = *taps.begin(); auto bit = tap.second; @@ -208,52 +276,24 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTech auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); - newcell->set_src_attribute(cell->get_src_attribute()); - newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); - newcell->setParam("\\INIT", cell->getParam("\\INIT")); - - if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", - "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { - int param_clkpol = -1; - int param_enpol = 2; - if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; - else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; - else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - else log_abort(); - - log_assert(param_clkpol >= 0); - cell->setParam("\\CLKPOL", param_clkpol); - cell->setParam("\\ENPOL", param_enpol); - } - else log_abort(); - - newcell->setPort("\\C", cell->getPort("\\C")); - newcell->setPort("\\D", cell->getPort("\\D")); - if (cell->hasPort("\\E")) - newcell->setPort("\\E", cell->getPort("\\E")); + RTLIL::Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); + log_assert(newcell); + log_assert(newcell->type == "$__SHREG_"); + newcell->type = "$__XILINX_SHREG_"; Cell* shiftx = std::get<0>(it->second); - RTLIL::SigSpec l_wire, q_wire; - if (shiftx->type == "$shiftx") { + RTLIL::SigSpec l_wire; + if (shiftx->type == "$shiftx") l_wire = shiftx->getPort("\\B"); - q_wire = shiftx->getPort("\\Y"); - shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); - } - else if (shiftx->type == "$mux") { + else if (shiftx->type == "$mux") l_wire = shiftx->getPort("\\S"); - q_wire = shiftx->getPort("\\Y"); - shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); - } else log_abort(); - newcell->setPort("\\Q", q_wire); newcell->setPort("\\L", l_wire); + newcell->setPort("\\Q", shiftx->getPort("\\Y")); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); - return false; + return newcell; } }; @@ -509,7 +549,7 @@ struct ShregmapWorker first_cell->setPort(q_port, last_cell->getPort(q_port)); first_cell->setParam("\\DEPTH", depth); - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps_dict)) remove_cells.insert(first_cell); for (int i = 1; i < depth; i++) From dfe9d95579ab98d7518d40e427af858243de4eb3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 11:14:14 -0700 Subject: [PATCH 342/514] Add -tech xilinx_static --- passes/techmap/shregmap.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index add4e9e2f..ef285160f 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -716,7 +716,7 @@ struct ShregmapPass : public Pass { opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; } - else if (tech == "xilinx_dynamic") { + else if (tech == "xilinx_static" || tech == "xilinx_dynamic") { opts.init = true; opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q")); @@ -724,7 +724,18 @@ struct ShregmapPass : public Pass { opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.tech = new ShregmapTechXilinx7Dynamic(opts); + opts.ffcells["FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + if (tech == "xilinx_static") + opts.tech = new ShregmapTechXilinx7Dynamic(opts); + else if (tech == "xilinx_dynamic") + opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { argidx--; break; From e473e7456545d702c011ee7872956f94a8522865 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 11:53:06 -0700 Subject: [PATCH 343/514] Revert "Move ff_map back after ABC for shregmap" This reverts commit 9b9bd4e19f3da363eb3c90ef27ace282716d2e06. --- techlibs/xilinx/synth_xilinx.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b2559d272..e825a032c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -286,7 +286,9 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v "); + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); } @@ -303,9 +305,7 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); - run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); + run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"); run("clean"); } From 2c18d530ea69094e7ed46dcf781d8f2517d4c61e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 12:28:26 -0700 Subject: [PATCH 344/514] Call shregmap -tech xilinx_static --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e825a032c..7686f2cbc 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -304,7 +304,7 @@ struct SynthXilinxPass : public ScriptPass // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode) - run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); + run("shregmap -tech xilinx_static -minlen 3", "(skip if '-nosrl')"); run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"); run("clean"); } From 67f744d428b5385fbddc859c8e02f3e1ccfc17eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 12:28:46 -0700 Subject: [PATCH 345/514] Cleanup --- techlibs/xilinx/cells_map.v | 10 ---------- techlibs/xilinx/ff_map.v | 7 ------- 2 files changed, 17 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f3422349f..4acf04744 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -18,16 +18,6 @@ * */ -// Convert negative-polarity reset to positive-polarity -(* techmap_celltype = "$_DFF_NN0_" *) -module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_DFF_PN0_" *) -module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_DFF_NN1_" *) -module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -(* techmap_celltype = "$_DFF_PN1_" *) -module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule - module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index ce465130d..13beaa6ae 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -38,12 +38,5 @@ module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPL module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule -`ifndef DEPRECATED -module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; FDRE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .R(R), .Q(Q)); endmodule -module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; FDSE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .S(S), .Q(Q)); endmodule -module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; FDCE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q)); endmodule -module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; FDPE #(.INIT(INIT), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q)); endmodule -`endif - `endif From 6ed15b7890091d358b7715413a844a01e9b2adf6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 12:33:40 -0700 Subject: [PATCH 346/514] Update abc attributes on FD*E_1 --- techlibs/xilinx/cells_sim.v | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 16b8b4949..e00992bb7 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -283,28 +283,48 @@ module FDPE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input `endif endmodule -module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R); +(* abc_box_id = 6, abc_flop /*, lib_whitebox */ *) +module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input R); parameter [0:0] INIT = 1'b0; initial Q <= INIT; - always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; +`ifndef _ABC + always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; +`else + always @* if (R) Q <= 1'b0; else if (CE) Q <= D; +`endif endmodule -module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S); +(* abc_box_id = 7, abc_flop /*, lib_whitebox */ *) +module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input S); parameter [0:0] INIT = 1'b1; initial Q <= INIT; - always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; +`ifndef _ABC + always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; +`else + always @* if (S) Q <= 1'b1; else if (CE) Q <= D; + `endif endmodule -module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); +(* abc_box_id = 8, abc_flop /*, lib_whitebox */ *) +module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input CLR); parameter [0:0] INIT = 1'b0; initial Q <= INIT; +`ifndef _ABC always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; +`else + always @* if (CLR) Q <= 1'b0; else if (CE) Q <= D; +`endif endmodule -module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); +(* abc_box_id = 9, abc_flop /*, lib_whitebox */ *) +module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input PRE); parameter [0:0] INIT = 1'b1; initial Q <= INIT; +`ifndef _ABC always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; +`else + always @* if (PRE) Q <= 1'b1; else if (CE) Q <= D; +`endif endmodule (* abc_box_id = 4 /*, lib_whitebox*/ *) From 72eda94a66c8c4938a713c9ae49d560e6b33574f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 12:33:55 -0700 Subject: [PATCH 347/514] Continue support for ShregmapTechXilinx7Static --- passes/techmap/shregmap.cc | 111 +++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 30 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index ef285160f..325db081b 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -28,8 +28,9 @@ struct ShregmapTech virtual ~ShregmapTech() { } virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} + virtual bool analyze_first(const Cell* /*first_cell*/, const SigMap &/*sigmap*/) { return true; } virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) = 0; + virtual Cell* fixup(Cell *cell, dict &taps) = 0; }; struct ShregmapOptions @@ -71,7 +72,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override + virtual Cell* fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -99,18 +100,61 @@ struct ShregmapTechXilinx7Static : ShregmapTech ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} - virtual bool analyze(vector &taps, const vector &/*qbits*/) override + virtual bool analyze_first(const Cell* first_cell, const SigMap &sigmap) override { - if (GetSize(taps) == 1) - return taps[0] >= opts.minlen-1; - - if (taps.back() < opts.minlen-1) - return false; - + if (first_cell->type.in("\\FDRE", "\\FDRE_1")) { + bool is_R_inverted = false; + if (first_cell->hasParam("\\IS_R_INVERTED")) + is_R_inverted = first_cell->getParam("\\IS_R_INVERTED").as_bool(); + SigBit R = sigmap(first_cell->getPort("\\R")); + if (R != RTLIL::S0 && R != RTLIL::S1) + return false; + if ((!is_R_inverted && R != RTLIL::S0) || (is_R_inverted && R != RTLIL::S1)) + return false; + return true; + } + if (first_cell->type.in("\\FDSE", "\\FDSE_1")) { + bool is_S_inverted = false; + if (first_cell->hasParam("\\IS_S_INVERTED")) + is_S_inverted = first_cell->getParam("\\IS_S_INVERTED").as_bool(); + SigBit S = sigmap(first_cell->getPort("\\S")); + if (S != RTLIL::S0 && S != RTLIL::S1) + return false; + if ((!is_S_inverted && S != RTLIL::S0) || (is_S_inverted && S != RTLIL::S1)) + return false; + return true; + } + if (first_cell->type.in("\\FDCE", "\\FDCE_1")) { + bool is_CLR_inverted = false; + if (first_cell->hasParam("\\IS_CLR_INVERTED")) + is_CLR_inverted = first_cell->getParam("\\IS_CLR_INVERTED").as_bool(); + SigBit CLR = sigmap(first_cell->getPort("\\CLR")); + if (CLR != RTLIL::S0 && CLR != RTLIL::S1) + return false; + if ((!is_CLR_inverted && CLR != RTLIL::S0) || (is_CLR_inverted && CLR != RTLIL::S1)) + return false; + return true; + } + if (first_cell->type.in("\\FDPE", "\\FDPE_1")) { + bool is_PRE_inverted = false; + if (first_cell->hasParam("\\IS_PRE_INVERTED")) + is_PRE_inverted = first_cell->getParam("\\IS_PRE_INVERTED").as_bool(); + SigBit PRE = sigmap(first_cell->getPort("\\PRE")); + if (PRE != RTLIL::S0 && PRE != RTLIL::S1) + return false; + if ((!is_PRE_inverted && PRE != RTLIL::S0) || (is_PRE_inverted && PRE != RTLIL::S1)) + return false; + return true; + } return true; } - virtual RTLIL::Cell* fixup(Cell *cell, dict &/*taps*/) override + virtual bool analyze(vector &taps, const vector &/*qbits*/) override + { + return GetSize(taps) == 1 && taps[0] >= opts.minlen-1; + } + + virtual Cell* fixup(Cell *cell, dict &/*taps*/) override { auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); newcell->set_src_attribute(cell->get_src_attribute()); @@ -136,16 +180,17 @@ struct ShregmapTechXilinx7Static : ShregmapTech if (cell->hasPort("\\E")) newcell->setPort("\\E", cell->getPort("\\E")); } - else if (cell->type.in("$__SHREG_FDRE_", "$__SHREG_FDSE_", "$__SHREG_FDCE_", "$__SHREG_FDPE_")) { - if (cell->getParam("\\IS_C_INVERTED").as_bool()) - newcell->setParam("\\CLKPOL", 0); - else - newcell->setParam("\\CLKPOL", 1); + else if (cell->type.in("$__SHREG_FDRE", "$__SHREG_FDRE_1","$__SHREG_FDSE", "$__SHREG_FDSE_1", + "$__SHREG_FDCE", "$__SHREG_FDCE_1", "$__SHREG_FDPE", "$__SHREG_FDPE_1")) { + int param_clkpol = 1; + if (cell->hasParam("\\IS_C_INVERTED") && cell->getParam("\\IS_C_INVERTED").as_bool()) + param_clkpol = 0; + newcell->setParam("\\CLKPOL", param_clkpol); newcell->setParam("\\ENPOL", 1); newcell->setPort("\\E", cell->getPort("\\CE")); } - else if (cell->type.in("$__SHREG_FDRE_1_", "$__SHREG_FDSE_1_", "$__SHREG_FDCE_1_", "$__SHREG_FDPE_1_")) { + else if (cell->type.in("$__SHREG_FDRE_1", "$__SHREG_FDSE_1", "$__SHREG_FDCE_1", "$__SHREG_FDPE_1")) { newcell->setParam("\\CLKPOL", 0); newcell->setPort("\\E", cell->getPort("\\CE")); @@ -215,13 +260,14 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static Cell *shiftx = nullptr; int group = 0; for (int i = 0; i < GetSize(taps); ++i) { + // Check taps are sequential + if (i != taps[i]) + return false; + auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (it == sigbit_to_shiftx_offset.end()) return false; - // Check taps are sequential - if (i != taps[i]) - return false; // Check taps are not connected to a shift register, // or sequential to the same shift register if (i == 0) { @@ -268,7 +314,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static return true; } - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override + virtual Cell* fixup(Cell *cell, dict &taps) override { const auto &tap = *taps.begin(); auto bit = tap.second; @@ -276,7 +322,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - RTLIL::Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); + Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); log_assert(newcell); log_assert(newcell->type == "$__SHREG_"); newcell->type = "$__XILINX_SHREG_"; @@ -451,6 +497,11 @@ struct ShregmapWorker if (opts.tech) { + if (!opts.tech->analyze_first(first_cell, sigmap)) { + cursor += depth; + continue; + } + vector qbits; vector taps; @@ -724,16 +775,16 @@ struct ShregmapPass : public Pass { opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["\\FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); if (tech == "xilinx_static") - opts.tech = new ShregmapTechXilinx7Dynamic(opts); + opts.tech = new ShregmapTechXilinx7Static(opts); else if (tech == "xilinx_dynamic") opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { From 935df3569b4677ac38041ff01a2f67185681f4e3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 12:55:59 -0700 Subject: [PATCH 348/514] shregmap -tech xilinx_static to handle INIT --- passes/techmap/shregmap.cc | 54 ++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 325db081b..3868bbb89 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -30,7 +30,7 @@ struct ShregmapTech virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} virtual bool analyze_first(const Cell* /*first_cell*/, const SigMap &/*sigmap*/) { return true; } virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual Cell* fixup(Cell *cell, dict &taps) = 0; + virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) = 0; }; struct ShregmapOptions @@ -72,7 +72,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual Cell* fixup(Cell *cell, dict &taps) override + virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -84,8 +84,8 @@ struct ShregmapTechGreenpak4 : ShregmapTech int i = 0; for (auto tap : taps) { - newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second); - newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap.first + 1); + newcell->setPort(i ? "\\OUTB" : "\\OUTA", qbits[tap]); + newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap + 1); i++; } @@ -96,8 +96,21 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7Static : ShregmapTech { + dict sigbit_to_cell; const ShregmapOptions &opts; + virtual void init(const Module* module, const SigMap &sigmap) override + { + for (const auto &i : module->cells_) { + auto cell = i.second; + if (!cell->type.in("\\FDRE", "\\FDRE_1","\\FDSE", "\\FDSE_1", + "\\FDCE", "\\FDCE_1", "\\FDPE", "\\FDPE_1")) + continue; + + sigbit_to_cell[sigmap(cell->getPort("\\Q"))] = cell; + } + } + ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} virtual bool analyze_first(const Cell* first_cell, const SigMap &sigmap) override @@ -154,15 +167,14 @@ struct ShregmapTechXilinx7Static : ShregmapTech return GetSize(taps) == 1 && taps[0] >= opts.minlen-1; } - virtual Cell* fixup(Cell *cell, dict &/*taps*/) override + virtual Cell* fixup(Cell *cell, const vector &/*taps*/, const vector &qbits) override { auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); - newcell->setParam("\\INIT", cell->getParam("\\INIT")); if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", - "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { + "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { int param_clkpol = -1; int param_enpol = 2; if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; @@ -176,6 +188,7 @@ struct ShregmapTechXilinx7Static : ShregmapTech log_assert(param_clkpol >= 0); newcell->setParam("\\CLKPOL", param_clkpol); newcell->setParam("\\ENPOL", param_enpol); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); if (cell->hasPort("\\E")) newcell->setPort("\\E", cell->getPort("\\E")); @@ -187,11 +200,12 @@ struct ShregmapTechXilinx7Static : ShregmapTech param_clkpol = 0; newcell->setParam("\\CLKPOL", param_clkpol); newcell->setParam("\\ENPOL", 1); - - newcell->setPort("\\E", cell->getPort("\\CE")); - } - else if (cell->type.in("$__SHREG_FDRE_1", "$__SHREG_FDSE_1", "$__SHREG_FDCE_1", "$__SHREG_FDPE_1")) { - newcell->setParam("\\CLKPOL", 0); + log_assert(cell->getParam("\\INIT").is_fully_undef()); + SigSpec INIT; + for (auto q : qbits) { + Cell* reg = sigbit_to_cell.at(q); + INIT.append(SigBit(reg->getParam("\\INIT").as_bool())); + } newcell->setPort("\\E", cell->getPort("\\CE")); } @@ -314,15 +328,14 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static return true; } - virtual Cell* fixup(Cell *cell, dict &taps) override + virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) override { - const auto &tap = *taps.begin(); - auto bit = tap.second; + auto bit = qbits[taps.front()]; auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); + Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps, qbits); log_assert(newcell); log_assert(newcell->type == "$__SHREG_"); newcell->type = "$__XILINX_SHREG_"; @@ -493,7 +506,8 @@ struct ShregmapWorker Cell *first_cell = chain[cursor]; IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; + vector qbits; + vector taps; if (opts.tech) { @@ -502,9 +516,6 @@ struct ShregmapWorker continue; } - vector qbits; - vector taps; - for (int i = 0; i < depth; i++) { Cell *cell = chain[cursor+i]; @@ -529,7 +540,6 @@ struct ShregmapWorker depth = 0; for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); log_assert(depth < tap+1); depth = tap+1; } @@ -600,7 +610,7 @@ struct ShregmapWorker first_cell->setPort(q_port, last_cell->getPort(q_port)); first_cell->setParam("\\DEPTH", depth); - if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps_dict)) + if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps, qbits)) remove_cells.insert(first_cell); for (int i = 1; i < depth; i++) From 7166dbe418420bf8f0696b21bff22d5f66a4cc8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:35:38 -0700 Subject: [PATCH 349/514] Remove abc_flop attributes for now --- techlibs/xilinx/cells_sim.v | 66 ++++++------------------------------- 1 file changed, 10 insertions(+), 56 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index e00992bb7..88967b068 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -205,126 +205,80 @@ endmodule `endif -(* abc_box_id = 6, abc_flop /*, lib_whitebox */ *) -module FDRE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input R); +module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; -`ifndef _ABC generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`else - always @* if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; -`endif endmodule -(* abc_box_id = 7, abc_flop /*, lib_whitebox*/ *) -module FDSE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input S); +module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; -`ifndef _ABC generate case (|IS_C_INVERTED) 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`else - always @* if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; -`endif endmodule -(* abc_box_id = 8, abc_flop /*, lib_whitebox*/ *) -module FDCE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input CLR); +module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; -`ifndef _ABC generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`else - generate case (|IS_CLR_INVERTED) - 1'b0: always @* if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @* if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate -`endif endmodule -(* abc_box_id = 9, abc_flop /*, lib_whitebox*/ *) -module FDPE ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input PRE); +module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; -`ifndef _ABC generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endcase endgenerate -`else - generate case (|IS_PRE_INVERTED) - 1'b0: always @* if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @* if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate -`endif endmodule -(* abc_box_id = 6, abc_flop /*, lib_whitebox */ *) -module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input R); +module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; initial Q <= INIT; -`ifndef _ABC - always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; -`else - always @* if (R) Q <= 1'b0; else if (CE) Q <= D; -`endif + always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; endmodule -(* abc_box_id = 7, abc_flop /*, lib_whitebox */ *) -module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input S); +module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; initial Q <= INIT; -`ifndef _ABC - always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; -`else - always @* if (S) Q <= 1'b1; else if (CE) Q <= D; - `endif + always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule -(* abc_box_id = 8, abc_flop /*, lib_whitebox */ *) -module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input CLR); +module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; initial Q <= INIT; -`ifndef _ABC always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; -`else - always @* if (CLR) Q <= 1'b0; else if (CE) Q <= D; -`endif endmodule -(* abc_box_id = 9, abc_flop /*, lib_whitebox */ *) -module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, (* abc_flop_d *) input D, input PRE); +module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; initial Q <= INIT; -`ifndef _ABC always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; -`else - always @* if (PRE) Q <= 1'b1; else if (CE) Q <= D; -`endif endmodule (* abc_box_id = 4 /*, lib_whitebox*/ *) From a8c49168fb1e5e665e126c65dc454183a6d7826b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:43:08 -0700 Subject: [PATCH 350/514] Run muxpack and muxcover in synth_xilinx --- techlibs/xilinx/cells_map.v | 12 ++++++++++++ techlibs/xilinx/synth_xilinx.cc | 7 ++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 4acf04744..8537dc479 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -250,3 +250,15 @@ module \$__XILINX_MUX_ (A, B, Y); end endgenerate endmodule + +module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); +input A, B, C, D, E, F, G, H, S, T, U; +output Y; + \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({A,B,C,D,E,F,G,H}), .B({U,T,S}), .Y(Y)); +endmodule + +module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); +input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; +output Y; + \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P}), .B({V,U,T,S}), .Y(Y)); +endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7686f2cbc..a70bb23f1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -225,6 +225,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { run("synth -run coarse"); + if (!nomux || help_mode) + run("muxpack", "(skip if '-nomux')"); + // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former @@ -286,7 +289,9 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v "); + if (!nomux || help_mode) + run("muxcover", "(skip if '-nomux')"); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); From d3b7ae218bd7641a40adfba7809cf0f8bdff31e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 15:31:18 -0700 Subject: [PATCH 351/514] Fix muxcover and its techmapping --- techlibs/xilinx/cells_map.v | 4 ++-- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 8537dc479..f0d3ebbac 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -254,11 +254,11 @@ endmodule module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); input A, B, C, D, E, F, G, H, S, T, U; output Y; - \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({A,B,C,D,E,F,G,H}), .B({U,T,S}), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); endmodule module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; output Y; - \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P}), .B({V,U,T,S}), .Y(Y)); + \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a70bb23f1..a0c2c781d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -290,7 +290,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { if (!nomux || help_mode) - run("muxcover", "(skip if '-nomux')"); + run("muxcover -mux8 -mux16", "(skip if '-nomux')"); run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); From 88ae13e6a55a36eb66de2424a6138b984ffb6a9e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 15:32:36 -0700 Subject: [PATCH 352/514] $__XILINX_MUX_ -> $__XILINX_SHIFTX --- techlibs/xilinx/cells_map.v | 18 +++++++++--------- techlibs/xilinx/mux_map.v | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f0d3ebbac..f8f9356bc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -143,7 +143,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule -module \$__XILINX_MUX_ (A, B, Y); +module \$__XILINX_SHIFTX (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -178,7 +178,7 @@ module \$__XILINX_MUX_ (A, B, Y); // Bit-blast if (Y_WIDTH > 1) begin for (i = 0; i < Y_WIDTH; i++) - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); end // If the LSB of B is constant zero (and Y_WIDTH is 1) then // we can optimise by removing every other entry from A @@ -187,13 +187,13 @@ module \$__XILINX_MUX_ (A, B, Y); wire [(A_WIDTH+1)/2-1:0] A_i; for (i = 0; i < (A_WIDTH+1)/2; i++) assign A_i[i] = A[i*2]; - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end // Trim off any leading 1'bx -es in A, and resize B accordingly else if (num_leading_X_in_A > 0) begin localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; localparam B_WIDTH_new = $clog2(A_WIDTH_new); - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); end else if (B_WIDTH < 3 || A_WIDTH <= 4) begin \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); @@ -237,16 +237,16 @@ module \$__XILINX_MUX_ (A, B, Y); wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin if (a_widthN > 1) - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; end else assign T[i] = 1'bx; - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule @@ -254,11 +254,11 @@ endmodule module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); input A, B, C, D, E, F, G, H, S, T, U; output Y; - \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); endmodule module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; output Y; - \$__XILINX_MUX_ #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); endmodule diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 2ad7f7671..0fa8db736 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -38,7 +38,7 @@ module \$shiftx (A, B, Y); if (B_SIGNED) begin if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); else wire _TECHMAP_FAIL_ = 1; end @@ -46,7 +46,7 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else begin - \$__XILINX_MUX_ #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); end endgenerate endmodule From fe4394fb9aacfaee840d2c72b88c5da666fbcb28 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 08:30:39 -0700 Subject: [PATCH 353/514] Allow muxcover costs to be changed --- passes/techmap/muxcover.cc | 54 +++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 12da9ed0c..32102436d 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -58,12 +58,21 @@ struct MuxcoverWorker bool use_mux16; bool nodecode; + int cost_mux2; + int cost_mux4; + int cost_mux8; + int cost_mux16; + MuxcoverWorker(Module *module) : module(module), sigmap(module) { use_mux4 = false; use_mux8 = false; use_mux16 = false; nodecode = false; + cost_mux2 = COST_MUX2; + cost_mux4 = COST_MUX4; + cost_mux8 = COST_MUX8; + cost_mux16 = COST_MUX16; decode_mux_counter = 0; } @@ -157,7 +166,7 @@ struct MuxcoverWorker if (std::get<2>(entry)) return 0; - return COST_MUX2 / GetSize(std::get<1>(entry)); + return cost_mux2 / GetSize(std::get<1>(entry)); } void implement_decode_mux(SigBit ctrl_bit) @@ -209,7 +218,7 @@ struct MuxcoverWorker mux.inputs.push_back(B); mux.selects.push_back(S1); - mux.cost += COST_MUX2; + mux.cost += cost_mux2; mux.cost += find_best_cover(tree, A); mux.cost += find_best_cover(tree, B); @@ -247,7 +256,7 @@ struct MuxcoverWorker mux.selects.push_back(S1); mux.selects.push_back(T1); - mux.cost += COST_MUX4; + mux.cost += cost_mux4; mux.cost += find_best_cover(tree, A); mux.cost += find_best_cover(tree, B); mux.cost += find_best_cover(tree, C); @@ -310,7 +319,7 @@ struct MuxcoverWorker mux.selects.push_back(T1); mux.selects.push_back(U1); - mux.cost += COST_MUX8; + mux.cost += cost_mux8; mux.cost += find_best_cover(tree, A); mux.cost += find_best_cover(tree, B); mux.cost += find_best_cover(tree, C); @@ -414,7 +423,7 @@ struct MuxcoverWorker mux.selects.push_back(U1); mux.selects.push_back(V1); - mux.cost += COST_MUX16; + mux.cost += cost_mux16; mux.cost += find_best_cover(tree, A); mux.cost += find_best_cover(tree, B); mux.cost += find_best_cover(tree, C); @@ -569,9 +578,11 @@ struct MuxcoverPass : public Pass { log("\n"); log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); log("\n"); - log(" -mux4, -mux8, -mux16\n"); - log(" Use the specified types of MUXes. If none of those options are used,\n"); - log(" the effect is the same as if all of them where used.\n"); + log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); + log(" Use the specified types of MUXes (with optional integer costs). If none\n"); + log(" of these options are given, the effect is the same as if all of them are.\n"); + log(" Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4); + log(" $_MUX8_ = %d, $_MUX16_ = %d\n", COST_MUX8, COST_MUX16); log("\n"); log(" -nodecode\n"); log(" Do not insert decoder logic. This reduces the number of possible\n"); @@ -587,23 +598,39 @@ struct MuxcoverPass : public Pass { bool use_mux8 = false; bool use_mux16 = false; bool nodecode = false; + int cost_mux4 = COST_MUX4; + int cost_mux8 = COST_MUX8; + int cost_mux16 = COST_MUX16; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-mux4") { + const auto &arg = args[argidx]; + if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") { use_mux4 = true; + if (arg.size() > 5) { + if (arg[5] != '=') break; + cost_mux4 = atoi(arg.substr(5).c_str()); + } continue; } - if (args[argidx] == "-mux8") { + if (arg.size() >= 5 && arg.substr(0,5) == "-mux8") { use_mux8 = true; + if (arg.size() > 5) { + if (arg[5] != '=') break; + cost_mux8 = atoi(arg.substr(5).c_str()); + } continue; } - if (args[argidx] == "-mux16") { + if (arg.size() >= 6 && arg.substr(0,6) == "-mux16") { use_mux16 = true; + if (arg.size() > 6) { + if (arg[6] != '=') break; + cost_mux16 = atoi(arg.substr(6).c_str()); + } continue; } - if (args[argidx] == "-nodecode") { + if (arg == "-nodecode") { nodecode = true; continue; } @@ -623,6 +650,9 @@ struct MuxcoverPass : public Pass { worker.use_mux4 = use_mux4; worker.use_mux8 = use_mux8; worker.use_mux16 = use_mux16; + worker.cost_mux4 = cost_mux4; + worker.cost_mux8 = cost_mux8; + worker.cost_mux16 = cost_mux16; worker.nodecode = nodecode; worker.run(); } From 5a46a0b38584014c3644cc434458638874bd4d75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 16:57:32 -0700 Subject: [PATCH 354/514] Fine tune aigerparse --- frontends/aiger/aigerparse.cc | 89 +++++++++++------------------------ passes/techmap/abc9.cc | 6 ++- 2 files changed, 32 insertions(+), 63 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 20b43c3d3..4c19ec171 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -85,21 +85,10 @@ end_of_header: else log_abort(); - RTLIL::Wire* n0 = module->wire("\\n0"); + RTLIL::Wire* n0 = module->wire("\\__0__"); if (n0) module->connect(n0, RTLIL::S0); - for (unsigned i = 0; i < outputs.size(); ++i) { - RTLIL::Wire *wire = outputs[i]; - if (wire->port_input) { - RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o"); - o_wire->port_output = true; - wire->port_output = false; - module->connect(o_wire, wire); - outputs[i] = o_wire; - } - } - // Parse footer (symbol table, comments, etc.) unsigned l1; std::string s; @@ -212,6 +201,10 @@ void AigerReader::parse_xaiger() else log_abort(); + RTLIL::Wire* n0 = module->wire("\\__0__"); + if (n0) + module->connect(n0, RTLIL::S0); + dict box_lookup; for (auto m : design->modules()) { auto it = m->attributes.find("\\abc_box_id"); @@ -386,31 +379,17 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - RTLIL::Wire *wire; - if (l1 == 0 || l1 == 1) { - wire = module->addWire(NEW_ID); - if (l1 == 0) - module->connect(wire, RTLIL::State::S0); - else if (l1 == 1) - module->connect(wire, RTLIL::State::S1); - else - log_abort(); - } - else { - log_debug("%d is an output\n", l1); - const unsigned variable = l1 >> 1; - const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? - wire = module->wire(wire_name); - if (!wire) - wire = createWireIfNotExists(module, l1); - else { - if (wire->port_input || wire->port_output) { - RTLIL::Wire *new_wire = module->addWire(NEW_ID); - module->connect(new_wire, wire); - wire = new_wire; - } - } + log_debug("%d is an output\n", l1); + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else if (wire->port_input || wire->port_output) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; } wire->port_output = true; outputs.push_back(wire); @@ -525,31 +504,17 @@ void AigerReader::parse_aiger_binary() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - RTLIL::Wire *wire; - if (l1 == 0 || l1 == 1) { - wire = module->addWire(NEW_ID); - if (l1 == 0) - module->connect(wire, RTLIL::State::S0); - else if (l1 == 1) - module->connect(wire, RTLIL::State::S1); - else - log_abort(); - } - else { - log_debug("%d is an output\n", l1); - const unsigned variable = l1 >> 1; - const bool invert = l1 & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? - wire = module->wire(wire_name); - if (!wire) - wire = createWireIfNotExists(module, l1); - else { - if (wire->port_input || wire->port_output) { - RTLIL::Wire *new_wire = module->addWire(NEW_ID); - module->connect(new_wire, wire); - wire = new_wire; - } - } + log_debug("%d is an output\n", l1); + const unsigned variable = l1 >> 1; + const bool invert = l1 & 1; + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (!wire) + wire = createWireIfNotExists(module, l1); + else if (wire->port_input || wire->port_output) { + RTLIL::Wire *new_wire = module->addWire(NEW_ID); + module->connect(new_wire, wire); + wire = new_wire; } wire->port_output = true; outputs.push_back(wire); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 06a638558..af9439e41 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -586,7 +586,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Cell *cell; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); - if (!lut_costs.empty() || !lut_file.empty()) { + if (!a_bit.wire) { + c->setPort("\\Y", module->addWire(NEW_ID)); + module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1); + } + else if (!lut_costs.empty() || !lut_file.empty()) { RTLIL::Cell* driving_lut = nullptr; // ABC can return NOT gates that drive POs if (!a_bit.wire->port_input) { From 816b5f5891adfa71586991824e9db24e7e73604a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 16:58:57 -0700 Subject: [PATCH 355/514] Comment out muxpack (currently broken) --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a0c2c781d..ffdb22960 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -225,8 +225,8 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { run("synth -run coarse"); - if (!nomux || help_mode) - run("muxpack", "(skip if '-nomux')"); + //if (!nomux || help_mode) + // run("muxpack", "(skip if '-nomux')"); // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, From d5f0b73fd9ff3a5d015faf566adcebdc29bab2b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 17:00:36 -0700 Subject: [PATCH 356/514] Update CHANGELOG --- CHANGELOG | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 149443c74..c1b548aeb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,12 +16,10 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass -<<<<<<< HEAD - - Added "muxpack" pass -======= - Added "read_aiger" frontend ->>>>>>> origin/master + - Added "muxpack" pass - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" + - "synth_xilinx" to now infer wide multiplexers Yosys 0.7 .. Yosys 0.8 From 9d8563178e930fe30bf4dd35b4a0306a1bd85d92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:12 -0700 Subject: [PATCH 357/514] Revert "shregmap -tech xilinx_static to handle INIT" This reverts commit 935df3569b4677ac38041ff01a2f67185681f4e3. --- passes/techmap/shregmap.cc | 54 ++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index e4c811cfb..3fe383b86 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -30,7 +30,7 @@ struct ShregmapTech virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} virtual bool analyze_first(const Cell* /*first_cell*/, const SigMap &/*sigmap*/) { return true; } virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) = 0; + virtual Cell* fixup(Cell *cell, dict &taps) = 0; }; struct ShregmapOptions @@ -72,7 +72,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) override + virtual Cell* fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -84,8 +84,8 @@ struct ShregmapTechGreenpak4 : ShregmapTech int i = 0; for (auto tap : taps) { - newcell->setPort(i ? "\\OUTB" : "\\OUTA", qbits[tap]); - newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap + 1); + newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second); + newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap.first + 1); i++; } @@ -96,21 +96,8 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7Static : ShregmapTech { - dict sigbit_to_cell; const ShregmapOptions &opts; - virtual void init(const Module* module, const SigMap &sigmap) override - { - for (const auto &i : module->cells_) { - auto cell = i.second; - if (!cell->type.in("\\FDRE", "\\FDRE_1","\\FDSE", "\\FDSE_1", - "\\FDCE", "\\FDCE_1", "\\FDPE", "\\FDPE_1")) - continue; - - sigbit_to_cell[sigmap(cell->getPort("\\Q"))] = cell; - } - } - ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} virtual bool analyze_first(const Cell* first_cell, const SigMap &sigmap) override @@ -167,14 +154,15 @@ struct ShregmapTechXilinx7Static : ShregmapTech return GetSize(taps) == 1 && taps[0] >= opts.minlen-1; } - virtual Cell* fixup(Cell *cell, const vector &/*taps*/, const vector &qbits) override + virtual Cell* fixup(Cell *cell, dict &/*taps*/) override { auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", - "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { + "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { int param_clkpol = -1; int param_enpol = 2; if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; @@ -188,7 +176,6 @@ struct ShregmapTechXilinx7Static : ShregmapTech log_assert(param_clkpol >= 0); newcell->setParam("\\CLKPOL", param_clkpol); newcell->setParam("\\ENPOL", param_enpol); - newcell->setParam("\\INIT", cell->getParam("\\INIT")); if (cell->hasPort("\\E")) newcell->setPort("\\E", cell->getPort("\\E")); @@ -200,12 +187,11 @@ struct ShregmapTechXilinx7Static : ShregmapTech param_clkpol = 0; newcell->setParam("\\CLKPOL", param_clkpol); newcell->setParam("\\ENPOL", 1); - log_assert(cell->getParam("\\INIT").is_fully_undef()); - SigSpec INIT; - for (auto q : qbits) { - Cell* reg = sigbit_to_cell.at(q); - INIT.append(SigBit(reg->getParam("\\INIT").as_bool())); - } + + newcell->setPort("\\E", cell->getPort("\\CE")); + } + else if (cell->type.in("$__SHREG_FDRE_1", "$__SHREG_FDSE_1", "$__SHREG_FDCE_1", "$__SHREG_FDPE_1")) { + newcell->setParam("\\CLKPOL", 0); newcell->setPort("\\E", cell->getPort("\\CE")); } @@ -328,14 +314,15 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static return true; } - virtual Cell* fixup(Cell *cell, const vector &taps, const vector &qbits) override + virtual Cell* fixup(Cell *cell, dict &taps) override { - auto bit = qbits[taps.front()]; + const auto &tap = *taps.begin(); + auto bit = tap.second; auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps, qbits); + Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); log_assert(newcell); log_assert(newcell->type == "$__SHREG_"); newcell->type = "$__XILINX_SHREG_"; @@ -506,8 +493,7 @@ struct ShregmapWorker Cell *first_cell = chain[cursor]; IdString q_port = opts.ffcells.at(first_cell->type).second; - vector qbits; - vector taps; + dict taps_dict; if (opts.tech) { @@ -516,6 +502,9 @@ struct ShregmapWorker continue; } + vector qbits; + vector taps; + for (int i = 0; i < depth; i++) { Cell *cell = chain[cursor+i]; @@ -540,6 +529,7 @@ struct ShregmapWorker depth = 0; for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); log_assert(depth < tap+1); depth = tap+1; } @@ -610,7 +600,7 @@ struct ShregmapWorker first_cell->setPort(q_port, last_cell->getPort(q_port)); first_cell->setParam("\\DEPTH", depth); - if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps, qbits)) + if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps_dict)) remove_cells.insert(first_cell); for (int i = 1; i < depth; i++) From e1dbeb3004873ae6914bd84e2020a34f8867477b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:14 -0700 Subject: [PATCH 358/514] Revert "Continue support for ShregmapTechXilinx7Static" This reverts commit 72eda94a66c8c4938a713c9ae49d560e6b33574f. --- passes/techmap/shregmap.cc | 111 ++++++++++--------------------------- 1 file changed, 30 insertions(+), 81 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3fe383b86..a1483fab5 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -28,9 +28,8 @@ struct ShregmapTech virtual ~ShregmapTech() { } virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} - virtual bool analyze_first(const Cell* /*first_cell*/, const SigMap &/*sigmap*/) { return true; } virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual Cell* fixup(Cell *cell, dict &taps) = 0; + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) = 0; }; struct ShregmapOptions @@ -72,7 +71,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual Cell* fixup(Cell *cell, dict &taps) override + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -100,61 +99,18 @@ struct ShregmapTechXilinx7Static : ShregmapTech ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} - virtual bool analyze_first(const Cell* first_cell, const SigMap &sigmap) override + virtual bool analyze(vector &taps, const vector &/*qbits*/) override { - if (first_cell->type.in("\\FDRE", "\\FDRE_1")) { - bool is_R_inverted = false; - if (first_cell->hasParam("\\IS_R_INVERTED")) - is_R_inverted = first_cell->getParam("\\IS_R_INVERTED").as_bool(); - SigBit R = sigmap(first_cell->getPort("\\R")); - if (R != RTLIL::S0 && R != RTLIL::S1) - return false; - if ((!is_R_inverted && R != RTLIL::S0) || (is_R_inverted && R != RTLIL::S1)) - return false; - return true; - } - if (first_cell->type.in("\\FDSE", "\\FDSE_1")) { - bool is_S_inverted = false; - if (first_cell->hasParam("\\IS_S_INVERTED")) - is_S_inverted = first_cell->getParam("\\IS_S_INVERTED").as_bool(); - SigBit S = sigmap(first_cell->getPort("\\S")); - if (S != RTLIL::S0 && S != RTLIL::S1) - return false; - if ((!is_S_inverted && S != RTLIL::S0) || (is_S_inverted && S != RTLIL::S1)) - return false; - return true; - } - if (first_cell->type.in("\\FDCE", "\\FDCE_1")) { - bool is_CLR_inverted = false; - if (first_cell->hasParam("\\IS_CLR_INVERTED")) - is_CLR_inverted = first_cell->getParam("\\IS_CLR_INVERTED").as_bool(); - SigBit CLR = sigmap(first_cell->getPort("\\CLR")); - if (CLR != RTLIL::S0 && CLR != RTLIL::S1) - return false; - if ((!is_CLR_inverted && CLR != RTLIL::S0) || (is_CLR_inverted && CLR != RTLIL::S1)) - return false; - return true; - } - if (first_cell->type.in("\\FDPE", "\\FDPE_1")) { - bool is_PRE_inverted = false; - if (first_cell->hasParam("\\IS_PRE_INVERTED")) - is_PRE_inverted = first_cell->getParam("\\IS_PRE_INVERTED").as_bool(); - SigBit PRE = sigmap(first_cell->getPort("\\PRE")); - if (PRE != RTLIL::S0 && PRE != RTLIL::S1) - return false; - if ((!is_PRE_inverted && PRE != RTLIL::S0) || (is_PRE_inverted && PRE != RTLIL::S1)) - return false; - return true; - } + if (GetSize(taps) == 1) + return taps[0] >= opts.minlen-1; + + if (taps.back() < opts.minlen-1) + return false; + return true; } - virtual bool analyze(vector &taps, const vector &/*qbits*/) override - { - return GetSize(taps) == 1 && taps[0] >= opts.minlen-1; - } - - virtual Cell* fixup(Cell *cell, dict &/*taps*/) override + virtual RTLIL::Cell* fixup(Cell *cell, dict &/*taps*/) override { auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); newcell->set_src_attribute(cell->get_src_attribute()); @@ -180,17 +136,16 @@ struct ShregmapTechXilinx7Static : ShregmapTech if (cell->hasPort("\\E")) newcell->setPort("\\E", cell->getPort("\\E")); } - else if (cell->type.in("$__SHREG_FDRE", "$__SHREG_FDRE_1","$__SHREG_FDSE", "$__SHREG_FDSE_1", - "$__SHREG_FDCE", "$__SHREG_FDCE_1", "$__SHREG_FDPE", "$__SHREG_FDPE_1")) { - int param_clkpol = 1; - if (cell->hasParam("\\IS_C_INVERTED") && cell->getParam("\\IS_C_INVERTED").as_bool()) - param_clkpol = 0; - newcell->setParam("\\CLKPOL", param_clkpol); + else if (cell->type.in("$__SHREG_FDRE_", "$__SHREG_FDSE_", "$__SHREG_FDCE_", "$__SHREG_FDPE_")) { + if (cell->getParam("\\IS_C_INVERTED").as_bool()) + newcell->setParam("\\CLKPOL", 0); + else + newcell->setParam("\\CLKPOL", 1); newcell->setParam("\\ENPOL", 1); newcell->setPort("\\E", cell->getPort("\\CE")); } - else if (cell->type.in("$__SHREG_FDRE_1", "$__SHREG_FDSE_1", "$__SHREG_FDCE_1", "$__SHREG_FDPE_1")) { + else if (cell->type.in("$__SHREG_FDRE_1_", "$__SHREG_FDSE_1_", "$__SHREG_FDCE_1_", "$__SHREG_FDPE_1_")) { newcell->setParam("\\CLKPOL", 0); newcell->setPort("\\E", cell->getPort("\\CE")); @@ -260,14 +215,13 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static Cell *shiftx = nullptr; int group = 0; for (int i = 0; i < GetSize(taps); ++i) { - // Check taps are sequential - if (i != taps[i]) - return false; - auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (it == sigbit_to_shiftx_offset.end()) return false; + // Check taps are sequential + if (i != taps[i]) + return false; // Check taps are not connected to a shift register, // or sequential to the same shift register if (i == 0) { @@ -314,7 +268,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static return true; } - virtual Cell* fixup(Cell *cell, dict &taps) override + virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override { const auto &tap = *taps.begin(); auto bit = tap.second; @@ -322,7 +276,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); + RTLIL::Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); log_assert(newcell); log_assert(newcell->type == "$__SHREG_"); newcell->type = "$__XILINX_SHREG_"; @@ -497,11 +451,6 @@ struct ShregmapWorker if (opts.tech) { - if (!opts.tech->analyze_first(first_cell, sigmap)) { - cursor += depth; - continue; - } - vector qbits; vector taps; @@ -778,16 +727,16 @@ struct ShregmapPass : public Pass { opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["\\FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.ffcells["FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); if (tech == "xilinx_static") - opts.tech = new ShregmapTechXilinx7Static(opts); + opts.tech = new ShregmapTechXilinx7Dynamic(opts); else if (tech == "xilinx_dynamic") opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { From b6a39351f4e82ee00f95d3168fe26a62090166b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:14 -0700 Subject: [PATCH 359/514] Revert "Add -tech xilinx_static" This reverts commit dfe9d95579ab98d7518d40e427af858243de4eb3. --- passes/techmap/shregmap.cc | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a1483fab5..c8971170a 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -719,7 +719,7 @@ struct ShregmapPass : public Pass { opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; } - else if (tech == "xilinx_static" || tech == "xilinx_dynamic") { + else if (tech == "xilinx_dynamic") { opts.init = true; opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q")); @@ -727,18 +727,7 @@ struct ShregmapPass : public Pass { opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDRE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDRE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDSE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDSE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDCE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDCE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDPE"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["FDPE_1"] = make_pair(IdString("\\D"), IdString("\\Q")); - if (tech == "xilinx_static") - opts.tech = new ShregmapTechXilinx7Dynamic(opts); - else if (tech == "xilinx_dynamic") - opts.tech = new ShregmapTechXilinx7Dynamic(opts); + opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { argidx--; break; From 3579d681935da5bb03876d0d562e5f4b556feabe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:15 -0700 Subject: [PATCH 360/514] Revert "Refactor to ShregmapTechXilinx7Static" This reverts commit e1e37db86073e545269ff440da77f57135e8b155. --- passes/techmap/shregmap.cc | 140 +++++++++++++------------------------ 1 file changed, 50 insertions(+), 90 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index c8971170a..91a942c39 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -29,7 +29,7 @@ struct ShregmapTech virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} virtual bool analyze(vector &taps, const vector &qbits) = 0; - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) = 0; + virtual bool fixup(Cell *cell, dict &taps) = 0; }; struct ShregmapOptions @@ -71,7 +71,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override + virtual bool fixup(Cell *cell, dict &taps) override { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -89,84 +89,16 @@ struct ShregmapTechGreenpak4 : ShregmapTech } cell->setParam("\\OUTA_INVERT", 0); - return newcell; + return false; } }; -struct ShregmapTechXilinx7Static : ShregmapTech -{ - const ShregmapOptions &opts; - - ShregmapTechXilinx7Static(const ShregmapOptions &opts) : opts(opts) {} - - virtual bool analyze(vector &taps, const vector &/*qbits*/) override - { - if (GetSize(taps) == 1) - return taps[0] >= opts.minlen-1; - - if (taps.back() < opts.minlen-1) - return false; - - return true; - } - - virtual RTLIL::Cell* fixup(Cell *cell, dict &/*taps*/) override - { - auto newcell = cell->module->addCell(NEW_ID, "$__SHREG_"); - newcell->set_src_attribute(cell->get_src_attribute()); - newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); - newcell->setParam("\\INIT", cell->getParam("\\INIT")); - - if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", - "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { - int param_clkpol = -1; - int param_enpol = 2; - if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; - else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; - else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - else log_abort(); - - log_assert(param_clkpol >= 0); - newcell->setParam("\\CLKPOL", param_clkpol); - newcell->setParam("\\ENPOL", param_enpol); - - if (cell->hasPort("\\E")) - newcell->setPort("\\E", cell->getPort("\\E")); - } - else if (cell->type.in("$__SHREG_FDRE_", "$__SHREG_FDSE_", "$__SHREG_FDCE_", "$__SHREG_FDPE_")) { - if (cell->getParam("\\IS_C_INVERTED").as_bool()) - newcell->setParam("\\CLKPOL", 0); - else - newcell->setParam("\\CLKPOL", 1); - newcell->setParam("\\ENPOL", 1); - - newcell->setPort("\\E", cell->getPort("\\CE")); - } - else if (cell->type.in("$__SHREG_FDRE_1_", "$__SHREG_FDSE_1_", "$__SHREG_FDCE_1_", "$__SHREG_FDPE_1_")) { - newcell->setParam("\\CLKPOL", 0); - - newcell->setPort("\\E", cell->getPort("\\CE")); - } - else log_abort(); - - newcell->setParam("\\ENPOL", 1); - - newcell->setPort("\\C", cell->getPort("\\C")); - newcell->setPort("\\D", cell->getPort("\\D")); - newcell->setPort("\\Q", cell->getPort("\\Q")); - - return newcell; - } -}; - -struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static +struct ShregmapTechXilinx7Dynamic : ShregmapTech { dict> sigbit_to_shiftx_offset; + const ShregmapOptions &opts; - ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : ShregmapTechXilinx7Static(opts) {} + ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : opts(opts) {} virtual void init(const Module* module, const SigMap &sigmap) override { @@ -268,7 +200,7 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static return true; } - virtual RTLIL::Cell* fixup(Cell *cell, dict &taps) override + virtual bool fixup(Cell *cell, dict &taps) override { const auto &tap = *taps.begin(); auto bit = tap.second; @@ -276,24 +208,52 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTechXilinx7Static auto it = sigbit_to_shiftx_offset.find(bit); log_assert(it != sigbit_to_shiftx_offset.end()); - RTLIL::Cell* newcell = ShregmapTechXilinx7Static::fixup(cell, taps); - log_assert(newcell); - log_assert(newcell->type == "$__SHREG_"); - newcell->type = "$__XILINX_SHREG_"; + auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); + newcell->set_src_attribute(cell->get_src_attribute()); + newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); - Cell* shiftx = std::get<0>(it->second); - RTLIL::SigSpec l_wire; - if (shiftx->type == "$shiftx") - l_wire = shiftx->getPort("\\B"); - else if (shiftx->type == "$mux") - l_wire = shiftx->getPort("\\S"); + if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", + "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { + int param_clkpol = -1; + int param_enpol = 2; + if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; + else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; + else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + else log_abort(); + + log_assert(param_clkpol >= 0); + cell->setParam("\\CLKPOL", param_clkpol); + cell->setParam("\\ENPOL", param_enpol); + } else log_abort(); - newcell->setPort("\\L", l_wire); - newcell->setPort("\\Q", shiftx->getPort("\\Y")); - shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); + newcell->setPort("\\C", cell->getPort("\\C")); + newcell->setPort("\\D", cell->getPort("\\D")); + if (cell->hasPort("\\E")) + newcell->setPort("\\E", cell->getPort("\\E")); - return newcell; + Cell* shiftx = std::get<0>(it->second); + RTLIL::SigSpec l_wire, q_wire; + if (shiftx->type == "$shiftx") { + l_wire = shiftx->getPort("\\B"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); + } + else if (shiftx->type == "$mux") { + l_wire = shiftx->getPort("\\S"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); + } + else log_abort(); + + newcell->setPort("\\Q", q_wire); + newcell->setPort("\\L", l_wire); + + return false; } }; @@ -549,7 +509,7 @@ struct ShregmapWorker first_cell->setPort(q_port, last_cell->getPort(q_port)); first_cell->setParam("\\DEPTH", depth); - if (opts.tech != nullptr && opts.tech->fixup(first_cell, taps_dict)) + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) remove_cells.insert(first_cell); for (int i = 1; i < depth; i++) From 7d27e1e4312499b72d253470c97cfbf98e4c9d8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:16 -0700 Subject: [PATCH 361/514] Revert "shregmap -tech xilinx_dynamic to work -params and -enpol" This reverts commit 45d1bdf83ae6d51628e917b66f1b6043c8a3baee. --- passes/techmap/shregmap.cc | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 91a942c39..60b04be6f 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -56,7 +56,7 @@ struct ShregmapOptions struct ShregmapTechGreenpak4 : ShregmapTech { - virtual bool analyze(vector &taps, const vector &/*qbits*/) override + bool analyze(vector &taps, const vector &/*qbits*/) { if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) { taps.clear(); @@ -71,7 +71,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech return true; } - virtual bool fixup(Cell *cell, dict &taps) override + bool fixup(Cell *cell, dict &taps) { auto D = cell->getPort("\\D"); auto C = cell->getPort("\\C"); @@ -212,24 +212,8 @@ struct ShregmapTechXilinx7Dynamic : ShregmapTech newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); newcell->setParam("\\INIT", cell->getParam("\\INIT")); - - if (cell->type.in("$__SHREG_DFF_N_", "$__SHREG_DFF_P_", - "$__SHREG_DFFE_NN_", "$__SHREG_DFFE_NP_", "$__SHREG_DFFE_PN_", "$__SHREG_DFFE_PP_")) { - int param_clkpol = -1; - int param_enpol = 2; - if (cell->type == "$__SHREG_DFF_N_") param_clkpol = 0; - else if (cell->type == "$__SHREG_DFF_P_") param_clkpol = 1; - else if (cell->type == "$__SHREG_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - else if (cell->type == "$__SHREG_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - else if (cell->type == "$__SHREG_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - else log_abort(); - - log_assert(param_clkpol >= 0); - cell->setParam("\\CLKPOL", param_clkpol); - cell->setParam("\\ENPOL", param_enpol); - } - else log_abort(); + newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); + newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL")); newcell->setPort("\\C", cell->getPort("\\C")); newcell->setPort("\\D", cell->getPort("\\D")); @@ -681,12 +665,8 @@ struct ShregmapPass : public Pass { } else if (tech == "xilinx_dynamic") { opts.init = true; - opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["$_DFFE_PP_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); - opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); + opts.params = true; + enpol = "any_or_none"; opts.tech = new ShregmapTechXilinx7Dynamic(opts); } else { argidx--; From a1d4ae78a0ee474af6782bc5e12d8bd1fc790f04 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:43 -0700 Subject: [PATCH 362/514] Revert "Rename shregmap -tech xilinx -> xilinx_dynamic" This reverts commit 94a5f4e60985fc1e3fea75eec85638fa29874bea. --- passes/techmap/shregmap.cc | 8 ++++---- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 60b04be6f..21dfe9619 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -93,12 +93,12 @@ struct ShregmapTechGreenpak4 : ShregmapTech } }; -struct ShregmapTechXilinx7Dynamic : ShregmapTech +struct ShregmapTechXilinx7 : ShregmapTech { dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; - ShregmapTechXilinx7Dynamic(const ShregmapOptions &opts) : opts(opts) {} + ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} virtual void init(const Module* module, const SigMap &sigmap) override { @@ -663,11 +663,11 @@ struct ShregmapPass : public Pass { opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; } - else if (tech == "xilinx_dynamic") { + else if (tech == "xilinx") { opts.init = true; opts.params = true; enpol = "any_or_none"; - opts.tech = new ShregmapTechXilinx7Dynamic(opts); + opts.tech = new ShregmapTechXilinx7(opts); } else { argidx--; break; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ffdb22960..689a40135 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -266,8 +266,8 @@ struct SynthXilinxPass : public ScriptPass // shregmap operates on bit-level flops, not word-level, // so break those down here run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); - // shregmap to infer variable length shift regs - run("shregmap -tech xilinx_dynamic -minlen 3", "(skip if '-nosrl')"); + // shregmap with '-tech xilinx' infers variable length shift regs + run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } std::string techmap_files = " -map +/techmap.v"; From b77c5da76919f7f99f171a0a2775896fbc8debc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:37:09 -0700 Subject: [PATCH 363/514] Revert "Revert "Move ff_map back after ABC for shregmap"" This reverts commit e473e7456545d702c011ee7872956f94a8522865. --- techlibs/xilinx/synth_xilinx.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 689a40135..f5f8c43e0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -291,9 +291,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { if (!nomux || help_mode) run("muxcover -mux8 -mux16", "(skip if '-nomux')"); - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); - run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); + run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } @@ -309,8 +307,10 @@ struct SynthXilinxPass : public ScriptPass // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode) - run("shregmap -tech xilinx_static -minlen 3", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"); + run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); + run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); } From 8a708d1fdb662f86a46720200fa15acafde30333 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 12:02:31 -0700 Subject: [PATCH 364/514] Remove #ifndef ABC --- techlibs/xilinx/cells_sim.v | 4 ---- 1 file changed, 4 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 88967b068..14e35737e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -295,10 +295,8 @@ module RAM64X1D ( reg [63:0] mem = INIT; assign SPO = mem[a]; assign DPO = mem[dpra]; -`ifndef _ABC wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[a] <= D; -`endif endmodule (* abc_box_id = 5 /*, lib_whitebox*/ *) @@ -312,10 +310,8 @@ module RAM128X1D ( reg [127:0] mem = INIT; assign SPO = mem[A]; assign DPO = mem[DPRA]; -`ifndef _ABC wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[A] <= D; -`endif endmodule module SRL16E ( From 54379f9872ba3abdf5328994abcf5abfc7288c6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 12:02:51 -0700 Subject: [PATCH 365/514] Disable dist RAM boxes due to comb loop --- techlibs/xilinx/cells_sim.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 14e35737e..d9aa36666 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,7 +281,7 @@ module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4 /*, lib_whitebox*/ *) +//(* abc_box_id = 4 /*, lib_whitebox*/ *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -299,7 +299,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 5 /*, lib_whitebox*/ *) +//(* abc_box_id = 5 /*, lib_whitebox*/ *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From d26646051c4ae9740decd5d76eec6a3afd63844a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 16:05:27 -0700 Subject: [PATCH 366/514] Revert "Merge remote-tracking branch 'origin/eddie/shregmap_improve' into xc7mux" This reverts commit 5174082208ef9bea22ad1ba62622947375b3e83b, reversing changes made to 54379f9872ba3abdf5328994abcf5abfc7288c6b. --- passes/techmap/shregmap.cc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3adcd8968..46f6a79fb 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -294,8 +294,12 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); - if (!r.second) + if (!r.second) { sigbit_with_non_chain_users.insert(d_bit); + Wire *wire = module->addWire(NEW_ID); + module->connect(wire, d_bit); + sigbit_chain_next.insert(std::make_pair(wire, cell)); + } sigbit_chain_prev[q_bit] = cell; continue; @@ -315,14 +319,14 @@ struct ShregmapWorker { for (auto it : sigbit_chain_next) { - Cell *c1, *c2 = it.second; - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) goto start_cell; - c1 = sigbit_chain_prev.at(it.first, nullptr); - if (c1 != nullptr) + if (sigbit_chain_prev.count(it.first) != 0) { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; + if (c1->type != c2->type) goto start_cell; @@ -332,15 +336,6 @@ struct ShregmapWorker IdString d_port = opts.ffcells.at(c1->type).first; IdString q_port = opts.ffcells.at(c1->type).second; - // If the previous cell's D has other non chain users, - // then it is possible that this previous cell could - // be a start of the chain - SigBit d_bit = sigmap(c1->getPort(d_port).as_bit()); - if (sigbit_with_non_chain_users.count(d_bit)) { - c2 = c1; - goto start_cell; - } - auto c1_conn = c1->connections(); auto c2_conn = c1->connections(); @@ -357,7 +352,7 @@ struct ShregmapWorker } start_cell: - chain_start_cells.insert(c2); + chain_start_cells.insert(it.second); } } From 2dffa4685b830313204f5d04314a14ed6ecac8ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 17:10:47 -0700 Subject: [PATCH 367/514] Add "-W' wire delay arg to abc9, use from synth_xilinx --- frontends/verilog/verilog_lexer.l | 5 ----- passes/techmap/abc9.cc | 18 +++++++++++++----- techlibs/xilinx/synth_xilinx.cc | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 3c612472d..9558bbfb9 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -311,11 +311,6 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } -"$"(info|warning|error|fatal) { - frontend_verilog_yylval.string = new std::string(yytext); - return TOK_ELAB_TASK; -} - "$signed" { return TOK_TO_SIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index af9439e41..19157adc6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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" @@ -272,7 +272,8 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file) + const std::vector &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++; @@ -387,6 +388,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); @@ -960,7 +964,7 @@ struct Abc9Pass : public Pass { 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 lut_costs; @@ -1214,6 +1218,10 @@ struct Abc9Pass : public Pass { box_file = std::string(pwd) + "/" + box_file; continue; } + if (arg == "-W" && argidx+1 < args.size()) { + wire_delay = "-S " + args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); @@ -1256,7 +1264,7 @@ struct Abc9Pass : public Pass { 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; } @@ -1402,7 +1410,7 @@ struct Abc9Pass : public Pass { 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); } } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f5f8c43e0..f966115cd 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -297,7 +297,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { if (abc == "abc9") - run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box" + string(retime ? " -dff" : "")); + run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box -W 160" + string(retime ? " -dff" : "")); else if (help_mode) run(abc + " -luts 2:2,3,6:5,10,20 [-dff]"); else From 4c9fde87d170fc8d4b729581b055407553951e4c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:48:45 -0700 Subject: [PATCH 368/514] Revert "Add "-W' wire delay arg to abc9, use from synth_xilinx" This reverts commit 2dffa4685b830313204f5d04314a14ed6ecac8ec. --- frontends/verilog/verilog_lexer.l | 5 +++++ passes/techmap/abc9.cc | 18 +++++------------- techlibs/xilinx/synth_xilinx.cc | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 9558bbfb9..3c612472d 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -311,6 +311,11 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } +"$"(info|warning|error|fatal) { + frontend_verilog_yylval.string = new std::string(yytext); + return TOK_ELAB_TASK; +} + "$signed" { return TOK_TO_SIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 19157adc6..af9439e41 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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} -v; &ps -l" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if -W 160 -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" @@ -272,8 +272,7 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file, - std::string wire_delay) + const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file) { module = current_module; map_autoidx = autoidx++; @@ -388,9 +387,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); @@ -964,7 +960,7 @@ struct Abc9Pass : public Pass { 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", wire_delay; + std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1"; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false, sop_mode = false; vector lut_costs; @@ -1218,10 +1214,6 @@ struct Abc9Pass : public Pass { box_file = std::string(pwd) + "/" + box_file; continue; } - if (arg == "-W" && argidx+1 < args.size()) { - wire_delay = "-S " + args[++argidx]; - continue; - } break; } extra_args(args, argidx, design); @@ -1264,7 +1256,7 @@ struct Abc9Pass : public Pass { 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, wire_delay); + box_file, lut_file); continue; } @@ -1410,7 +1402,7 @@ struct Abc9Pass : public Pass { 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, wire_delay); + box_file, lut_file); assign_map.set(mod); } } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f966115cd..f5f8c43e0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -297,7 +297,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { if (abc == "abc9") - run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box -W 160" + string(retime ? " -dff" : "")); + run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box" + string(retime ? " -dff" : "")); else if (help_mode) run(abc + " -luts 2:2,3,6:5,10,20 [-dff]"); else From 1e838a8913afa36a57d425f26ea881f5071b8b5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:49:15 -0700 Subject: [PATCH 369/514] Retry "Add "-W' wire delay arg to abc9, use from synth_xilinx" --- passes/techmap/abc9.cc | 18 +++++++++++++----- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index af9439e41..19157adc6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -25,7 +25,7 @@ #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" @@ -272,7 +272,8 @@ failed: 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 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 &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file) + const std::vector &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++; @@ -387,6 +388,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); @@ -960,7 +964,7 @@ struct Abc9Pass : public Pass { 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 lut_costs; @@ -1214,6 +1218,10 @@ struct Abc9Pass : public Pass { box_file = std::string(pwd) + "/" + box_file; continue; } + if (arg == "-W" && argidx+1 < args.size()) { + wire_delay = "-S " + args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); @@ -1256,7 +1264,7 @@ struct Abc9Pass : public Pass { 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; } @@ -1402,7 +1410,7 @@ struct Abc9Pass : public Pass { 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); } } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f5f8c43e0..f966115cd 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -297,7 +297,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { if (abc == "abc9") - run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box" + string(retime ? " -dff" : "")); + run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box -W 160" + string(retime ? " -dff" : "")); else if (help_mode) run(abc + " -luts 2:2,3,6:5,10,20 [-dff]"); else From 86efe9a616b70ffa64bb344d83aa42956e5fd470 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:01:15 -0700 Subject: [PATCH 370/514] Revert "Merge remote-tracking branch 'origin/eddie/muxpack' into xc7mux" This reverts commit 2223ca91b0cc559bb876e8e97372a8f77da1603e, reversing changes made to eaee250a6e63e58dfef63fa30c4120db78223e24. --- passes/opt/muxpack.cc | 24 ++++++++++-------------- tests/various/muxpack.v | 26 -------------------------- tests/various/muxpack.ys | 15 --------------- 3 files changed, 10 insertions(+), 55 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 8c4db4e4d..f9e5c8f09 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -94,27 +94,23 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec a_sig = cell->getPort("\\A"); - if (cell->type == "$mux") { - SigSpec b_sig = cell->getPort("\\B"); - if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) - goto start_cell; - - if (!sig_chain_prev.count(a_sig)) - a_sig = b_sig; - } - else if (cell->type == "$pmux") { - if (!sig_chain_prev.count(a_sig)) + SigSpec next_sig = cell->getPort("\\A"); + if (sig_chain_prev.count(next_sig) == 0) { + if (cell->type == "$mux") { + next_sig = cell->getPort("\\B"); + if (sig_chain_prev.count(next_sig) == 0) + goto start_cell; + } + else goto start_cell; } - else log_abort(); { - for (auto bit : a_sig.bits()) + for (auto bit : next_sig.bits()) if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - Cell *c1 = sig_chain_prev.at(a_sig); + Cell *c1 = sig_chain_prev.at(next_sig); Cell *c2 = cell; if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index f1bd5ea8e..7c189fff8 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -110,29 +110,3 @@ always @* begin endcase end endmodule - -module mux_if_bal_8_2 #(parameter N=8, parameter W=2) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* - if (s[0] == 1'b0) - if (s[1] == 1'b0) - if (s[2] == 1'b0) - o <= i[0*W+:W]; - else - o <= i[1*W+:W]; - else - if (s[2] == 1'b0) - o <= i[2*W+:W]; - else - o <= i[3*W+:W]; - else - if (s[1] == 1'b0) - if (s[2] == 1'b0) - o <= i[4*W+:W]; - else - o <= i[5*W+:W]; - else - if (s[2] == 1'b0) - o <= i[6*W+:W]; - else - o <= i[7*W+:W]; -endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 9ea743b9f..0c5b82818 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -133,18 +133,3 @@ design -import gold -as gold design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_bal_8_2 -prep -design -save gold -muxpack -opt -stat -select -assert-count 7 t:$mux -select -assert-count 0 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter From 882a83c383e277e51083019227a88c38bc6b1c68 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:04:31 -0700 Subject: [PATCH 371/514] Revert "Merge remote-tracking branch 'origin/eddie/muxpack' into xc7mux" This reverts commit eaee250a6e63e58dfef63fa30c4120db78223e24, reversing changes made to 935df3569b4677ac38041ff01a2f67185681f4e3. --- CHANGELOG | 1 - passes/opt/Makefile.inc | 1 - passes/opt/muxpack.cc | 266 ---------------------------------------- 3 files changed, 268 deletions(-) delete mode 100644 passes/opt/muxpack.cc diff --git a/CHANGELOG b/CHANGELOG index c1b548aeb..28f36b458 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,7 +17,6 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "rename -src" - Added "equiv_opt" pass - Added "read_aiger" frontend - - Added "muxpack" pass - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" - "synth_xilinx" to now infer wide multiplexers diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index ea3646330..337fee9e4 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -14,6 +14,5 @@ OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o OBJS += passes/opt/opt_lut.o OBJS += passes/opt/pmux2shiftx.o -OBJS += passes/opt/muxpack.o endif diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc deleted file mode 100644 index f9e5c8f09..000000000 --- a/passes/opt/muxpack.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct MuxpackWorker -{ - Module *module; - SigMap sigmap; - - int mux_count, pmux_count; - - pool remove_cells; - - dict sig_chain_next; - dict sig_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; - pool candidate_cells; - - void make_sig_chain_next_prev() - { - for (auto wire : module->wires()) - { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) - sigbit_with_non_chain_users.insert(bit); - } - } - - for (auto cell : module->cells()) - { - if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep")) - { - SigSpec a_sig = sigmap(cell->getPort("\\A")); - SigSpec b_sig; - if (cell->type == "$mux") - b_sig = sigmap(cell->getPort("\\B")); - SigSpec y_sig = sigmap(cell->getPort("\\Y")); - - if (sig_chain_next.count(a_sig)) - for (auto a_bit : a_sig.bits()) - sigbit_with_non_chain_users.insert(a_bit); - else { - sig_chain_next[a_sig] = cell; - candidate_cells.insert(cell); - } - - if (!b_sig.empty()) { - if (sig_chain_next.count(b_sig)) - for (auto b_bit : b_sig.bits()) - sigbit_with_non_chain_users.insert(b_bit); - else { - sig_chain_next[b_sig] = cell; - candidate_cells.insert(cell); - } - } - - sig_chain_prev[y_sig] = cell; - continue; - } - - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - sigbit_with_non_chain_users.insert(bit); - } - } - - void find_chain_start_cells() - { - for (auto cell : candidate_cells) - { - log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - - SigSpec next_sig = cell->getPort("\\A"); - if (sig_chain_prev.count(next_sig) == 0) { - if (cell->type == "$mux") { - next_sig = cell->getPort("\\B"); - if (sig_chain_prev.count(next_sig) == 0) - goto start_cell; - } - else - goto start_cell; - } - - { - for (auto bit : next_sig.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - Cell *c1 = sig_chain_prev.at(next_sig); - Cell *c2 = cell; - - if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) - goto start_cell; - } - - continue; - - start_cell: - chain_start_cells.insert(cell); - } - } - - vector create_chain(Cell *start_cell) - { - vector chain; - - Cell *c = start_cell; - while (c != nullptr) - { - chain.push_back(c); - - SigSpec y_sig = sigmap(c->getPort("\\Y")); - - if (sig_chain_next.count(y_sig) == 0) - break; - - c = sig_chain_next.at(y_sig); - if (chain_start_cells.count(c) != 0) - break; - } - - return chain; - } - - void process_chain(vector &chain) - { - if (GetSize(chain) < 2) - return; - - int cursor = 0; - while (cursor < GetSize(chain)) - { - int cases = GetSize(chain) - cursor; - - Cell *first_cell = chain[cursor]; - dict taps_dict; - - if (cases < 2) { - cursor++; - continue; - } - - Cell *last_cell = chain[cursor+cases-1]; - - log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases); - - mux_count += cases; - pmux_count += 1; - - first_cell->type = "$pmux"; - SigSpec b_sig = first_cell->getPort("\\B"); - SigSpec s_sig = first_cell->getPort("\\S"); - - for (int i = 1; i < cases; i++) { - Cell* prev_cell = chain[cursor+i-1]; - Cell* cursor_cell = chain[cursor+i]; - if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) { - b_sig.append(cursor_cell->getPort("\\B")); - s_sig.append(cursor_cell->getPort("\\S")); - } - else { - b_sig.append(cursor_cell->getPort("\\A")); - s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S"))); - } - remove_cells.insert(cursor_cell); - } - - first_cell->setPort("\\B", b_sig); - first_cell->setPort("\\S", s_sig); - first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); - first_cell->setPort("\\Y", last_cell->getPort("\\Y")); - - cursor += cases; - } - } - - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); - - remove_cells.clear(); - sig_chain_next.clear(); - sig_chain_prev.clear(); - chain_start_cells.clear(); - candidate_cells.clear(); - } - - MuxpackWorker(Module *module) : - module(module), sigmap(module), mux_count(0), pmux_count(0) - { - make_sig_chain_next_prev(); - find_chain_start_cells(); - - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); - } - - cleanup(); - } -}; - -struct MuxpackPass : public Pass { - MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" muxpack [selection]\n"); - log("\n"); - log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n"); - log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n"); - log("into $pmux cells.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - break; - } - extra_args(args, argidx, design); - - int mux_count = 0; - int pmux_count = 0; - - for (auto module : design->selected_modules()) { - MuxpackWorker worker(module); - mux_count += worker.mux_count; - pmux_count += worker.pmux_count; - } - - log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count); - } -} MuxpackPass; - -PRIVATE_NAMESPACE_END From 2cbcd6224c0293a3abdf00f51c515fc556d9d3e1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:05:02 -0700 Subject: [PATCH 372/514] Revert "Merge remote-tracking branch 'origin/eddie/shregmap_improve' into xc7mux" This reverts commit a138381ac3f2c820d187f08531ffd823d6cbcfd5, reversing changes made to b77c5da76919f7f99f171a0a2775896fbc8debc2. --- passes/techmap/shregmap.cc | 9 +++------ tests/various/shregmap.v | 22 ---------------------- tests/various/shregmap.ys | 31 ------------------------------- 3 files changed, 3 insertions(+), 59 deletions(-) delete mode 100644 tests/various/shregmap.v delete mode 100644 tests/various/shregmap.ys diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 46f6a79fb..21dfe9619 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -293,13 +293,10 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { - auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); - if (!r.second) { + if (sigbit_chain_next.count(d_bit)) { sigbit_with_non_chain_users.insert(d_bit); - Wire *wire = module->addWire(NEW_ID); - module->connect(wire, d_bit); - sigbit_chain_next.insert(std::make_pair(wire, cell)); - } + } else + sigbit_chain_next[d_bit] = cell; sigbit_chain_prev[q_bit] = cell; continue; diff --git a/tests/various/shregmap.v b/tests/various/shregmap.v deleted file mode 100644 index 56e05c2c0..000000000 --- a/tests/various/shregmap.v +++ /dev/null @@ -1,22 +0,0 @@ -module shregmap_test(input i, clk, output [1:0] q); -reg head = 1'b0; -reg [3:0] shift1 = 4'b0000; -reg [3:0] shift2 = 4'b0000; - -always @(posedge clk) begin - head <= i; - shift1 <= {shift1[2:0], head}; - shift2 <= {shift2[2:0], head}; -end - -assign q = {shift2[3], shift1[3]}; -endmodule - -module $__SHREG_DFF_P_(input C, D, output Q); -parameter DEPTH = 1; -parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; -reg [DEPTH-1:0] r = INIT; -always @(posedge C) - r <= { r[DEPTH-2:0], D }; -assign Q = r[DEPTH-1]; -endmodule diff --git a/tests/various/shregmap.ys b/tests/various/shregmap.ys deleted file mode 100644 index ca7f47015..000000000 --- a/tests/various/shregmap.ys +++ /dev/null @@ -1,31 +0,0 @@ -read_verilog shregmap.v -design -copy-to model $__SHREG_DFF_P_ -hierarchy -top shregmap_test -prep -design -save gold - -techmap -shregmap -init - -opt - -stat -# show -width -select -assert-count 1 t:$_DFF_P_ -select -assert-count 2 t:$__SHREG_DFF_P_ - -design -stash gate - -design -import gold -as gold -design -import gate -as gate -design -copy-from model -as $__SHREG_DFF_P_ \$__SHREG_DFF_P_ -prep - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 5 miter - -design -load gold -stat - -design -load gate -stat From afd620fd5f4236a802b3e6139a5d58821153b01e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:13:53 -0700 Subject: [PATCH 373/514] Typo: wire delay is -W argument --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 19157adc6..fef977eb8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1219,7 +1219,7 @@ struct Abc9Pass : public Pass { continue; } if (arg == "-W" && argidx+1 < args.size()) { - wire_delay = "-S " + args[++argidx]; + wire_delay = "-W " + args[++argidx]; continue; } break; From 738fdfe8f55e18ac7f315cd68c117eae370004ca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:20:46 -0700 Subject: [PATCH 374/514] Remove wide mux inference --- CHANGELOG | 1 - techlibs/xilinx/Makefile.inc | 1 - techlibs/xilinx/cells_map.v | 120 -------------------------------- techlibs/xilinx/mux_map.v | 52 -------------- techlibs/xilinx/synth_xilinx.cc | 24 +------ 5 files changed, 3 insertions(+), 195 deletions(-) delete mode 100644 techlibs/xilinx/mux_map.v diff --git a/CHANGELOG b/CHANGELOG index 28f36b458..839fefcf1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,7 +18,6 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "equiv_opt" pass - Added "read_aiger" frontend - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" - - "synth_xilinx" to now infer wide multiplexers Yosys 0.7 .. Yosys 0.8 diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 2f3945167..296edace9 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,7 +30,6 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f8f9356bc..6b92d2ea9 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -142,123 +142,3 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end endgenerate endmodule - -module \$__XILINX_SHIFTX (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; - parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; - - function integer compute_num_leading_X_in_A; - integer i, c; - begin - compute_num_leading_X_in_A = 0; - c = 1; - for (i = A_WIDTH-1; i >= 0; i=i-1) begin - if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx) - c = 0; - compute_num_leading_X_in_A = compute_num_leading_X_in_A + c; - end - end - endfunction - localparam num_leading_X_in_A = compute_num_leading_X_in_A(); - - generate - genvar i, j; - // Bit-blast - if (Y_WIDTH > 1) begin - for (i = 0; i < Y_WIDTH; i++) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); - end - // If the LSB of B is constant zero (and Y_WIDTH is 1) then - // we can optimise by removing every other entry from A - // and popping the constant zero from B - else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin - wire [(A_WIDTH+1)/2-1:0] A_i; - for (i = 0; i < (A_WIDTH+1)/2; i++) - assign A_i[i] = A[i*2]; - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); - end - // Trim off any leading 1'bx -es in A, and resize B accordingly - else if (num_leading_X_in_A > 0) begin - localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; - localparam B_WIDTH_new = $clog2(A_WIDTH_new); - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); - end - else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); - end - else if (B_WIDTH == 3) begin - localparam a_width0 = 2 ** 2; - localparam a_widthN = A_WIDTH - a_width0; - wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - else - assign T1 = A[A_WIDTH-1]; - MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); - end - else if (B_WIDTH == 4) begin - localparam a_width0 = 2 ** 2; - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [4-1:0] T; - wire T0, T1; - for (i = 0; i < 4; i++) - if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 0) begin - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end - else - assign T[i] = 1'bx; - MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); - MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); - MUXF8 fpga_hard_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); - end - else begin - localparam a_width0 = 2 ** 4; - localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) - if (i < num_mux16) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - else if (i == num_mux16 && a_widthN > 0) begin - if (a_widthN > 1) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end - else - assign T[i] = 1'bx; - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); - end - endgenerate -endmodule - -module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); -input A, B, C, D, E, F, G, H, S, T, U; -output Y; - \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); -endmodule - -module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); -input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; -output Y; - \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); -endmodule diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v deleted file mode 100644 index 0fa8db736..000000000 --- a/techlibs/xilinx/mux_map.v +++ /dev/null @@ -1,52 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -module \$shiftx (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; - parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; - - generate - genvar i, j; - // TODO: Check if this opt still necessary - if (B_SIGNED) begin - if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); - else - wire _TECHMAP_FAIL_ = 1; - end - else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - wire _TECHMAP_FAIL_ = 1; - end - else begin - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); - end - endgenerate -endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f966115cd..42a3bba12 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -70,9 +70,6 @@ struct SynthXilinxPass : public ScriptPass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); - log(" -nomux\n"); - log(" disable inference of wide multiplexers\n"); - log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); log(" from label is synonymous to 'begin', and empty to label is\n"); @@ -94,7 +91,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, abc, arch; - bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl, nomux; + bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; void clear_flags() YS_OVERRIDE { @@ -109,7 +106,6 @@ struct SynthXilinxPass : public ScriptPass nobram = false; nodram = false; nosrl = false; - nomux = false; arch = "xc7"; } @@ -173,10 +169,6 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } - if (args[argidx] == "-nomux") { - nomux = true; - continue; - } if (args[argidx] == "-abc9") { abc = "abc9"; continue; @@ -225,15 +217,11 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { run("synth -run coarse"); - //if (!nomux || help_mode) - // run("muxpack", "(skip if '-nomux')"); - // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former - // Also: wide multiplexer inference benefits from this too - if (!(nosrl && nomux) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); + if (!nosrl || help_mode) + run("pmux2shiftx", "(skip if '-nosrl')"); // Run a number of peephole optimisations, including one // that optimises $mul cells driving $shiftx's B input @@ -271,10 +259,6 @@ struct SynthXilinxPass : public ScriptPass } std::string techmap_files = " -map +/techmap.v"; - if (help_mode) - techmap_files += " [-map +/xilinx/mux_map.v]"; - else if (!nomux) - techmap_files += " -map +/xilinx/mux_map.v"; if (help_mode) techmap_files += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { @@ -289,8 +273,6 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - if (!nomux || help_mode) - run("muxcover -mux8 -mux16", "(skip if '-nomux')"); run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } From 99267f660f5aca3d84d885a27aad54ae3e4e8044 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:21:52 -0700 Subject: [PATCH 375/514] Fix spacing --- techlibs/xilinx/synth_xilinx.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 42a3bba12..56a3eb6fc 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -260,13 +260,13 @@ struct SynthXilinxPass : public ScriptPass std::string techmap_files = " -map +/techmap.v"; if (help_mode) - techmap_files += " [-map +/xilinx/arith_map.v]"; + techmap_files += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { - techmap_files += " -map +/xilinx/arith_map.v"; - if (vpr) - techmap_files += " -D _EXPLICIT_CARRY"; - else if (abc == "abc9") - techmap_files += " -D _CLB_CARRY"; + techmap_files += " -map +/xilinx/arith_map.v"; + if (vpr) + techmap_files += " -D _EXPLICIT_CARRY"; + else if (abc == "abc9") + techmap_files += " -D _CLB_CARRY"; } run("techmap " + techmap_files); run("opt -fast"); From f9433cc34bd52d4807c318a6b26f63cdd15d35c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:29:30 -0700 Subject: [PATCH 376/514] Remove abc_flop{,_d} attributes from ice40/cells_sim.v --- techlibs/ice40/cells_sim.v | 60 +++++++++++++------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 523dd8cbe..55b4d98c9 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -143,8 +143,7 @@ endmodule // Positive Edge SiliconBlue FF Cells -(* abc_box_id = 1, abc_flop, lib_whitebox *) -module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); +module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, D); `ifndef _ABC always @(posedge C) Q <= D; @@ -153,15 +152,13 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) in `endif endmodule -//(* abc_box_id = 2, abc_flop *) -module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D); +module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); always @(posedge C) if (E) Q <= D; endmodule -//(* abc_box_id = 3, abc_flop *) -module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); +module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(posedge C) if (R) Q <= 0; @@ -169,8 +166,7 @@ module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 4, abc_flop *) -module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); +module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -178,8 +174,7 @@ module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d * Q <= D; endmodule -//(* abc_box_id = 5, abc_flop *) -module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); +module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(posedge C) if (S) Q <= 1; @@ -187,8 +182,7 @@ module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 6, abc_flop *) -module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); +module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -196,8 +190,7 @@ module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d * Q <= D; endmodule -//(* abc_box_id = 7, abc_flop *) -module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); +module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(posedge C) if (E) begin if (R) @@ -207,8 +200,7 @@ module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flo end endmodule -//(* abc_box_id = 8, abc_flop *) -module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); +module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -216,8 +208,7 @@ module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop Q <= D; endmodule -//(* abc_box_id = 9, abc_flop *) -module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); +module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(posedge C) if (E) begin if (S) @@ -227,8 +218,7 @@ module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flo end endmodule -//(* abc_box_id = 10, abc_flop *) -module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); +module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -238,21 +228,18 @@ endmodule // Negative Edge SiliconBlue FF Cells -//(* abc_box_id = 11, abc_flop *) -module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D); +module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, D); always @(negedge C) Q <= D; endmodule -//(* abc_box_id = 12, abc_flop *) -module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D); +module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); always @(negedge C) if (E) Q <= D; endmodule -//(* abc_box_id = 13, abc_flop *) -module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); +module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(negedge C) if (R) Q <= 0; @@ -260,8 +247,7 @@ module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 14, abc_flop *) -module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D); +module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -269,8 +255,7 @@ module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 15, abc_flop *) -module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); +module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(negedge C) if (S) Q <= 1; @@ -278,8 +263,7 @@ module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 16, abc_flop *) -module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D); +module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -287,8 +271,7 @@ module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d Q <= D; endmodule -//(* abc_box_id = 17, abc_flop *) -module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); +module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(negedge C) if (E) begin if (R) @@ -298,8 +281,7 @@ module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_fl end endmodule -//(* abc_box_id = 18, abc_flop *) -module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D); +module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -307,8 +289,7 @@ module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flo Q <= D; endmodule -//(* abc_box_id = 19, abc_flop *) -module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); +module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(negedge C) if (E) begin if (S) @@ -318,8 +299,7 @@ module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_fl end endmodule -//(* abc_box_id = 20, abc_flop *) -module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D); +module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); always @(negedge C, posedge S) if (S) Q <= 1; From c7f5091c2fac374c4e48cd9736c2727d65acdcf9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:34:41 -0700 Subject: [PATCH 377/514] Reduce diff with master --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 56a3eb6fc..3ac19e498 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -290,7 +290,7 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v"); + run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); run("clean"); From b21d29598a59f0f137a42f00a000b7937dabb402 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:40:51 -0700 Subject: [PATCH 378/514] Consistency --- backends/aiger/xaiger.cc | 2 +- frontends/aiger/aigerparse.cc | 2 +- frontends/aiger/aigerparse.h | 2 +- passes/techmap/abc9.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf2f9f1bc..730f50f5b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2019 Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4c19ec171..0afdf9592 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2019 Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 7d6d70b2c..de3c3efbc 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fef977eb8..47e87fa46 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2019 Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above From 4be417f6e15ee3f3d8da8cd75d8405b90d5b32ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:53:14 -0700 Subject: [PATCH 379/514] Cleanup write_xaiger --- backends/aiger/xaiger.cc | 98 +++------------------------------------- 1 file changed, 6 insertions(+), 92 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 730f50f5b..fd0620cac 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -624,14 +624,9 @@ struct XAigerWriter aig_o++; aig_outputs.push_back(0); } - - if (bmode) { - //aig_b++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -708,73 +703,6 @@ struct XAigerWriter } } - if (symbols_mode) - { - dict> symbols; - - bool output_seen = false; - for (auto wire : module->wires()) - { - //if (wire->name[0] == '$') - // continue; - - SigSpec sig = sigmap(wire); - - for (int i = 0; i < GetSize(wire); i++) - { - RTLIL::SigBit b(wire, i); - if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); - } - - if (output_bits.count(b)) { - int o = ordered_outputs.at(b); - output_seen = !miter_mode; - if (GetSize(wire) != 1) - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); - } - - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // if (GetSize(wire) != 1) - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - // else - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; - if (GetSize(wire) != 1) - symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); - else - symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); - } - } - } - - if (omode && !output_seen) - symbols["o0"].push_back("__dummy_o__"); - - symbols.sort(); - - for (auto &sym : symbols) { - f << sym.first; - std::sort(sym.second.begin(), sym.second.end()); - for (auto &s : sym.second) - f << " " << s; - f << std::endl; - } - } - f << "c"; if (!box_list.empty() || !ff_bits.empty()) { @@ -931,8 +859,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); f << "a"; std::string buffer_str = a_buffer.str(); @@ -1055,9 +983,6 @@ struct XAigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -symbols\n"); - log(" include a symbol table in the generated AIGER file\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -1074,12 +999,9 @@ struct XAigerBackend : public Backend { { bool ascii_mode = false; bool zinit_mode = false; - bool miter_mode = false; - bool symbols_mode = false; bool verbose_map = false; bool imode = false; bool omode = false; - bool bmode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1095,10 +1017,6 @@ struct XAigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-symbols") { - symbols_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1116,10 +1034,6 @@ struct XAigerBackend : public Backend { omode = true; continue; } - if (args[argidx] == "-B") { - bmode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1129,8 +1043,8 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); + XAigerWriter writer(top_module, zinit_mode, imode, omode); + writer.write_aiger(*f, ascii_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; From 14e870d4c47e18abf45f82f2d9329d1488e0650c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 10:00:57 -0700 Subject: [PATCH 380/514] More write_xaiger cleanup --- backends/aiger/xaiger.cc | 52 ++++++++++------------------------------ passes/techmap/abc9.cc | 2 +- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fd0620cac..af9a30135 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -543,10 +543,6 @@ struct XAigerWriter ff_aig_map[bit] = 2*aig_m; } - if (imode && input_bits.empty()) { - aig_m++, aig_i++; - } - //if (zinit_mode) //{ // for (auto it : ff_map) { @@ -620,13 +616,9 @@ struct XAigerWriter aig_outputs.push_back(ff_aig_map.at(bit)); } - if (omode && output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -716,18 +708,15 @@ struct XAigerWriter #endif h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -859,8 +848,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/); f << "a"; std::string buffer_str = a_buffer.str(); @@ -879,7 +868,7 @@ struct XAigerWriter f << stringf("Generated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map, bool omode) + void write_map(std::ostream &f, bool verbose_map) { dict input_lines; dict init_lines; @@ -952,8 +941,6 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) @@ -989,19 +976,12 @@ struct XAigerBackend : public Backend { log(" -vmap \n"); log(" like -map, but more verbose\n"); log("\n"); - log(" -I, -O, -B\n"); - log(" If the design contains no input/output/assert then create one\n"); - log(" dummy input/output/bad_state pin to make the tools reading the\n"); - log(" AIGER file happy.\n"); - log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; bool zinit_mode = false; bool verbose_map = false; - bool imode = false; - bool omode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1026,14 +1006,6 @@ struct XAigerBackend : public Backend { verbose_map = true; continue; } - if (args[argidx] == "-I") { - imode = true; - continue; - } - if (args[argidx] == "-O") { - omode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1043,15 +1015,15 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode); - writer.write_aiger(*f, ascii_mode, omode); + XAigerWriter writer(top_module, zinit_mode); + writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { std::ofstream mapf; 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, omode); + writer.write_map(mapf, verbose_map); } } } XAigerBackend; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 47e87fa46..b0c6b6d7b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -425,7 +425,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri handle_loops(design); - 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, stringf("write_xaiger -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); #if 0 std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); From 8bb67fa67cfeb90a236b9ad6705c42e052a09448 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 10:18:44 -0700 Subject: [PATCH 381/514] Do not call abc9 if no outputs --- passes/techmap/abc9.cc | 129 ++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b0c6b6d7b..d4abb8d3b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -414,64 +414,75 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - sel.select(module); - - // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero - Pass::call(design, "setundef -zero"); - - Pass::call(design, "aigmap"); - - handle_loops(design); - - Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); - -#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 - - 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); + 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; } } - module->fixup_ports(); - - //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); log_push(); - //if (count_output > 0) + if (count_output) { + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(module); + + // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero + Pass::call(design, "setundef -zero"); + + Pass::call(design, "aigmap"); + + handle_loops(design); + + //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())); + +#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 + + 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_header(design, "Executing ABC9.\n"); - std::string buffer; + std::string buffer; if (!lut_costs.empty()) { buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); @@ -643,7 +654,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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) { @@ -654,10 +665,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } 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; @@ -753,10 +764,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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) { From 2e7b3eee400a4d845398be8e15ca023672f05270 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:43:43 -0700 Subject: [PATCH 382/514] Add a couple more tests --- backends/aiger/xaiger.cc | 39 ++++++++++++++++++--------------------- tests/simple_abc9/abc9.v | 12 ++++++++++++ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index af9a30135..3dbff5496 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,14 +142,6 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire == nullptr) { - if (wire->port_output) { - aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); - } - continue; - } - undriven_bits.insert(bit); unused_bits.insert(bit); @@ -160,8 +152,10 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) + if (bit != wirebit) { alias_map[wirebit] = bit; + undriven_bits.insert(wirebit); + } output_bits.insert(wirebit); } } @@ -169,7 +163,6 @@ struct XAigerWriter for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); - for (auto bit : output_bits) if (!bit.wire->port_input) unused_bits.erase(bit); @@ -178,8 +171,7 @@ struct XAigerWriter TopoSort toposort; bool abc_box_seen = false; - for (auto cell : module->cells()) - { + for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); bool builtin_type = yosys_celltypes.cell_known(cell->type); bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); @@ -296,14 +288,15 @@ struct XAigerWriter else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - if (!w->port_input) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + + if (is_input) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (!w->port_output) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; @@ -311,7 +304,11 @@ struct XAigerWriter unused_bits.erase(b); } } - if (is_output) { + } + if (is_output) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; input_bits.insert(b); SigBit O = sigmap(b); if (O != b) diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 2752ff8cc..0b83c34a3 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -250,3 +250,15 @@ module abc9_test023 #( wire [2*M-1:0] mask = {M{1'b1}}; assign dout = (mask << din[N-1:0]) >> M; endmodule + +module abc9_test024(input [3:0] i, output [3:0] o); +abc9_test024_sub a(i[1:0], o[1:0]); +endmodule + +module abc9_test024_sub(input [1:0] i, output [1:0] o); +assign o = i; +endmodule + +module abc9_test025(input [3:0] i, output [3:0] o); +abc9_test024_sub a(i[2:1], o[2:1]); +endmodule From fb2758aade4561d8c379e8b9d97ee871b1bbfde3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:44:30 -0700 Subject: [PATCH 383/514] write_xaiger to preserve POs even if driven by constant --- backends/aiger/xaiger.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3dbff5496..3a4b353e2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,8 +142,10 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - undriven_bits.insert(bit); - unused_bits.insert(bit); + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); + } if (wire->port_input || keep) { if (bit != wirebit) @@ -154,7 +156,8 @@ struct XAigerWriter if (wire->port_output || keep) { if (bit != wirebit) { alias_map[wirebit] = bit; - undriven_bits.insert(wirebit); + if (!bit.wire) + undriven_bits.insert(wirebit); } output_bits.insert(wirebit); } @@ -480,10 +483,6 @@ struct XAigerWriter } } - // Erase all POs that are undriven - if (!holes_mode) - for (auto bit : undriven_bits) - output_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); From 342fc0a600584ab59fd24b6a6e22d49ff024c8d0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:45:46 -0700 Subject: [PATCH 384/514] parse_xaiger to cope with inouts --- frontends/aiger/aigerparse.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0afdf9592..72b37d21d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -696,10 +696,6 @@ void AigerReader::post_process() RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); - if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) { - wire->port_output = false; - continue; - } if (index == 0) { // Cope with the fact that a CO might be identical @@ -797,8 +793,6 @@ void AigerReader::post_process() port_output = port_output || other_wire->port_output; } } - if ((port_input && port_output) || (!port_input && !port_output)) - continue; wire = module->addWire(name, width); wire->port_input = port_input; From d9974b85e741ad6b0071db319664565fb4354499 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:47:39 -0700 Subject: [PATCH 385/514] Fix compile errors when #if 1 for debug --- passes/techmap/abc9.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d4abb8d3b..5b778d440 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -444,16 +444,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str())); -#if 0 - std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig"); + 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 */, false /* wideports */); - reader.parse_xaiger(); + { + AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* 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__")); @@ -482,7 +485,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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"); @@ -518,7 +520,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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()); @@ -527,7 +528,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //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(); From 2e7e73f483e32fec62bc14fc12b10dafb17082f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:52:49 -0700 Subject: [PATCH 386/514] Remove hacky wideports_split from abc9 --- passes/techmap/abc9.cc | 56 +++--------------------------------------- 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5b778d440..21d207d33 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -246,29 +246,6 @@ struct abc_output_filter } }; -static std::pair 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::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1)); - -failed: - return std::pair(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 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, @@ -548,21 +525,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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}); - } } } @@ -725,22 +690,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); From 8374eb1cb4dcb99b2125543a3d5f9f6adbdd6b7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:55:02 -0700 Subject: [PATCH 387/514] Remove unnecessary undriven_bits.insert --- backends/aiger/xaiger.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3a4b353e2..fcf9a7bf1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -154,11 +154,8 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) { + if (bit != wirebit) alias_map[wirebit] = bit; - if (!bit.wire) - undriven_bits.insert(wirebit); - } output_bits.insert(wirebit); } } From b3faf0246d46f31027ce2aade410e4325822b121 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:04:33 -0700 Subject: [PATCH 388/514] Be more precise when connecting during ABC9 re-integration --- passes/techmap/abc9.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 21d207d33..c3145dbe5 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -569,7 +569,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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; From 009255d11d37beaeca95a59e5b484d44b39b980a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 28 Apr 2019 12:36:04 -0700 Subject: [PATCH 389/514] Move neg-pol to pos-pol mapping from ff_map to cells_map.v --- techlibs/xilinx/cells_map.v | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 6b92d2ea9..8291f5647 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -18,6 +18,14 @@ * */ +// Convert negative-polarity reset to positive-polarity +module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + + module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; From 9f275c1437cb48c28b717f0996edab9da9e73aa0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:33:05 -0700 Subject: [PATCH 390/514] Revert "Merge remote-tracking branch 'origin/eddie/muxpack' into xc7mux" This reverts commit 2223ca91b0cc559bb876e8e97372a8f77da1603e, reversing changes made to eaee250a6e63e58dfef63fa30c4120db78223e24. --- tests/various/muxpack.v | 112 -------------------------------- tests/various/muxpack.ys | 135 --------------------------------------- 2 files changed, 247 deletions(-) delete mode 100644 tests/various/muxpack.v delete mode 100644 tests/various/muxpack.ys diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v deleted file mode 100644 index 7c189fff8..000000000 --- a/tests/various/muxpack.v +++ /dev/null @@ -1,112 +0,0 @@ -module mux_if_unbal_4_1 #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* - if (s == 0) o <= i[0*W+:W]; - else if (s == 1) o <= i[1*W+:W]; - else if (s == 2) o <= i[2*W+:W]; - else if (s == 3) o <= i[3*W+:W]; - else o <= {W{1'bx}}; -endmodule - -module mux_if_unbal_5_3 #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - o <= {W{1'bx}}; - if (s == 0) o <= i[0*W+:W]; - if (s == 1) o <= i[1*W+:W]; - if (s == 2) o <= i[2*W+:W]; - if (s == 3) o <= i[3*W+:W]; - if (s == 4) o <= i[4*W+:W]; -end -endmodule - -module mux_if_unbal_5_3_invert #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* - if (s != 0) - if (s != 1) - if (s != 2) - if (s != 3) - if (s != 4) o <= i[4*W+:W]; - else o <= i[0*W+:W]; - else o <= i[3*W+:W]; - else o <= i[2*W+:W]; - else o <= i[1*W+:W]; - else o <= {W{1'bx}}; -endmodule - -module mux_if_unbal_5_3_width_mismatch #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - o <= {W{1'bx}}; - if (s == 0) o <= i[0*W+:W]; - if (s == 1) o <= i[1*W+:W]; - if (s == 2) o[W-2:0] <= i[2*W+:W-1]; - if (s == 3) o <= i[3*W+:W]; - if (s == 4) o <= i[4*W+:W]; -end -endmodule - -module mux_if_unbal_4_1_missing #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - if (s == 0) o <= i[0*W+:W]; -// else if (s == 1) o <= i[1*W+:W]; -// else if (s == 2) o <= i[2*W+:W]; - else if (s == 3) o <= i[3*W+:W]; - else o <= {W{1'bx}}; -end -endmodule - -module mux_if_unbal_5_3_order #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - o <= {W{1'bx}}; - if (s == 3) o <= i[3*W+:W]; - if (s == 2) o <= i[2*W+:W]; - if (s == 1) o <= i[1*W+:W]; - if (s == 4) o <= i[4*W+:W]; - if (s == 0) o <= i[0*W+:W]; -end -endmodule - -module mux_if_unbal_4_1_nonexcl #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* - if (s == 0) o <= i[0*W+:W]; - else if (s == 1) o <= i[1*W+:W]; - else if (s == 2) o <= i[2*W+:W]; - else if (s == 3) o <= i[3*W+:W]; - else if (s == 0) o <= {W{1'b0}}; - else o <= {W{1'bx}}; -endmodule - -module mux_if_unbal_5_3_nonexcl #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - o <= {W{1'bx}}; - if (s == 0) o <= i[0*W+:W]; - if (s == 1) o <= i[1*W+:W]; - if (s == 2) o <= i[2*W+:W]; - if (s == 3) o <= i[3*W+:W]; - if (s == 4) o <= i[4*W+:W]; - if (s == 0) o <= i[2*W+:W]; -end -endmodule - -module mux_case_unbal_8_7#(parameter N=8, parameter W=7) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); -always @* begin - o <= {W{1'bx}}; - case (s) - 0: o <= i[0*W+:W]; - default: - case (s) - 1: o <= i[1*W+:W]; - 2: o <= i[2*W+:W]; - default: - case (s) - 3: o <= i[3*W+:W]; - 4: o <= i[4*W+:W]; - 5: o <= i[5*W+:W]; - default: - case (s) - 6: o <= i[6*W+:W]; - default: o <= i[7*W+:W]; - endcase - endcase - endcase - endcase -end -endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys deleted file mode 100644 index 0c5b82818..000000000 --- a/tests/various/muxpack.ys +++ /dev/null @@ -1,135 +0,0 @@ -read_verilog muxpack.v -design -save read -hierarchy -top mux_if_unbal_4_1 -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_5_3 -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_5_3_invert -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_5_3_width_mismatch -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 2 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_4_1_missing -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_5_3_order -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_4_1_nonexcl -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_if_unbal_5_3_nonexcl -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter - -design -load read -hierarchy -top mux_case_unbal_8_7 -prep -design -save gold -muxpack -opt -stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports miter From 90dc4d82de2eb7193caef797203d0e4cc8d32d3e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:51:37 -0700 Subject: [PATCH 391/514] Revert "For 'stat' do not count modules with abc_box_id" This reverts commit b89bb744529fc8a5e4cd38522f86a797117f2abc. --- passes/cmds/stat.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index c42f7fcdd..d22685b62 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -339,9 +339,6 @@ struct StatPass : public Pass { if (mod->get_bool_attribute("\\top")) top_mod = mod; - if (mod->attributes.count("\\abc_box_id")) - continue; - statdata_t data(design, mod, width_mode, cell_area, techname); mod_stat[mod->name] = data; From f81a189fb893c62cf6e6f020608ca23db211e31f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:52:09 -0700 Subject: [PATCH 392/514] Fix spelling --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 5b19d84fb..15e79f9d1 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1453,7 +1453,7 @@ struct AbcPass : public Pass { log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); log("ABC on logic snippets extracted from your design. You will not get any useful\n"); log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and the load that into ABC externally if\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); log("you want to use ABC to convert your design into another format.\n"); log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); From 2c40b667850578eb7bb2dceb3a9beda0fdbfe7e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:53:12 -0700 Subject: [PATCH 393/514] Rip out all non FPGA stuff from abc9 --- passes/techmap/abc9.cc | 452 ++++++++++------------------------------- 1 file changed, 110 insertions(+), 342 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index c3145dbe5..a6ec4a6fb 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -22,18 +22,9 @@ // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification // http://www.eecs.berkeley.edu/~alanmi/abc/ -#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} -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" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} -v; "/*"&mfs; "*/"&ps -l" -#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" -#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "&st; &retime; &if" -#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" -#define ABC_FAST_COMMAND_DFL "strash; dretime; map" +#define ABC_FAST_COMMAND_LUT "&st; &retime; &if {W}" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -247,8 +238,8 @@ struct abc_output_filter }; 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 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, + bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, + bool keepff, std::string delay_target, std::string lutin_shared, bool fast_mode, const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file, std::string wire_delay) { @@ -302,11 +293,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri std::string abc_script; - if (!liberty_file.empty()) { - abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); - if (!constr_file.empty()) - abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); - } else if (!lut_costs.empty()) { abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); if (!box_file.empty()) @@ -319,7 +305,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script += stringf("read_box -v %s; ", box_file.c_str()); } else - abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); + log_abort(); abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); @@ -342,12 +328,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; //if (all_luts_cost_same && !fast_mode) // abc_script += "; lutpack {S}"; - } else if (!liberty_file.empty()) - abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); - else if (sop_mode) - abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; - else - abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + } else + log_abort(); if (script_file.empty() && !delay_target.empty()) for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) @@ -356,14 +338,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); - for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) - abc_script = abc_script.substr(0, pos) + sop_inputs + abc_script.substr(pos+3); - - for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) - abc_script = abc_script.substr(0, pos) + sop_products + abc_script.substr(pos+3); - - 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("{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); @@ -501,8 +477,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (ifs.fail()) log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); - bool builtin_lib = liberty_file.empty(); - //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 */, true /* wideports */); @@ -561,66 +535,63 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri std::map cell_stats; for (auto c : mapped_mod->cells()) { - if (builtin_lib) - { - if (c->type == "$_NOT_") { - RTLIL::Cell *cell; - RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); - RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); - if (!a_bit.wire) { - c->setPort("\\Y", module->addWire(NEW_ID)); - RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); - log_assert(wire); - module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1); + if (c->type == "$_NOT_") { + RTLIL::Cell *cell; + RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); + RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); + if (!a_bit.wire) { + c->setPort("\\Y", module->addWire(NEW_ID)); + 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; + // ABC can return NOT gates that drive POs + if (!a_bit.wire->port_input) { + // If it's not a NOT gate that that comes from a PI directly, + // find the driving LUT and clone that to guarantee that we won't + // increase the max logic depth + // (TODO: Optimise by not cloning unless will increase depth) + RTLIL::IdString driver_name; + if (GetSize(a_bit.wire) == 1) + driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); + else + driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); + driving_lut = mapped_mod->cell(driver_name); } - else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driving_lut = nullptr; - // ABC can return NOT gates that drive POs - if (!a_bit.wire->port_input) { - // If it's not a NOT gate that that comes from a PI directly, - // find the driving LUT and clone that to guarantee that we won't - // increase the max logic depth - // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::IdString driver_name; - if (GetSize(a_bit.wire) == 1) - driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); - else - driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - driving_lut = mapped_mod->cell(driver_name); - } - if (!driving_lut) { - // If a driver couldn't be found (could be from PI, - // or from a box) then implement using a LUT - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - 1); - } - else { - auto driver_a = driving_lut->getPort("\\A").chunks(); - for (auto &chunk : driver_a) - chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - driver_a, - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - driver_lut); - } + if (!driving_lut) { + // If a driver couldn't be found (could be from PI, + // or from a box) then implement using a LUT + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + 1); } else { - cell = module->addCell(remap_name(c->name), "$_NOT_"); - cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); - cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); - cell_stats[RTLIL::unescape_id(c->type)]++; + auto driver_a = driving_lut->getPort("\\A").chunks(); + for (auto &chunk : driver_a) + chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); + for (auto &b : driver_lut.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + driver_a, + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + driver_lut); } - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - continue; } + else { + cell = module->addCell(remap_name(c->name), "$_NOT_"); + cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); + cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); + cell_stats[RTLIL::unescape_id(c->type)]++; + } + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + continue; } cell_stats[RTLIL::unescape_id(c->type)]++; @@ -734,7 +705,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } struct Abc9Pass : public Pass { - Abc9Pass() : Pass("abc9", "use ABC for technology mapping") { } + Abc9Pass() : Pass("abc9", "use ABC9 for technology mapping") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -762,76 +733,29 @@ struct Abc9Pass : public Pass { log("\n"); log(" if no -script parameter is given, the following scripts are used:\n"); log("\n"); - log(" for -liberty without -constr:\n"); - 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/-luts (only one LUT size):\n"); - log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack {S}").c_str()); + log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); log("\n"); log(" for -lut/-luts (different LUT sizes):\n"); log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str()); log("\n"); - log(" for -sop:\n"); - log("%s\n", fold_abc_cmd(ABC_COMMAND_SOP).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", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str()); - log("\n"); log(" for -lut/-luts:\n"); log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str()); log("\n"); - log(" for -sop:\n"); - log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_SOP).c_str()); - log("\n"); - log(" otherwise:\n"); - log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str()); - log("\n"); - log(" -liberty \n"); - log(" generate netlists for the specified cell library (using the liberty\n"); - log(" file format).\n"); - log("\n"); - log(" -constr \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 \n"); - log(" set_load \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 \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(" this also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); - log(" default scripts above.\n"); - log("\n"); - log(" -I \n"); - log(" maximum number of SOP inputs.\n"); - log(" (replaces {I} in the default scripts above)\n"); - log("\n"); - log(" -P \n"); - log(" maximum number of SOP products.\n"); - log(" (replaces {P} in the default scripts above)\n"); - log("\n"); - log(" -S \n"); - log(" maximum number of LUT inputs shared.\n"); - log(" (replaces {S} in the default scripts above, default: -S 1)\n"); - log("\n"); +// log(" -D \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(" this also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); +// log(" default scripts above.\n"); +// log("\n"); +// log(" -S \n"); +// log(" maximum number of LUT inputs shared.\n"); +// log(" (replaces {S} in the default scripts above, default: -S 1)\n"); +// log("\n"); log(" -lut \n"); log(" generate netlist using luts of (max) the specified width.\n"); log("\n"); @@ -848,42 +772,19 @@ struct Abc9Pass : public Pass { log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); - log(" -sop\n"); - log(" map to sum-of-product cells and inverters\n"); - log("\n"); - // log(" -mux4, -mux8, -mux16\n"); - // log(" try to extract 4-input, 8-input, and/or 16-input muxes\n"); - // log(" (ignored when used with -liberty or -lut)\n"); - // log("\n"); - log(" -g type1,type2,...\n"); - log(" Map to the specified list of gate types. Supported gates types are:\n"); - log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n"); - log(" (The NOT gate is always added to this list automatically.)\n"); - log("\n"); - log(" The following aliases can be used to reference common sets of gate types:\n"); - log(" simple: AND OR XOR MUX\n"); - log(" cmos2: NAND NOR\n"); - log(" cmos3: NAND NOR AOI3 OAI3\n"); - log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n"); - log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); - log(" aig: AND NAND OR NOR ANDNOT ORNOT\n"); - log("\n"); - log(" Prefix a gate type with a '-' to remove it from the list. For example\n"); - log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\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 [!][,[!]]\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 $_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 [!][,[!]]\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(" -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"); @@ -900,14 +801,11 @@ struct Abc9Pass : public Pass { log(" -box \n"); log(" pass this file with box library to ABC. Use with -lut.\n"); log("\n"); - log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n"); - log("loaded into ABC before the ABC script is executed.\n"); - log("\n"); log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); log("ABC on logic snippets extracted from your design. You will not get any useful\n"); log("output when passing an ABC script that writes a file. Instead write your full\n"); - log("design as BLIF file with write_blif and the load that into ABC externally if\n"); + log("design as BLIF file with write_blif and then load that into ABC externally if\n"); log("you want to use ABC to convert your design into another format.\n"); log("\n"); log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n"); @@ -915,7 +813,7 @@ struct Abc9Pass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing ABC9 pass (technology mapping using ABC).\n"); + log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n"); log_push(); assign_map.clear(); @@ -929,8 +827,8 @@ struct Abc9Pass : public Pass { #else 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", wire_delay; + std::string script_file, clk_str, box_file, lut_file; + std::string delay_target, 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 lut_costs; @@ -972,36 +870,14 @@ struct Abc9Pass : public Pass { 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()) { - constr_file = args[++argidx]; - rewrite_filename(constr_file); - if (!constr_file.empty() && !is_absolute_path(constr_file)) - constr_file = std::string(pwd) + "/" + constr_file; - continue; - } if (arg == "-D" && argidx+1 < args.size()) { delay_target = "-D " + args[++argidx]; continue; } - if (arg == "-I" && argidx+1 < args.size()) { - sop_inputs = "-I " + args[++argidx]; - continue; - } - if (arg == "-P" && argidx+1 < args.size()) { - sop_products = "-P " + args[++argidx]; - continue; - } - if (arg == "-S" && argidx+1 < args.size()) { - lutin_shared = "-S " + args[++argidx]; - continue; - } + //if (arg == "-S" && argidx+1 < args.size()) { + // lutin_shared = "-S " + args[++argidx]; + // continue; + //} if (arg == "-lut" && argidx+1 < args.size()) { string arg = args[++argidx]; size_t pos = arg.find_first_of(':'); @@ -1045,126 +921,23 @@ struct Abc9Pass : public Pass { } continue; } - if (arg == "-sop") { - sop_mode = true; - continue; - } - if (arg == "-mux4") { - map_mux4 = true; - continue; - } - if (arg == "-mux8") { - map_mux8 = true; - continue; - } - if (arg == "-mux16") { - map_mux16 = true; - continue; - } - if (arg == "-dress") { - // TODO - //abc_dress = true; - continue; - } - if (arg == "-g" && argidx+1 < args.size()) { - for (auto g : split_tokens(args[++argidx], ",")) { - vector 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 == "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") { - gate_list.push_back("NAND"); - gate_list.push_back("NOR"); - goto ok_alias; - } - if (g == "cmos3") { - 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") { - 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 == "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; - } - 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); - } - } - continue; - } if (arg == "-fast") { fast_mode = true; continue; } - if (arg == "-dff") { - dff_mode = true; - continue; - } - if (arg == "-clk" && argidx+1 < args.size()) { - clk_str = args[++argidx]; - dff_mode = true; - continue; - } - if (arg == "-keepff") { - keepff = true; - continue; - } + //if (arg == "-dff") { + // dff_mode = true; + // continue; + //} + //if (arg == "-clk" && argidx+1 < args.size()) { + // clk_str = args[++argidx]; + // dff_mode = true; + // continue; + //} + //if (arg == "-keepff") { + // keepff = true; + // continue; + //} if (arg == "-nocleanup") { cleanup = false; continue; @@ -1192,11 +965,6 @@ struct Abc9Pass : public Pass { } extra_args(args, argidx, design); - if ((!lut_costs.empty() || !lut_file.empty()) && !liberty_file.empty()) - log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); - if (!constr_file.empty() && liberty_file.empty()) - log_cmd_error("Got -constr but no -liberty!\n"); - for (auto mod : design->selected_modules()) { if (mod->attributes.count("\\abc_box_id")) @@ -1228,8 +996,8 @@ struct Abc9Pass : public Pass { } 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, + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, + delay_target, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, box_file, lut_file, wire_delay); continue; } @@ -1374,8 +1142,8 @@ struct Abc9Pass : public Pass { clk_sig = assign_map(std::get<1>(it.first)); en_polarity = std::get<2>(it.first); 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, + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", + keepff, delay_target, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, box_file, lut_file, wire_delay); assign_map.set(mod); } From c04482b07798cfcca3218cfafe0998eeb6a88f76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 16:54:12 -0700 Subject: [PATCH 394/514] Update CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 839fefcf1..6e3faa9ff 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "rename -src" - Added "equiv_opt" pass - Added "read_aiger" frontend + - Added "abc9" pass (experimental, accessible using synth_xilinx -abc9 and synth_ice40 -abc9) - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From 9d34cea65af5b34ce0930fb892fca6742db898ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 08:22:22 -0700 Subject: [PATCH 395/514] More accurate CHANGELOG --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 6e3faa9ff..139f71672 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,7 +17,9 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "rename -src" - Added "equiv_opt" pass - Added "read_aiger" frontend - - Added "abc9" pass (experimental, accessible using synth_xilinx -abc9 and synth_ice40 -abc9) + - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) + - Added "synth_xilinx -abc9" (experimental) + - Added "synth_ice40 -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From 2052806d3361dca8a866aee0665af223db51bdbd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 08:24:33 -0700 Subject: [PATCH 396/514] Fix LP SB_LUT4 timing --- techlibs/ice40/abc_lp.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index dbc98d0c4..eb1cd0937 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -110,4 +110,4 @@ SB_CARRY 21 1 3 1 # Inputs: I0 I1 I2 I3 # Outputs: O SB_LUT4 22 1 4 1 -465 558 589 661 +661 589 558 465 From 7f9d2d18251c3bec667993c744b568bbbe1a75ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 09:15:30 -0700 Subject: [PATCH 397/514] Update CHANGELOG with "synth -abc9" --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 139f71672..44e32c6a8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) + - Added "synth -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From d39a5a77a9ec58ea97af91c961b02b5a55deaaa7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 13:13:48 -0700 Subject: [PATCH 398/514] Add ConstEvalAig specialised for AIGs --- frontends/aiger/aigerparse.cc | 5 +- kernel/consteval.h | 157 ++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 72b37d21d..42b3c7624 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -234,7 +234,7 @@ void AigerReader::parse_xaiger() uint32_t lutNum = parse_xaiger_literal(f); uint32_t lutSize = parse_xaiger_literal(f); log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); - ConstEval ce(module); + ConstEvalAig ce(module); for (unsigned i = 0; i < lutNum; ++i) { uint32_t rootNodeID = parse_xaiger_literal(f); uint32_t cutLeavesM = parse_xaiger_literal(f); @@ -251,12 +251,11 @@ void AigerReader::parse_xaiger() } RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); for (int j = 0; j < (1 << cutLeavesM); ++j) { - ce.push(); + ce.clear(); ce.set(input_sig, RTLIL::Const{j, static_cast(cutLeavesM)}); RTLIL::SigSpec o(output_sig); ce.eval(o); lut_mask[j] = o.as_const()[0]; - ce.pop(); } RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); log_assert(output_cell); diff --git a/kernel/consteval.h b/kernel/consteval.h index 154373a8d..59e3ef20f 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -390,6 +390,163 @@ struct ConstEval } }; +struct ConstEvalAig +{ + RTLIL::Module *module; + //SigMap assign_map; + SigMap values_map; + //SigPool stop_signals; + SigSet sig2driver; + std::set busy; + std::vector stack; + //RTLIL::State defaultval; + + ConstEvalAig(RTLIL::Module *module /*, RTLIL::State defaultval = RTLIL::State::Sm*/) : module(module) /*, assign_map(module), defaultval(defaultval)*/ + { + CellTypes ct; + ct.setup_internals(); + ct.setup_stdcells(); + + for (auto &it : module->cells_) { + if (!ct.cell_known(it.second->type)) + continue; + for (auto &it2 : it.second->connections()) + if (ct.cell_output(it.second->type, it2.first)) + sig2driver.insert(/*assign_map*/(it2.second), it.second); + } + } + + void clear() + { + values_map.clear(); + //stop_signals.clear(); + } + + void push() + { + stack.push_back(values_map); + } + + void pop() + { + values_map.swap(stack.back()); + stack.pop_back(); + } + + void set(RTLIL::SigSpec sig, RTLIL::Const value) + { + //assign_map.apply(sig); +#ifndef NDEBUG + RTLIL::SigSpec current_val = values_map(sig); + for (int i = 0; i < GetSize(current_val); i++) + log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); +#endif + values_map.add(sig, RTLIL::SigSpec(value)); + } + + //void stop(RTLIL::SigSpec sig) + //{ + // assign_map.apply(sig); + // stop_signals.add(sig); + //} + + bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef) + { + RTLIL::SigSpec sig_y = values_map(/*assign_map*/(cell->getPort("\\Y"))); + if (sig_y.is_fully_const()) + return true; + + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + if (sig_a.size() > 0 && !eval(sig_a, undef, cell)) + return false; + + RTLIL::Const eval_ret; + if (cell->type == "$_NOT_") { + if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1; + else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0; + } + else if (cell->type == "$_AND_") { + if (sig_a == RTLIL::S0) { + eval_ret = RTLIL::S0; + goto eval_end; + } + + { + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + if (sig_b.size() > 0 && !eval(sig_b, undef, cell)) + return false; + if (sig_b == RTLIL::S0) { + eval_ret = RTLIL::S0; + goto eval_end; + } + + if (sig_a != RTLIL::State::S1 || sig_b != RTLIL::State::S1) { + eval_ret = RTLIL::State::Sx; + goto eval_end; + } + + eval_ret = RTLIL::State::S1; + } + } + else log_abort(); + + +eval_end: + set(sig_y, eval_ret); + return true; + } + + bool eval(RTLIL::SigSpec &sig, RTLIL::SigSpec &undef, RTLIL::Cell *busy_cell = NULL) + { + //assign_map.apply(sig); + values_map.apply(sig); + + if (sig.is_fully_const()) + return true; + + //if (stop_signals.check_any(sig)) { + // undef = stop_signals.extract(sig); + // return false; + //} + + if (busy_cell) { + if (busy.count(busy_cell) > 0) { + undef = sig; + return false; + } + busy.insert(busy_cell); + } + + std::set driver_cells; + sig2driver.find(sig, driver_cells); + for (auto cell : driver_cells) { + if (!eval(cell, undef)) { + if (busy_cell) + busy.erase(busy_cell); + return false; + } + } + + if (busy_cell) + busy.erase(busy_cell); + + values_map.apply(sig); + if (sig.is_fully_const()) + return true; + + for (auto &c : sig.chunks()) + if (c.wire != NULL) + undef.append(c); + return false; + } + + bool eval(RTLIL::SigSpec &sig) + { + RTLIL::SigSpec undef; + return eval(sig, undef); + } +}; + YOSYS_NAMESPACE_END #endif From 63e2f83632a760d64e64f8e03529de941301125e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 13:29:03 -0700 Subject: [PATCH 399/514] More slimming --- kernel/consteval.h | 70 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/kernel/consteval.h b/kernel/consteval.h index 59e3ef20f..e0131b233 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -397,8 +397,8 @@ struct ConstEvalAig SigMap values_map; //SigPool stop_signals; SigSet sig2driver; - std::set busy; - std::vector stack; + //std::set busy; + //std::vector stack; //RTLIL::State defaultval; ConstEvalAig(RTLIL::Module *module /*, RTLIL::State defaultval = RTLIL::State::Sm*/) : module(module) /*, assign_map(module), defaultval(defaultval)*/ @@ -422,16 +422,16 @@ struct ConstEvalAig //stop_signals.clear(); } - void push() - { - stack.push_back(values_map); - } + //void push() + //{ + // stack.push_back(values_map); + //} - void pop() - { - values_map.swap(stack.back()); - stack.pop_back(); - } + //void pop() + //{ + // values_map.swap(stack.back()); + // stack.pop_back(); + //} void set(RTLIL::SigSpec sig, RTLIL::Const value) { @@ -450,14 +450,14 @@ struct ConstEvalAig // stop_signals.add(sig); //} - bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef) + bool eval(RTLIL::Cell *cell /*, RTLIL::SigSpec &undef*/) { RTLIL::SigSpec sig_y = values_map(/*assign_map*/(cell->getPort("\\Y"))); if (sig_y.is_fully_const()) return true; RTLIL::SigSpec sig_a = cell->getPort("\\A"); - if (sig_a.size() > 0 && !eval(sig_a, undef, cell)) + if (sig_a.size() > 0 && !eval(sig_a /*, undef, cell*/)) return false; RTLIL::Const eval_ret; @@ -473,7 +473,7 @@ struct ConstEvalAig { RTLIL::SigSpec sig_b = cell->getPort("\\B"); - if (sig_b.size() > 0 && !eval(sig_b, undef, cell)) + if (sig_b.size() > 0 && !eval(sig_b /*, undef, cell*/)) return false; if (sig_b == RTLIL::S0) { eval_ret = RTLIL::S0; @@ -496,7 +496,7 @@ eval_end: return true; } - bool eval(RTLIL::SigSpec &sig, RTLIL::SigSpec &undef, RTLIL::Cell *busy_cell = NULL) + bool eval(RTLIL::SigSpec &sig /*, RTLIL::SigSpec &undef, RTLIL::Cell *busy_cell = NULL*/) { //assign_map.apply(sig); values_map.apply(sig); @@ -509,42 +509,42 @@ eval_end: // return false; //} - if (busy_cell) { - if (busy.count(busy_cell) > 0) { - undef = sig; - return false; - } - busy.insert(busy_cell); - } + //if (busy_cell) { + // if (busy.count(busy_cell) > 0) { + // undef = sig; + // return false; + // } + // busy.insert(busy_cell); + //} std::set driver_cells; sig2driver.find(sig, driver_cells); for (auto cell : driver_cells) { - if (!eval(cell, undef)) { - if (busy_cell) - busy.erase(busy_cell); + if (!eval(cell /*, undef*/)) { + //if (busy_cell) + // busy.erase(busy_cell); return false; } } - if (busy_cell) - busy.erase(busy_cell); + //if (busy_cell) + // busy.erase(busy_cell); values_map.apply(sig); if (sig.is_fully_const()) return true; - for (auto &c : sig.chunks()) - if (c.wire != NULL) - undef.append(c); + //for (auto &c : sig.chunks()) + // if (c.wire != NULL) + // undef.append(c); return false; } - bool eval(RTLIL::SigSpec &sig) - { - RTLIL::SigSpec undef; - return eval(sig, undef); - } + //bool eval(RTLIL::SigSpec &sig) + //{ + // RTLIL::SigSpec undef; + // return eval(sig, undef); + //} }; YOSYS_NAMESPACE_END From 75d89e56cfd9472605f27570cf2760ff89dc7603 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 14:27:07 -0700 Subject: [PATCH 400/514] Fix name clash --- techlibs/xilinx/cells_map.v | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 8291f5647..b5114758c 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -19,11 +19,15 @@ */ // Convert negative-polarity reset to positive-polarity -module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +(* techmap_celltype = "$_DFF_NN0_" *) +module _90_dff_nn0_to_np0(input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +(* techmap_celltype = "$_DFF_PN0_" *) +module _90_dff_pn0_to_pp0(input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +(* techmap_celltype = "$_DFF_NN1_" *) +module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +(* techmap_celltype = "$_DFF_PN1_" *) +module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule module \$__SHREG_ (input C, input D, input E, output Q); From d09d4e0706e806d53b3b83986f49c1d59435d2ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 16:28:11 -0700 Subject: [PATCH 401/514] Move ConstEvalAig to aigerparse.cc --- frontends/aiger/aigerparse.cc | 164 +++++++++++++++++++++++++++++++++- kernel/consteval.h | 157 -------------------------------- 2 files changed, 161 insertions(+), 160 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 42b3c7624..3b5f413df 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -35,6 +35,162 @@ YOSYS_NAMESPACE_BEGIN +struct ConstEvalAig +{ + RTLIL::Module *module; + dict values_map; + SigSet sig2driver; + dict> sig2deps; + + ConstEvalAig(RTLIL::Module *module) : module(module) + { + CellTypes ct; + ct.setup_internals(); + ct.setup_stdcells(); + + for (auto &it : module->cells_) { + if (!ct.cell_known(it.second->type)) + continue; + for (auto &it2 : it.second->connections()) + if (ct.cell_output(it.second->type, it2.first)) + sig2driver.insert(it2.second, it.second); + } + } + + void clear() + { + values_map.clear(); + sig2deps.clear(); + } + + void set(RTLIL::SigSpec sig, RTLIL::Const value) + { +#ifndef NDEBUG + auto it = values_map.find(sig); + RTLIL::SigSpec current_val; + if (it != values_map.end()) + current_val = it->second; + for (int i = 0; i < GetSize(current_val); i++) + log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); +#endif + for (int i = 0; i < GetSize(sig); i++) + values_map[sig[i]] = value[i]; + } + + void set_incremental(RTLIL::SigSpec sig, RTLIL::Const value) + { + log_assert(GetSize(sig) == GetSize(value)); + + for (int i = 0; i < GetSize(sig); i++) { + auto it = values_map.find(sig[i]); + if (it != values_map.end()) { + RTLIL::SigSpec current_val = it->second; + if (current_val != value[i]) + for (auto dep : sig2deps[sig[i]]) + values_map.erase(dep); + it->second = value[i]; + } + else + values_map[sig[i]] = value[i]; + } + } + + void compute_deps(RTLIL::SigBit output, const pool &inputs) + { + sig2deps[output].insert(output); + + std::set driver_cells; + sig2driver.find(output, driver_cells); + for (auto cell : driver_cells) { + RTLIL::SigBit sig_a = cell->getPort("\\A"); + sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_a)) + compute_deps(sig_a, inputs); + + if (cell->type == "$_AND_") { + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_b)) + compute_deps(sig_b, inputs); + } + else if (cell->type == "$_NOT_") { + } + else log_abort(); + } + } + + bool eval(RTLIL::Cell *cell) + { + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + auto it = values_map.find(sig_y); + if (it != values_map.end()) + sig_y = it->second; + if (sig_y.is_fully_const()) + return true; + + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + if (sig_a.size() > 0 && !eval(sig_a)) + return false; + + RTLIL::Const eval_ret; + if (cell->type == "$_NOT_") { + if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1; + else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0; + } + else if (cell->type == "$_AND_") { + if (sig_a == RTLIL::S0) { + eval_ret = RTLIL::S0; + goto eval_end; + } + + { + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + if (sig_b.size() > 0 && !eval(sig_b)) + return false; + if (sig_b == RTLIL::S0) { + eval_ret = RTLIL::S0; + goto eval_end; + } + + if (sig_a != RTLIL::State::S1 || sig_b != RTLIL::State::S1) { + eval_ret = RTLIL::State::Sx; + goto eval_end; + } + + eval_ret = RTLIL::State::S1; + } + } + else log_abort(); + +eval_end: + set(sig_y, eval_ret); + return true; + } + + bool eval(RTLIL::SigSpec &sig) + { + auto it = values_map.find(sig); + if (it != values_map.end()) + sig = it->second; + if (sig.is_fully_const()) + return true; + + std::set driver_cells; + sig2driver.find(sig, driver_cells); + for (auto cell : driver_cells) + if (!eval(cell)) + return false; + + it = values_map.find(sig); + if (it != values_map.end()) + sig = it->second; + if (sig.is_fully_const()) + return true; + + return false; + } +}; + AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports) { @@ -249,13 +405,15 @@ void AigerReader::parse_xaiger() log_assert(wire); input_sig.append(wire); } + ce.clear(); + ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); for (int j = 0; j < (1 << cutLeavesM); ++j) { - ce.clear(); - ce.set(input_sig, RTLIL::Const{j, static_cast(cutLeavesM)}); + int gray = j ^ (j >> 1); + ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast(cutLeavesM)}); RTLIL::SigSpec o(output_sig); ce.eval(o); - lut_mask[j] = o.as_const()[0]; + lut_mask[gray] = o.as_const()[0]; } RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); log_assert(output_cell); diff --git a/kernel/consteval.h b/kernel/consteval.h index e0131b233..154373a8d 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -390,163 +390,6 @@ struct ConstEval } }; -struct ConstEvalAig -{ - RTLIL::Module *module; - //SigMap assign_map; - SigMap values_map; - //SigPool stop_signals; - SigSet sig2driver; - //std::set busy; - //std::vector stack; - //RTLIL::State defaultval; - - ConstEvalAig(RTLIL::Module *module /*, RTLIL::State defaultval = RTLIL::State::Sm*/) : module(module) /*, assign_map(module), defaultval(defaultval)*/ - { - CellTypes ct; - ct.setup_internals(); - ct.setup_stdcells(); - - for (auto &it : module->cells_) { - if (!ct.cell_known(it.second->type)) - continue; - for (auto &it2 : it.second->connections()) - if (ct.cell_output(it.second->type, it2.first)) - sig2driver.insert(/*assign_map*/(it2.second), it.second); - } - } - - void clear() - { - values_map.clear(); - //stop_signals.clear(); - } - - //void push() - //{ - // stack.push_back(values_map); - //} - - //void pop() - //{ - // values_map.swap(stack.back()); - // stack.pop_back(); - //} - - void set(RTLIL::SigSpec sig, RTLIL::Const value) - { - //assign_map.apply(sig); -#ifndef NDEBUG - RTLIL::SigSpec current_val = values_map(sig); - for (int i = 0; i < GetSize(current_val); i++) - log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); -#endif - values_map.add(sig, RTLIL::SigSpec(value)); - } - - //void stop(RTLIL::SigSpec sig) - //{ - // assign_map.apply(sig); - // stop_signals.add(sig); - //} - - bool eval(RTLIL::Cell *cell /*, RTLIL::SigSpec &undef*/) - { - RTLIL::SigSpec sig_y = values_map(/*assign_map*/(cell->getPort("\\Y"))); - if (sig_y.is_fully_const()) - return true; - - RTLIL::SigSpec sig_a = cell->getPort("\\A"); - if (sig_a.size() > 0 && !eval(sig_a /*, undef, cell*/)) - return false; - - RTLIL::Const eval_ret; - if (cell->type == "$_NOT_") { - if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1; - else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0; - } - else if (cell->type == "$_AND_") { - if (sig_a == RTLIL::S0) { - eval_ret = RTLIL::S0; - goto eval_end; - } - - { - RTLIL::SigSpec sig_b = cell->getPort("\\B"); - if (sig_b.size() > 0 && !eval(sig_b /*, undef, cell*/)) - return false; - if (sig_b == RTLIL::S0) { - eval_ret = RTLIL::S0; - goto eval_end; - } - - if (sig_a != RTLIL::State::S1 || sig_b != RTLIL::State::S1) { - eval_ret = RTLIL::State::Sx; - goto eval_end; - } - - eval_ret = RTLIL::State::S1; - } - } - else log_abort(); - - -eval_end: - set(sig_y, eval_ret); - return true; - } - - bool eval(RTLIL::SigSpec &sig /*, RTLIL::SigSpec &undef, RTLIL::Cell *busy_cell = NULL*/) - { - //assign_map.apply(sig); - values_map.apply(sig); - - if (sig.is_fully_const()) - return true; - - //if (stop_signals.check_any(sig)) { - // undef = stop_signals.extract(sig); - // return false; - //} - - //if (busy_cell) { - // if (busy.count(busy_cell) > 0) { - // undef = sig; - // return false; - // } - // busy.insert(busy_cell); - //} - - std::set driver_cells; - sig2driver.find(sig, driver_cells); - for (auto cell : driver_cells) { - if (!eval(cell /*, undef*/)) { - //if (busy_cell) - // busy.erase(busy_cell); - return false; - } - } - - //if (busy_cell) - // busy.erase(busy_cell); - - values_map.apply(sig); - if (sig.is_fully_const()) - return true; - - //for (auto &c : sig.chunks()) - // if (c.wire != NULL) - // undef.append(c); - return false; - } - - //bool eval(RTLIL::SigSpec &sig) - //{ - // RTLIL::SigSpec undef; - // return eval(sig, undef); - //} -}; - YOSYS_NAMESPACE_END #endif From bc22e2e3ee120aeb84323ce52031b895f9f62f54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 17:02:58 -0700 Subject: [PATCH 402/514] Optimise some more --- frontends/aiger/aigerparse.cc | 109 ++++++++++++++++------------------ 1 file changed, 52 insertions(+), 57 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3b5f413df..9c6096655 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -38,8 +38,8 @@ YOSYS_NAMESPACE_BEGIN struct ConstEvalAig { RTLIL::Module *module; - dict values_map; - SigSet sig2driver; + dict values_map; + dict sig2driver; dict> sig2deps; ConstEvalAig(RTLIL::Module *module) : module(module) @@ -52,8 +52,10 @@ struct ConstEvalAig if (!ct.cell_known(it.second->type)) continue; for (auto &it2 : it.second->connections()) - if (ct.cell_output(it.second->type, it2.first)) - sig2driver.insert(it2.second, it.second); + if (ct.cell_output(it.second->type, it2.first)) { + auto r = sig2driver.insert(std::make_pair(it2.second, it.second)); + log_assert(r.second); + } } } @@ -63,18 +65,19 @@ struct ConstEvalAig sig2deps.clear(); } - void set(RTLIL::SigSpec sig, RTLIL::Const value) + void set(RTLIL::SigBit sig, RTLIL::State value) { -#ifndef NDEBUG auto it = values_map.find(sig); - RTLIL::SigSpec current_val; - if (it != values_map.end()) - current_val = it->second; - for (int i = 0; i < GetSize(current_val); i++) - log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); +#ifndef NDEBUG + if (it != values_map.end()) { + RTLIL::State current_val = it->second; + log_assert(current_val == value); + } #endif - for (int i = 0; i < GetSize(sig); i++) - values_map[sig[i]] = value[i]; + if (it != values_map.end()) + it->second = value; + else + values_map[sig] = value; } void set_incremental(RTLIL::SigSpec sig, RTLIL::Const value) @@ -84,7 +87,7 @@ struct ConstEvalAig for (int i = 0; i < GetSize(sig); i++) { auto it = values_map.find(sig[i]); if (it != values_map.end()) { - RTLIL::SigSpec current_val = it->second; + RTLIL::State current_val = it->second; if (current_val != value[i]) for (auto dep : sig2deps[sig[i]]) values_map.erase(dep); @@ -99,40 +102,34 @@ struct ConstEvalAig { sig2deps[output].insert(output); - std::set driver_cells; - sig2driver.find(output, driver_cells); - for (auto cell : driver_cells) { - RTLIL::SigBit sig_a = cell->getPort("\\A"); - sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); - if (!inputs.count(sig_a)) - compute_deps(sig_a, inputs); + RTLIL::Cell *cell = sig2driver.at(output); + RTLIL::SigBit sig_a = cell->getPort("\\A"); + sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_a)) + compute_deps(sig_a, inputs); - if (cell->type == "$_AND_") { - RTLIL::SigSpec sig_b = cell->getPort("\\B"); - sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); - if (!inputs.count(sig_b)) - compute_deps(sig_b, inputs); - } - else if (cell->type == "$_NOT_") { - } - else log_abort(); + if (cell->type == "$_AND_") { + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_b)) + compute_deps(sig_b, inputs); } + else if (cell->type == "$_NOT_") { + } + else log_abort(); } bool eval(RTLIL::Cell *cell) { - RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - auto it = values_map.find(sig_y); - if (it != values_map.end()) - sig_y = it->second; - if (sig_y.is_fully_const()) + RTLIL::SigBit sig_y = cell->getPort("\\Y"); + if (values_map.count(sig_y)) return true; - RTLIL::SigSpec sig_a = cell->getPort("\\A"); - if (sig_a.size() > 0 && !eval(sig_a)) + RTLIL::SigBit sig_a = cell->getPort("\\A"); + if (!eval(sig_a)) return false; - RTLIL::Const eval_ret; + RTLIL::State eval_ret = RTLIL::Sx; if (cell->type == "$_NOT_") { if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1; else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0; @@ -144,20 +141,18 @@ struct ConstEvalAig } { - RTLIL::SigSpec sig_b = cell->getPort("\\B"); - if (sig_b.size() > 0 && !eval(sig_b)) + RTLIL::SigBit sig_b = cell->getPort("\\B"); + if (!eval(sig_b)) return false; if (sig_b == RTLIL::S0) { eval_ret = RTLIL::S0; goto eval_end; } - if (sig_a != RTLIL::State::S1 || sig_b != RTLIL::State::S1) { - eval_ret = RTLIL::State::Sx; + if (sig_a != RTLIL::S1 || sig_b != RTLIL::S1) goto eval_end; - } - eval_ret = RTLIL::State::S1; + eval_ret = RTLIL::S1; } } else log_abort(); @@ -167,25 +162,23 @@ eval_end: return true; } - bool eval(RTLIL::SigSpec &sig) + bool eval(RTLIL::SigBit &sig) { auto it = values_map.find(sig); - if (it != values_map.end()) + if (it != values_map.end()) { sig = it->second; - if (sig.is_fully_const()) return true; + } - std::set driver_cells; - sig2driver.find(sig, driver_cells); - for (auto cell : driver_cells) - if (!eval(cell)) - return false; + RTLIL::Cell *cell = sig2driver.at(sig); + if (!eval(cell)) + return false; it = values_map.find(sig); - if (it != values_map.end()) + if (it != values_map.end()) { sig = it->second; - if (sig.is_fully_const()) return true; + } return false; } @@ -411,9 +404,11 @@ void AigerReader::parse_xaiger() for (int j = 0; j < (1 << cutLeavesM); ++j) { int gray = j ^ (j >> 1); ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast(cutLeavesM)}); - RTLIL::SigSpec o(output_sig); - ce.eval(o); - lut_mask[gray] = o.as_const()[0]; + RTLIL::SigBit o(output_sig); + bool success = ce.eval(o); + log_assert(success); + log_assert(o.wire == nullptr); + lut_mask[gray] = o.data; } RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID)); log_assert(output_cell); From 95665730540c0fd7c76690f28d0fd6b5f13f2223 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 14 Jun 2019 12:02:12 +0100 Subject: [PATCH 403/514] ecp5: Add abc9 option Signed-off-by: David Shah --- backends/aiger/xaiger.cc | 3 +- passes/techmap/abc9.cc | 9 +++ techlibs/ecp5/Makefile.inc | 3 + techlibs/ecp5/abc_5g.box | 36 +++++++++++ techlibs/ecp5/abc_5g.lut | 25 ++++++++ techlibs/ecp5/cells_map.v | 121 ++++++++++++++++++++++-------------- techlibs/ecp5/cells_sim.v | 32 ++++++---- techlibs/ecp5/synth_ecp5.cc | 25 ++++++-- 8 files changed, 188 insertions(+), 66 deletions(-) create mode 100644 techlibs/ecp5/abc_5g.box create mode 100644 techlibs/ecp5/abc_5g.lut diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5fa20c9c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -833,8 +833,7 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - //Pass::call(holes_module->design, "techmap"); - + Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); Pass::call(holes_module->design, "clean -purge"); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a6ec4a6fb..d4f5c5238 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -22,7 +22,16 @@ // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification // http://www.eecs.berkeley.edu/~alanmi/abc/ +#if 0 +// Based on &flow3 - better QoR but more experimental +#define ABC_COMMAND_LUT "&st; &ps -l; "/*"&sweep -v;"*/" &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W}; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W}; &save; &load" +#else #define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} -v; "/*"&mfs; "*/"&ps -l" +#endif + #define ABC_FAST_COMMAND_LUT "&st; &retime; &if {W}" diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 4db087e87..eee3b418f 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -11,6 +11,9 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.box)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut)) + EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk .SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc_5g.box new file mode 100644 index 000000000..72af6d9cb --- /dev/null +++ b/techlibs/ecp5/abc_5g.box @@ -0,0 +1,36 @@ +# Box 1 : CCU2C (2xCARRY + 2xLUT4) +# Outputs: S0, S1, COUT +# name ID w/b ins outs +CCU2C 1 1 9 3 + +#A0 A1 B0 B1 C0 C1 D0 D1 CIN +379 - 379 - 275 - 141 - 257 +630 379 630 379 526 275 392 141 273 +516 516 516 516 412 412 278 278 43 + +# Box 2 : TRELLIS_DPR16X4 (16x4 dist ram) +# Outputs: DO0, DO1, DO2, DO3, DO4 +# name ID w/b ins outs +TRELLIS_DPR16X4 2 0 14 4 + +#DI0 DI1 DI2 DI3 RAD0 RAD1 RAD2 RAD3 WAD0 WAD1 WAD2 WAD3 WCK WRE +- - - - 141 379 275 379 - - - - - - +- - - - 141 379 275 379 - - - - - - +- - - - 141 379 275 379 - - - - - - +- - - - 141 379 275 379 - - - - - - + +# Box 3 : PFUMX (MUX2) +# Outputs: Z +# name ID w/b ins outs +PFUMX 3 1 3 1 + +#ALUT BLUT C0 +98 98 151 + +# Box 4 : L6MUX21 (MUX2) +# Outputs: Z +# name ID w/b ins outs +L6MUX21 4 1 3 1 + +#D0 D1 SD +140 141 148 diff --git a/techlibs/ecp5/abc_5g.lut b/techlibs/ecp5/abc_5g.lut new file mode 100644 index 000000000..e8aa9b35d --- /dev/null +++ b/techlibs/ecp5/abc_5g.lut @@ -0,0 +1,25 @@ +# ECP5-5G LUT library for ABC +# Note that ECP5 architecture assigns difference +# in LUT input delay to interconnect, so this is +# considered too + + +# Simple LUTs +# area D C B A +1 1 141 +2 1 141 275 +3 1 141 275 379 +4 1 141 275 379 379 + +# LUT5 = 2x LUT4 + PFUMX +# area M0 D C B A +5 2 151 239 373 477 477 + +# LUT6 = 2x LUT5 + MUX2 +# area M1 M0 D C B A +6 4 148 292 380 514 618 618 + +# LUT7 = 2x LUT6 + MUX2 +# area M2 M1 M0 D C B A +7 8 148 289 433 521 655 759 759 + diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index f6c71a03d..53a89e8a3 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -70,80 +70,107 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; + + // Need to swap input ordering, and fix init accordingly, + // to match ABC's expectation of LUT inputs in non-decreasing + // delay order + localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH; + function [P_WIDTH-1:0] permute_index; + input [P_WIDTH-1:0] i; + integer j; + begin + permute_index = 0; + for (j = 0; j < P_WIDTH; j = j + 1) + permute_index[P_WIDTH-1 - j] = i[j]; + end + endfunction + + function [2**P_WIDTH-1:0] permute_init; + input [2**P_WIDTH-1:0] orig; + integer i; + begin + permute_init = 0; + for (i = 0; i < 2**P_WIDTH; i = i + 1) + permute_init[i] = orig[permute_index(i)]; + end + endfunction + + parameter [2**P_WIDTH-1:0] P_LUT = permute_init(LUT); + input [WIDTH-1:0] A; output Y; generate if (WIDTH == 1) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0)); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0])); end else if (WIDTH == 2) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0)); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0])); end else if (WIDTH == 3) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0)); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0])); end else if (WIDTH == 4) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), + .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0])); `ifndef NO_PFUMUX end else if (WIDTH == 5) begin wire f0, f1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y)); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); + PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y)); end else if (WIDTH == 6) begin wire f0, f1, f2, f3, g0, g1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); - LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); + LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), + .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); - PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); - PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); - L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y)); + PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0)); + PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1)); + L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y)); end else if (WIDTH == 7) begin wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1; - LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); - LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); - LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); - LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); - LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7), - .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); + LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7), + .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); - PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); - PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); - PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2)); - PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3)); - L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0)); - L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1)); - L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y)); + PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0)); + PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1)); + PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2)); + PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3)); + L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0)); + L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1)); + L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y)); `endif end else begin wire _TECHMAP_FAIL_ = 1; diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 1e4002ee0..430aadbd7 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -9,15 +9,17 @@ module LUT4(input A, B, C, D, output Z); endmodule // --------------------------------------- - +(* abc_box_id=4, lib_whitebox *) module L6MUX21 (input D0, D1, SD, output Z); assign Z = SD ? D1 : D0; endmodule // --------------------------------------- - -module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1, - output S0, S1, COUT); +(* abc_box_id=1, abc_carry, lib_whitebox *) +module CCU2C((* abc_carry_in *) input CIN, + input A0, B0, C0, D0, A1, B1, C1, D1, + output S0, S1, + (* abc_carry_out *) output COUT); parameter [15:0] INIT0 = 16'h0000; parameter [15:0] INIT1 = 16'h0000; @@ -26,9 +28,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1, // First half wire LUT4_0, LUT2_0; +`ifdef _ABC + assign LUT4_0 = INIT0[{D0, C0, B0, A0}]; + assign LUT2_0 = INIT0[{2'b00, B0, A0}]; +`else LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0)); LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0)); - +`endif wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN; assign S0 = LUT4_0 ^ gated_cin_0; @@ -37,9 +43,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1, // Second half wire LUT4_1, LUT2_1; +`ifdef _ABC + assign LUT4_1 = INIT1[{D1, C1, B1, A1}]; + assign LUT2_1 = INIT1[{2'b00, B1, A1}]; +`else LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1)); LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1)); - +`endif wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0; assign S1 = LUT4_1 ^ gated_cin_1; @@ -90,13 +100,13 @@ module TRELLIS_RAM16X2 ( endmodule // --------------------------------------- - +(* abc_box_id=3, lib_whitebox *) module PFUMX (input ALUT, BLUT, C0, output Z); assign Z = C0 ? ALUT : BLUT; endmodule // --------------------------------------- - +(* abc_box_id=2 *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, @@ -203,7 +213,7 @@ endmodule // --------------------------------------- -module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); +module TRELLIS_FF(input CLK, LSR, CE, DI, M, (* abc_flop_q *) output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; parameter CLKMUX = "CLK"; @@ -464,13 +474,13 @@ module DP16KD( input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0, input CEA, OCEA, CLKA, WEA, RSTA, input CSA2, CSA1, CSA0, - output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0, + (* abc_flop_q *) output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0, input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0, input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0, input CEB, OCEB, CLKB, WEB, RSTB, input CSB2, CSB1, CSB0, - output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 + (* abc_flop_q *) output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 ); parameter DATA_WIDTH_A = 18; parameter DATA_WIDTH_B = 18; diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index c6e12248e..b271500f1 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -82,6 +82,9 @@ struct SynthEcp5Pass : public ScriptPass log(" -abc2\n"); log(" run two passes of 'abc' for slightly improved logic density\n"); log("\n"); + log(" -abc9\n"); + log(" use new ABC9 flow (EXPERIMENTAL)\n"); + log("\n"); log(" -vpr\n"); log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); @@ -93,7 +96,7 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr; + bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, abc9, vpr; void clear_flags() YS_OVERRIDE { @@ -110,6 +113,7 @@ struct SynthEcp5Pass : public ScriptPass retime = false; abc2 = false; vpr = false; + abc9 = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -184,6 +188,10 @@ struct SynthEcp5Pass : public ScriptPass vpr = true; continue; } + if (args[argidx] == "-abc9") { + abc9 = true; + continue; + } break; } extra_args(args, argidx, design); @@ -203,7 +211,7 @@ struct SynthEcp5Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); + run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); } @@ -264,10 +272,15 @@ struct SynthEcp5Pass : public ScriptPass run("abc", " (only if -abc2)"); } run("techmap -map +/ecp5/latches_map.v"); - if (nomux) - run("abc -lut 4 -dress"); - else - run("abc -lut 4:7 -dress"); + if (abc9) { + run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200"); + } else { + if (nomux) + run("abc -lut 4 -dress"); + else + run("abc -lut 4:7 -dress"); + } + run("clean"); } From d005568f2ea8825fdd47ae871f5bdeeaf7e27635 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:11:13 -0700 Subject: [PATCH 404/514] Add TODO to parse_xaiger --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9c6096655..c41772c92 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -398,6 +398,7 @@ void AigerReader::parse_xaiger() log_assert(wire); input_sig.append(wire); } + // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) ce.clear(); ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); From a5425a2f7e86f63ee4df84d15bf58fb9f006b465 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:11:34 -0700 Subject: [PATCH 405/514] Remove extra semicolon --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index a6ec4a6fb..d90b421a8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -395,7 +395,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //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())); + Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); std::string buffer; std::ifstream ifs; From 1948e7c846ea318d003148974945d917701a4452 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:13:17 -0700 Subject: [PATCH 406/514] Cleanup/optimise toposort in write_xaiger --- backends/aiger/xaiger.cc | 101 ++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 54 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5a26548b8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -167,51 +167,12 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - dict> bit_drivers, bit_users; - TopoSort toposort; + SigMap topomap; + topomap.database = sigmap.database; + bool abc_box_seen = false; for (auto cell : module->cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - bool builtin_type = yosys_celltypes.cell_known(cell->type); - bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); - - if (!holes_mode) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (!builtin_type && !abc_type) - continue; - - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (builtin_type) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") - continue; - } - - if (inst_module) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - - if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) - continue; - } - } - - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -219,6 +180,8 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; + if (!holes_mode) + topomap.add(Y, A); continue; } @@ -241,6 +204,10 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); + if (!holes_mode) { + topomap.add(Y, A); + topomap.add(Y, B); + } continue; } @@ -252,6 +219,7 @@ struct XAigerWriter // continue; //} + RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; @@ -322,20 +290,46 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen) { + if (abc_box_seen && !holes_mode) { + TopoSort toposort; + dict> bit_drivers, bit_users; + + for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) + continue; + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : topomap(conn.second)) + if (bit.wire) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + for (auto bit : topomap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } + } + for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - -#if 0 +#if 1 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 0 +#if 1 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -346,13 +340,14 @@ struct XAigerWriter #endif log_assert(no_loops); + pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc_box_id")) - continue; + log_assert(box_module); + log_assert(box_module->attributes.count("\\abc_box_id")); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -448,8 +443,6 @@ struct XAigerWriter } box_list.emplace_back(cell); } - - // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { From a3be25ab0d6040564ad9082db231478b21e021ac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:27:30 -0700 Subject: [PATCH 407/514] Cleanup --- frontends/aiger/aigerparse.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c41772c92..a72a82926 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,7 +30,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/consteval.h" +#include "kernel/celltypes.h" #include "aigerparse.h" YOSYS_NAMESPACE_BEGIN @@ -44,15 +44,11 @@ struct ConstEvalAig ConstEvalAig(RTLIL::Module *module) : module(module) { - CellTypes ct; - ct.setup_internals(); - ct.setup_stdcells(); - for (auto &it : module->cells_) { - if (!ct.cell_known(it.second->type)) + if (!yosys_celltypes.cell_known(it.second->type)) continue; for (auto &it2 : it.second->connections()) - if (ct.cell_output(it.second->type, it2.first)) { + if (yosys_celltypes.cell_output(it.second->type, it2.first)) { auto r = sig2driver.insert(std::make_pair(it2.second, it.second)); log_assert(r.second); } From 1656c44373dbf7375c068d5626e38a76b5a83c4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:29:27 -0700 Subject: [PATCH 408/514] Cleanup --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bba0ec713..daefd3a73 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,7 +20,6 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" #include "kernel/utils.h" USING_YOSYS_NAMESPACE From 627a62a797ef9e676ba9d89f53f927d0c2463585 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:32:46 -0700 Subject: [PATCH 409/514] Make doc consistent --- techlibs/common/synth.cc | 5 ++++- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index ee2e86de9..555de9fba 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -76,7 +76,7 @@ struct SynthPass : public ScriptPass log(" synonymous to the end of the command list.\n"); log("\n"); log(" -abc9\n"); - log(" use abc9 instead of abc\n"); + log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -174,6 +174,9 @@ struct SynthPass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); + if (abc == "abc9" && !lut) + log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)"); + log_header(design, "Executing SYNTH pass.\n"); log_push(); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 5afa042b0..a60829764 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -97,7 +97,7 @@ struct SynthIce40Pass : public ScriptPass log(" (this feature is experimental and incomplete)\n"); log("\n"); log(" -abc9\n"); - log(" use abc9 instead of abc\n"); + log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3ac19e498..69a3d99c2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -82,7 +82,7 @@ struct SynthXilinxPass : public ScriptPass log(" run 'abc' with -dff option\n"); log("\n"); log(" -abc9\n"); - log(" use abc9 instead of abc\n"); + log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); From ee428f73abdbbde95601e583db186d86a8fa6b91 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:37:52 -0700 Subject: [PATCH 410/514] Remove WIP ABC9 flop support --- backends/aiger/xaiger.cc | 64 ++++++++++++++++++------------------- techlibs/ecp5/cells_sim.v | 6 ++-- techlibs/ice40/cells_sim.v | 50 ++++++++++++++--------------- techlibs/xilinx/brams_bb.v | 16 +++++----- techlibs/xilinx/cells_sim.v | 20 ++++++------ 5 files changed, 78 insertions(+), 78 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index daefd3a73..1e70f3230 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -219,37 +219,37 @@ struct XAigerWriter //} RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - RTLIL::Wire* port = inst_module->wire(c.first); - for (auto b : c.second.bits()) { - if (is_input && port->attributes.count("\\abc_flop_d")) { - d = b; - SigBit I = sigmap(d); - if (I != d) - alias_map[I] = d; - unused_bits.erase(d); - } - if (is_output && port->attributes.count("\\abc_flop_q")) { - q = b; - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + //if (inst_flop) { + // SigBit d, q; + // for (const auto &c : cell->connections()) { + // auto is_input = cell->input(c.first); + // auto is_output = cell->output(c.first); + // log_assert(is_input || is_output); + // RTLIL::Wire* port = inst_module->wire(c.first); + // for (auto b : c.second.bits()) { + // if (is_input && port->attributes.count("\\abc_flop_d")) { + // d = b; + // SigBit I = sigmap(d); + // if (I != d) + // alias_map[I] = d; + // unused_bits.erase(d); + // } + // if (is_output && port->attributes.count("\\abc_flop_q")) { + // q = b; + // SigBit O = sigmap(q); + // if (O != q) + // alias_map[O] = q; + // undriven_bits.erase(O); + // } + // } + // } + // if (!abc_box_seen) + // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - ff_bits.emplace_back(d, q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + // ff_bits.emplace_back(d, q); + //} + /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -310,8 +310,8 @@ struct XAigerWriter if (cell->output(conn.first)) { RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + //if (inst_module_port->attributes.count("\\abc_flop_q")) + // continue; for (auto bit : topomap(conn.second)) bit_drivers[bit].insert(cell->name); } diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 430aadbd7..d7184f980 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -213,7 +213,7 @@ endmodule // --------------------------------------- -module TRELLIS_FF(input CLK, LSR, CE, DI, M, (* abc_flop_q *) output reg Q); +module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; parameter CLKMUX = "CLK"; @@ -474,13 +474,13 @@ module DP16KD( input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0, input CEA, OCEA, CLKA, WEA, RSTA, input CSA2, CSA1, CSA0, - (* abc_flop_q *) output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0, + output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0, input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0, input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0, input CEB, OCEB, CLKB, WEB, RSTB, input CSB2, CSB1, CSB0, - (* abc_flop_q *) output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 + output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 ); parameter DATA_WIDTH_A = 18; parameter DATA_WIDTH_B = 18; diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 55b4d98c9..031afa85c 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -143,7 +143,7 @@ endmodule // Positive Edge SiliconBlue FF Cells -module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, D); +module SB_DFF (output `SB_DFF_REG, input C, D); `ifndef _ABC always @(posedge C) Q <= D; @@ -152,13 +152,13 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, D); `endif endmodule -module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); +module SB_DFFE (output `SB_DFF_REG, input C, E, D); always @(posedge C) if (E) Q <= D; endmodule -module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +module SB_DFFSR (output `SB_DFF_REG, input C, R, D); always @(posedge C) if (R) Q <= 0; @@ -166,7 +166,7 @@ module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +module SB_DFFR (output `SB_DFF_REG, input C, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -174,7 +174,7 @@ module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +module SB_DFFSS (output `SB_DFF_REG, input C, S, D); always @(posedge C) if (S) Q <= 1; @@ -182,7 +182,7 @@ module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +module SB_DFFS (output `SB_DFF_REG, input C, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -190,7 +190,7 @@ module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D); always @(posedge C) if (E) begin if (R) @@ -200,7 +200,7 @@ module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +module SB_DFFER (output `SB_DFF_REG, input C, E, R, D); always @(posedge C, posedge R) if (R) Q <= 0; @@ -208,7 +208,7 @@ module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D); always @(posedge C) if (E) begin if (S) @@ -218,7 +218,7 @@ module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +module SB_DFFES (output `SB_DFF_REG, input C, E, S, D); always @(posedge C, posedge S) if (S) Q <= 1; @@ -228,18 +228,18 @@ endmodule // Negative Edge SiliconBlue FF Cells -module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, D); +module SB_DFFN (output `SB_DFF_REG, input C, D); always @(negedge C) Q <= D; endmodule -module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, D); +module SB_DFFNE (output `SB_DFF_REG, input C, E, D); always @(negedge C) if (E) Q <= D; endmodule -module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +module SB_DFFNSR (output `SB_DFF_REG, input C, R, D); always @(negedge C) if (R) Q <= 0; @@ -247,7 +247,7 @@ module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); +module SB_DFFNR (output `SB_DFF_REG, input C, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -255,7 +255,7 @@ module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, D); Q <= D; endmodule -module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +module SB_DFFNSS (output `SB_DFF_REG, input C, S, D); always @(negedge C) if (S) Q <= 1; @@ -263,7 +263,7 @@ module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); +module SB_DFFNS (output `SB_DFF_REG, input C, S, D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -271,7 +271,7 @@ module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, D); Q <= D; endmodule -module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D); always @(negedge C) if (E) begin if (R) @@ -281,7 +281,7 @@ module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); end endmodule -module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); +module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D); always @(negedge C, posedge R) if (R) Q <= 0; @@ -289,7 +289,7 @@ module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, D); Q <= D; endmodule -module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D); always @(negedge C) if (E) begin if (S) @@ -299,7 +299,7 @@ module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); end endmodule -module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, D); +module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D); always @(negedge C, posedge S) if (S) Q <= 1; @@ -310,7 +310,7 @@ endmodule // SiliconBlue RAM Cells module SB_RAM40_4K ( - (* abc_flop_q *) output [15:0] RDATA, + output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, input WCLK, WCLKE, WE, @@ -478,7 +478,7 @@ module SB_RAM40_4K ( endmodule module SB_RAM40_4KNR ( - (* abc_flop_q *) output [15:0] RDATA, + output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, input WCLK, WCLKE, WE, @@ -543,7 +543,7 @@ module SB_RAM40_4KNR ( endmodule module SB_RAM40_4KNW ( - (* abc_flop_q *) output [15:0] RDATA, + output [15:0] RDATA, input RCLK, RCLKE, RE, input [10:0] RADDR, input WCLKN, WCLKE, WE, @@ -608,7 +608,7 @@ module SB_RAM40_4KNW ( endmodule module SB_RAM40_4KNRNW ( - (* abc_flop_q *) output [15:0] RDATA, + output [15:0] RDATA, input RCLKN, RCLKE, RE, input [10:0] RADDR, input WCLKN, WCLKE, WE, @@ -902,7 +902,7 @@ module SB_SPRAM256KA ( input [15:0] DATAIN, input [3:0] MASKWREN, input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF, - (* abc_flop_q *) output reg [15:0] DATAOUT + output reg [15:0] DATAOUT ); `ifndef BLACKBOX `ifndef EQUIV diff --git a/techlibs/xilinx/brams_bb.v b/techlibs/xilinx/brams_bb.v index f540d299d..a682ba4a7 100644 --- a/techlibs/xilinx/brams_bb.v +++ b/techlibs/xilinx/brams_bb.v @@ -19,10 +19,10 @@ module RAMB18E1 ( input [1:0] WEA, input [3:0] WEBWE, - (* abc_flop_q *) output [15:0] DOADO, - (* abc_flop_q *) output [15:0] DOBDO, - (* abc_flop_q *) output [1:0] DOPADOP, - (* abc_flop_q *) output [1:0] DOPBDOP + output [15:0] DOADO, + output [15:0] DOBDO, + output [1:0] DOPADOP, + output [1:0] DOPBDOP ); parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; @@ -143,10 +143,10 @@ module RAMB36E1 ( input [3:0] WEA, input [7:0] WEBWE, - (* abc_flop_q *) output [31:0] DOADO, - (* abc_flop_q *) output [31:0] DOBDO, - (* abc_flop_q *) output [3:0] DOPADOP, - (* abc_flop_q *) output [3:0] DOPBDOP + output [31:0] DOADO, + output [31:0] DOBDO, + output [3:0] DOPADOP, + output [3:0] DOPBDOP ); parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index d9aa36666..bf7a0ed44 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -205,7 +205,7 @@ endmodule `endif -module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R); +module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -217,7 +217,7 @@ module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R); endcase endgenerate endmodule -module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S); +module FDSE (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -229,7 +229,7 @@ module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S); endcase endgenerate endmodule -module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); +module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -243,7 +243,7 @@ module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); endcase endgenerate endmodule -module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); +module FDPE (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; @@ -257,25 +257,25 @@ module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); endcase endgenerate endmodule -module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R); +module FDRE_1 (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; endmodule -module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S); +module FDSE_1 (output reg Q, input C, CE, D, S); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule -module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR); +module FDCE_1 (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE); +module FDPE_1 (output reg Q, input C, CE, D, PRE); parameter [0:0] INIT = 1'b1; initial Q <= INIT; always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; @@ -315,7 +315,7 @@ module RAM128X1D ( endmodule module SRL16E ( - (* abc_flop_q *) output Q, + output Q, input A0, A1, A2, A3, CE, CLK, D ); parameter [15:0] INIT = 16'h0000; @@ -333,7 +333,7 @@ module SRL16E ( endmodule module SRLC32E ( - (* abc_flop_q *) output Q, + output Q, output Q31, input [4:0] A, input CE, CLK, D From 94314ae2d5cbd06ba1457a8526f99c9ae01ff8fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:42:30 -0700 Subject: [PATCH 411/514] Comment out dist RAM boxing on ECP5 for now --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index d7184f980..f66147323 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -106,7 +106,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -(* abc_box_id=2 *) +//(* abc_box_id=2 *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From d47ff7ba8702f9ec76514cbbec1e447c454f5699 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:51:11 -0700 Subject: [PATCH 412/514] Rename +/xilinx/abc.{box,lut} -> abc_xc7.{box,lut} --- techlibs/xilinx/Makefile.inc | 4 ++-- techlibs/xilinx/{abc.box => abc_xc7.box} | 0 techlibs/xilinx/{abc.lut => abc_xc7.lut} | 0 techlibs/xilinx/synth_xilinx.cc | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename techlibs/xilinx/{abc.box => abc_xc7.box} (100%) rename techlibs/xilinx/{abc.lut => abc_xc7.lut} (100%) diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 296edace9..1a652eb27 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,8 +30,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc_xc7.box similarity index 100% rename from techlibs/xilinx/abc.box rename to techlibs/xilinx/abc_xc7.box diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc_xc7.lut similarity index 100% rename from techlibs/xilinx/abc.lut rename to techlibs/xilinx/abc_xc7.lut diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 69a3d99c2..2308ddadd 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,7 +279,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { if (abc == "abc9") - run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box -W 160" + string(retime ? " -dff" : "")); + run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W 160" + string(retime ? " -dff" : "")); else if (help_mode) run(abc + " -luts 2:2,3,6:5,10,20 [-dff]"); else From ba4b4a0088ff7ae37b86f0c22cf2a95f0aba9e13 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 11:33:10 -0700 Subject: [PATCH 413/514] Update delays based on SymbiFlow/prjxray-db --- techlibs/xilinx/abc_xc7.lut | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc_xc7.lut index 3a7dc268d..2e6906945 100644 --- a/techlibs/xilinx/abc_xc7.lut +++ b/techlibs/xilinx/abc_xc7.lut @@ -1,14 +1,15 @@ -# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf +# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json # K area delay -1 1 124 -2 2 124 235 -3 3 124 235 399 -4 3 124 235 399 490 -5 3 124 235 399 490 620 -6 5 124 235 399 490 620 632 - # F7BMUX -7 10 296 420 531 695 756 916 928 - # F8MUX - # F8MUX+F7BMUX -8 20 273 569 693 804 968 1029 1189 1201 +1 1 127 +2 2 127 238 +3 3 127 238 407 +4 3 127 238 407 472 +5 3 127 238 407 472 631 +6 5 127 238 407 472 631 642 + # F7AMUX + F7BMUX / 2 +7 10 286 413 524 693 758 917 928 + # F8MUX + # F8MUX+F7MUX +8 20 273 559 686 797 966 1031 1190 1201 From 2e34859a6b9780d6dc2df28dabcab893b5f4ce4a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 11:38:22 -0700 Subject: [PATCH 414/514] Add XC7_WIRE_DELAY macro to synth_xilinx.cc --- techlibs/xilinx/synth_xilinx.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2308ddadd..a11648873 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,6 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +#define XC7_WIRE_DELAY "160" + struct SynthXilinxPass : public ScriptPass { SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { } @@ -279,7 +281,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { if (abc == "abc9") - run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W 160" + string(retime ? " -dff" : "")); + run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + XC7_WIRE_DELAY + string(retime ? " -dff" : "")); else if (help_mode) run(abc + " -luts 2:2,3,6:5,10,20 [-dff]"); else From 97d265637505a239e3d328a3ee7e26c6fd5d6744 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:00:02 -0700 Subject: [PATCH 415/514] Resolve comments from @daveshah1 --- backends/aiger/xaiger.cc | 22 ++++++++-------------- frontends/aiger/aigerparse.cc | 4 ++-- techlibs/ice40/synth_ice40.cc | 2 +- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1e70f3230..42a2233e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -683,16 +683,18 @@ struct XAigerWriter f << "c"; if (!box_list.empty() || !ff_bits.empty()) { - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { + auto write_buffer = [](std::stringstream &buffer, int i32) { // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int32_t i32_be = _byteswap_ulong(i32); #else - int i32_be = __builtin_bswap32(i32); + int32_t i32_be = __builtin_bswap32(i32); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); @@ -782,15 +784,7 @@ struct XAigerWriter /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a72a82926..4ce76daa5 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -26,7 +26,7 @@ #include #include #endif -#include +#include #include "kernel/yosys.h" #include "kernel/sigtools.h" @@ -277,7 +277,7 @@ static uint32_t parse_xaiger_literal(std::istream &f) uint32_t l; f.read(reinterpret_cast(&l), sizeof(l)); if (f.gcount() != sizeof(l)) - log_error("Offset %ld: unable to read literal!\n", static_cast(f.tellg())); + log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast(f.tellg())); // TODO: Don't assume we're on little endian #ifdef _WIN32 return _byteswap_ulong(l); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index a60829764..d8e9786c5 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -332,7 +332,7 @@ struct SynthIce40Pass : public ScriptPass } if (!noabc) { if (abc == "abc9") - run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); + run(abc + stringf(" -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); else run(abc + " -dress -lut 4", "(skip if -noabc)"); } From a48b5bfaa5c55bfe4e5ff859b453ee00a1dd68c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:25:06 -0700 Subject: [PATCH 416/514] Further cleanup based on @daveshah1 --- backends/aiger/xaiger.cc | 48 +++++++++++++++-------------------- frontends/aiger/aigerparse.cc | 30 ++++++++++++++-------- kernel/rtlil.h | 6 +++++ passes/techmap/abc9.cc | 10 -------- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42a2233e4..7e22dca7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,20 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +inline int32_t to_big_endian(int32_t i32) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#ifdef _WIN32 + return _byteswap_ulong(i32); +#else + return __builtin_bswap32(i32); +#endif +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return i32; +#else +#error "Unknown endianness" +#endif +} + void aiger_encode(std::ostream &f, int x) { log_assert(x >= 0); @@ -684,12 +698,7 @@ struct XAigerWriter if (!box_list.empty() || !ff_bits.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int32_t i32_be = _byteswap_ulong(i32); -#else - int32_t i32_be = __builtin_bswap32(i32); -#endif + int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; @@ -773,12 +782,7 @@ struct XAigerWriter f << "h"; std::string buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); @@ -787,18 +791,13 @@ struct XAigerWriter auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); + //int mergeability_class = 1; + //for (auto cell : ff_bits) + // write_r_buffer(mergeability_class++); f << "r"; std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); } @@ -831,12 +830,7 @@ struct XAigerWriter f << "a"; std::string buffer_str = a_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4ce76daa5..7d156fe03 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -35,6 +35,20 @@ YOSYS_NAMESPACE_BEGIN +inline int32_t from_big_endian(int32_t i32) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#ifdef _WIN32 + return _byteswap_ulong(i32); +#else + return __builtin_bswap32(i32); +#endif +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return i32; +#else +#error "Unknown endianness" +#endif +} + struct ConstEvalAig { RTLIL::Module *module; @@ -278,19 +292,14 @@ static uint32_t parse_xaiger_literal(std::istream &f) f.read(reinterpret_cast(&l), sizeof(l)); if (f.gcount() != sizeof(l)) log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast(f.tellg())); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - return _byteswap_ulong(l); -#else - return __builtin_bswap32(l); -#endif + return from_big_endian(l); } static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) { const unsigned variable = literal >> 1; const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? + RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; log_debug("Creating %s\n", wire_name.c_str()); @@ -309,7 +318,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); // FIXME: is "$not" the right suffix? + module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); return wire; } @@ -355,7 +364,8 @@ void AigerReader::parse_xaiger() auto it = m->attributes.find("\\abc_box_id"); if (it == m->attributes.end()) continue; - if (m->name[0] == '$') continue; + if (m->name.begins_with("$paramod")) + continue; auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name)); log_assert(r.second); } @@ -495,7 +505,7 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1 >> l2)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); - log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? + log_assert(!(l1 & 1)); RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d3ad57d72..f4fcf5dcf 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -276,6 +276,12 @@ namespace RTLIL return std::string(c_str() + pos, len); } + bool begins_with(const char* prefix) const { + size_t len = strlen(prefix); + if (size() < len) return false; + return substr(0, len) == prefix; + } + bool ends_with(const char* suffix) const { size_t len = strlen(suffix); if (size() < len) return false; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 99083c20a..04e7d5d13 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -61,17 +61,12 @@ extern "C" int Abc_RealMain(int argc, char *argv[]); USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool map_mux4; -bool map_mux8; -bool map_mux16; - bool markgroups; int map_autoidx; SigMap assign_map; RTLIL::Module *module; std::map signal_map; std::map signal_init; -pool enabled_gates; bool recover_init; bool clk_polarity, en_polarity; @@ -848,11 +843,6 @@ struct Abc9Pass : public Pass { show_tempdir = true; #endif - map_mux4 = false; - map_mux8 = false; - map_mux16 = false; - enabled_gates.clear(); - #ifdef _WIN32 #ifndef ABCEXTERNAL if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) From e391fc8e7b469bb173d6bfd74d6b2bbc68973336 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:28:01 -0700 Subject: [PATCH 417/514] Enable "abc9 -D " for timing-driven synthesis --- passes/techmap/abc9.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 04e7d5d13..fa8b16789 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -29,7 +29,7 @@ "&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\ "&st; &if -g -K 6; &synch2; &if {W}; &save; &load" #else -#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} -v; "/*"&mfs; "*/"&ps -l" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l" #endif @@ -335,9 +335,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } else log_abort(); - if (script_file.empty() && !delay_target.empty()) - for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + //if (script_file.empty() && !delay_target.empty()) + // for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) + // abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); @@ -750,12 +750,12 @@ struct Abc9Pass : public Pass { log(" for -lut/-luts:\n"); log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str()); log("\n"); -// log(" -D \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(" this also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); + log(" -D \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(" This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n"); // log(" default scripts above.\n"); -// log("\n"); + log("\n"); // log(" -S \n"); // log(" maximum number of LUT inputs shared.\n"); // log(" (replaces {S} in the default scripts above, default: -S 1)\n"); From a632799d5b3e4d458f256203678e546474425556 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:29:46 -0700 Subject: [PATCH 418/514] Update abc9 -D doc --- passes/techmap/abc9.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fa8b16789..fe199f886 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -752,7 +752,8 @@ struct Abc9Pass : public Pass { log("\n"); log(" -D \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(" 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"); From 7876b5b8bef1ff8460e48232e68bb5136f04e7b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:40:51 -0700 Subject: [PATCH 419/514] Cover __APPLE__ too for little to big endian --- backends/aiger/xaiger.cc | 13 +++++++++---- frontends/aiger/aigerparse.cc | 11 +++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e22dca7f..7cb311736 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -18,6 +18,15 @@ * */ +// https://stackoverflow.com/a/46137633 +#ifdef _MSC_VER +#include +#define __builtin_bswap32 _byteswap_ulong +#elif defined(__APPLE__) +#include +#define __builtin_bswap32 OSSwapInt32 +#endif + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/utils.h" @@ -27,11 +36,7 @@ PRIVATE_NAMESPACE_BEGIN inline int32_t to_big_endian(int32_t i32) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#ifdef _WIN32 - return _byteswap_ulong(i32); -#else return __builtin_bswap32(i32); -#endif #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return i32; #else diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7d156fe03..d378a07b7 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -24,7 +24,14 @@ #ifdef _WIN32 #include +#endif +// https://stackoverflow.com/a/46137633 +#ifdef _MSC_VER #include +#define __builtin_bswap32 _byteswap_ulong +#elif defined(__APPLE__) +#include +#define __builtin_bswap32 OSSwapInt32 #endif #include @@ -37,11 +44,7 @@ YOSYS_NAMESPACE_BEGIN inline int32_t from_big_endian(int32_t i32) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#ifdef _WIN32 - return _byteswap_ulong(i32); -#else return __builtin_bswap32(i32); -#endif #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return i32; #else From 8fa74287a71fc3527cf48c7fb2c4a635ee832b72 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:43:20 -0700 Subject: [PATCH 420/514] As per @daveshah1 remove async DFF timing from xilinx --- techlibs/xilinx/abc_xc7.box | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index a4182ed63..8a48bad4e 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -54,9 +54,9 @@ FDSE 7 0 4 1 # Inputs: C CE CLR D # Outputs: Q FDCE 8 0 4 1 -- - 404 - +- - - - # Inputs: C CE D PRE # Outputs: Q FDPE 9 0 4 1 -- - - 404 +- - - - From 2d85725604271c658382e8fdd8ff28275fb94b03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:07:56 -0700 Subject: [PATCH 421/514] Get rid of compiler warnings --- backends/aiger/xaiger.cc | 4 ++-- passes/techmap/abc9.cc | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cb311736..3f7edc627 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -190,7 +190,7 @@ struct XAigerWriter bool abc_box_seen = false; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -312,7 +312,7 @@ struct XAigerWriter TopoSort toposort; dict> bit_drivers, bit_users; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) continue; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fe199f886..f7f2e862a 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -243,8 +243,8 @@ struct abc_output_filter void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, - bool keepff, std::string delay_target, std::string lutin_shared, bool fast_mode, - const std::vector &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file, + bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, + bool show_tempdir, std::string box_file, std::string lut_file, std::string wire_delay) { module = current_module; @@ -835,7 +835,7 @@ struct Abc9Pass : public Pass { std::string script_file, clk_str, box_file, lut_file; std::string delay_target, lutin_shared = "-S 1", wire_delay; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; - bool show_tempdir = false, sop_mode = false; + bool show_tempdir = false; vector lut_costs; markgroups = false; @@ -997,7 +997,7 @@ struct Abc9Pass : public Pass { if (!dff_mode || !clk_str.empty()) { abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, - delay_target, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, + delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay); continue; } @@ -1143,7 +1143,7 @@ struct Abc9Pass : public Pass { en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", - keepff, delay_target, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, + keepff, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, wire_delay); assign_map.set(mod); } From 0fa6a441f1a222b039975cf622ddca479a65cf24 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:08:38 -0700 Subject: [PATCH 422/514] Check that whiteboxes are synthesisable --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3f7edc627..bc722e492 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -722,7 +722,7 @@ struct XAigerWriter write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; - holes_module = module->design->addModule("\\__holes__"); + holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); int port_id = 1; @@ -822,17 +822,21 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap all lib_whitebox-es once + // TODO: Should techmap/AIG all lib_whitebox-es once Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - holes_module->design->selection_stack.pop_back(); + Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); + holes_module->design->selection_stack.pop_back(); + f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); From 746f70a9ce163f921b0e55b21042c59769bbcba9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:10:46 -0700 Subject: [PATCH 423/514] Update comment --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bc722e492..0c2ae62e6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -822,7 +822,8 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/AIG all lib_whitebox-es once + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) From 9b55e69755a00a46c97104f344c0ee7065a8f13c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: [PATCH 424/514] Revert "Cleanup/optimise toposort in write_xaiger" This reverts commit 1948e7c846ea318d003148974945d917701a4452. Restores old toposort with optimisations --- backends/aiger/xaiger.cc | 84 +++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0c2ae62e6..1d502a748 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,9 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - SigMap topomap; - topomap.database = sigmap.database; - + dict> bit_drivers, bit_users; + TopoSort toposort; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -198,8 +197,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) - topomap.add(Y, A); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -223,12 +225,16 @@ struct XAigerWriter undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); if (!holes_mode) { - topomap.add(Y, A); - topomap.add(Y, B); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); } continue; } + log_assert(!holes_mode); + //if (cell->type == "$initstate") //{ // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); @@ -265,11 +271,26 @@ struct XAigerWriter // } // if (!abc_box_seen) // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); //} /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; + + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } } else { for (const auto &c : cell->connections()) { @@ -309,45 +330,19 @@ struct XAigerWriter } if (abc_box_seen && !holes_mode) { - TopoSort toposort; - dict> bit_drivers, bit_users; - - for (auto cell : module->selected_cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) - continue; - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : topomap(conn.second)) - if (bit.wire) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - //if (inst_module_port->attributes.count("\\abc_flop_q")) - // continue; - for (auto bit : topomap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); -#if 1 + pool abc_carry_modules; + +#if 0 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 1 +#if 0 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -358,14 +353,13 @@ struct XAigerWriter #endif log_assert(no_loops); - pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - log_assert(box_module); - log_assert(box_module->attributes.count("\\abc_box_id")); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; - if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -461,6 +455,8 @@ struct XAigerWriter } box_list.emplace_back(cell); } + + // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { From 46e69ee934a6a954b73bb7a5669b6ee6d3047247 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:31:18 -0700 Subject: [PATCH 425/514] Remove redundant condition --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1d502a748..4d8bb7f00 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -329,7 +329,7 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen && !holes_mode) { + if (abc_box_seen) { for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) From 7ff8330d1e159173f9ed3494b85b83cb97208ab5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:34:40 -0700 Subject: [PATCH 426/514] Leave breadcrumb behind --- backends/aiger/xaiger.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d8bb7f00..df970e341 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,6 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + // TODO: Speed up toposort -- ultimately we care about + // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; bool abc_box_seen = false; From bf312043d47c5ca99e26e25d153b49b3d3603ea4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 05:45:16 -0700 Subject: [PATCH 427/514] Fix upper XC7 LUT[78] delays to use I[01] -> O delay not S -> O --- techlibs/xilinx/abc_xc7.lut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc_xc7.lut index 2e6906945..ceb27c659 100644 --- a/techlibs/xilinx/abc_xc7.lut +++ b/techlibs/xilinx/abc_xc7.lut @@ -9,7 +9,7 @@ 5 3 127 238 407 472 631 6 5 127 238 407 472 631 642 # F7AMUX + F7BMUX / 2 -7 10 286 413 524 693 758 917 928 +7 10 286 335 446 615 680 839 850 # F8MUX # F8MUX+F7MUX -8 20 273 559 686 797 966 1031 1190 1201 +8 20 273 390 439 550 719 784 943 954 From fb90d8c18c9e8bfad1356e3b4387d77eeb2e9377 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 09:34:26 -0700 Subject: [PATCH 428/514] Cleanup --- backends/aiger/xaiger.cc | 251 ++++------------------------------ frontends/aiger/aigerparse.cc | 21 +-- passes/techmap/abc9.cc | 58 +------- 3 files changed, 32 insertions(+), 298 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index df970e341..1485e2b0c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -59,31 +59,23 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; - bool zinit_mode; SigMap sigmap; - dict init_map; pool input_bits, output_bits; - dict not_map, ff_map, alias_map; + dict not_map, alias_map; dict> and_map; - //pool initstate_bits; vector> ci_bits; vector> co_bits; - vector> ff_bits; vector> aig_gates; - vector aig_latchin, aig_latchinit, aig_outputs; + vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; dict ordered_outputs; - dict ordered_latches; vector box_list; - //dict init_inputs; - //int initstate_ff = 0; - int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -97,10 +89,6 @@ struct XAigerWriter { aig_map[bit] = -1; - //if (initstate_bits.count(bit)) { - // log_assert(initstate_ff > 0); - // aig_map[bit] = initstate_ff; - //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -123,7 +111,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -145,14 +133,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) - if (initval[i] == State::S0 || initval[i] == State::S1) - init_map[initsig[i]] = initval[i] == State::S1; - } - bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -207,16 +187,6 @@ struct XAigerWriter continue; } - //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - //{ - // SigBit D = sigmap(cell->getPort("\\D").as_bit()); - // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - // unused_bits.erase(D); - // undriven_bits.erase(Q); - // ff_map[Q] = D; - // continue; - //} - if (cell->type == "$_AND_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -237,45 +207,8 @@ struct XAigerWriter log_assert(!holes_mode); - //if (cell->type == "$initstate") - //{ - // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - // undriven_bits.erase(Y); - // initstate_bits.insert(Y); - // continue; - //} - RTLIL::Module* inst_module = module->design->module(cell->type); - //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - //if (inst_flop) { - // SigBit d, q; - // for (const auto &c : cell->connections()) { - // auto is_input = cell->input(c.first); - // auto is_output = cell->output(c.first); - // log_assert(is_input || is_output); - // RTLIL::Wire* port = inst_module->wire(c.first); - // for (auto b : c.second.bits()) { - // if (is_input && port->attributes.count("\\abc_flop_d")) { - // d = b; - // SigBit I = sigmap(d); - // if (I != d) - // alias_map[I] = d; - // unused_bits.erase(d); - // } - // if (is_output && port->attributes.count("\\abc_flop_q")) { - // q = b; - // SigBit O = sigmap(q); - // if (O != q) - // alias_map[O] = q; - // undriven_bits.erase(O); - // } - // } - // } - // if (!abc_box_seen) - // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); - //} - /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -501,7 +434,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -517,7 +449,6 @@ struct XAigerWriter } not_map.sort(); - ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -529,78 +460,12 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - RTLIL::SigBit bit = f.second; - aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; + aig_map[bit] = 2*aig_m; } - //if (zinit_mode) - //{ - // for (auto it : ff_map) { - // if (init_map.count(it.first)) - // continue; - // aig_m++, aig_i++; - // init_inputs[it.first] = 2*aig_m; - // } - //} - - for (auto it : ff_map) { - aig_m++, aig_l++; - aig_map[it.first] = 2*aig_m; - ordered_latches[it.first] = aig_l-1; - if (init_map.count(it.first) == 0) - aig_latchinit.push_back(2); - else - aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - } - - //if (!initstate_bits.empty() || !init_inputs.empty()) { - // aig_m++, aig_l++; - // initstate_ff = 2*aig_m+1; - // aig_latchinit.push_back(0); - //} - - //if (zinit_mode) - //{ - // for (auto it : ff_map) - // { - // int l = ordered_latches[it.first]; - - // if (aig_latchinit.at(l) == 1) - // aig_map[it.first] ^= 1; - - // if (aig_latchinit.at(l) == 2) - // { - // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - // } - // } - //} - - for (auto it : ff_map) { - int a = bit2aig(it.second); - int l = ordered_latches[it.first]; - if (zinit_mode && aig_latchinit.at(l) == 1) - aig_latchin.push_back(a ^ 1); - else - aig_latchin.push_back(a); - } - - //if (!initstate_bits.empty() || !init_inputs.empty()) - // aig_latchin.push_back(1); - for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -611,13 +476,6 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - - for (auto &f : ff_bits) { - aig_o++; - RTLIL::SigBit bit = f.second; - aig_outputs.push_back(ff_aig_map.at(bit)); - } - } void write_aiger(std::ostream &f, bool ascii_mode) @@ -627,8 +485,6 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); - log_assert(aig_l == GetSize(aig_latchin)); - log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -639,15 +495,6 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -665,15 +512,6 @@ struct XAigerWriter } else { - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d 1\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -699,7 +537,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -708,14 +546,14 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); - write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); + write_h_buffer(input_bits.size()); + log_debug("poNum = %zu\n", output_bits.size()); + write_h_buffer(output_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -789,21 +627,15 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - /*if (!ff_bits.empty())*/ { - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %zu\n", ff_bits.size()); - write_r_buffer(ff_bits.size()); - //int mergeability_class = 1; - //for (auto cell : ff_bits) - // write_r_buffer(mergeability_class++); + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + write_r_buffer(0); - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } + f << "r"; + buffer_str = r_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { // NB: fixup_ports() will sort ports by name @@ -831,7 +663,7 @@ struct XAigerWriter Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); holes_module->design->selection_stack.pop_back(); @@ -851,9 +683,7 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; - dict init_lines; dict output_lines; - dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -878,22 +708,6 @@ struct XAigerWriter continue; } - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - // continue; - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - else - latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - continue; - } - if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; @@ -909,10 +723,6 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); - init_lines.sort(); - for (auto &it : init_lines) - f << it.second; - int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); @@ -922,10 +732,6 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size()); - latch_lines.sort(); - for (auto &it : latch_lines) - f << it.second; - wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -946,10 +752,6 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); - log(" -zinit\n"); - log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); - log(" uninitialized FFs.\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -960,7 +762,6 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -973,10 +774,6 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } - if (args[argidx] == "-zinit") { - zinit_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -995,7 +792,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d378a07b7..3b53b0086 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -726,7 +726,7 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { pool abc_carry_modules; - unsigned ci_count = 0, co_count = 0, flop_count = 0; + unsigned ci_count = 0, co_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); @@ -766,9 +766,6 @@ void AigerReader::post_process() } } - bool flop = box_module->attributes.count("\\abc_flop"); - log_assert(!flop || flop_count < flopNum); - // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { @@ -783,13 +780,6 @@ void AigerReader::post_process() log_assert(wire); log_assert(wire->port_output); wire->port_output = false; - - if (flop && w->attributes.count("\\abc_flop_d")) { - RTLIL::Wire* d = outputs[outputs.size() - flopNum + flop_count]; - log_assert(d); - log_assert(d->port_output); - d->port_output = false; - } } if (w->port_output) { log_assert((piNum + ci_count) < inputs.size()); @@ -797,20 +787,11 @@ void AigerReader::post_process() log_assert(wire); log_assert(wire->port_input); wire->port_input = false; - - if (flop && w->attributes.count("\\abc_flop_q")) { - wire = inputs[piNum - flopNum + flop_count]; - log_assert(wire); - log_assert(wire->port_input); - wire->port_input = false; - } } rhs.append(wire); } cell->setPort(port_name, rhs); } - - if (flop) flop_count++; } dict wideports_cache; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f7f2e862a..0e4053e55 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -65,13 +65,9 @@ bool markgroups; int map_autoidx; SigMap assign_map; RTLIL::Module *module; -std::map signal_map; -std::map signal_init; -bool recover_init; bool clk_polarity, en_polarity; RTLIL::SigSpec clk_sig, en_sig; -dict pi_map, po_map; std::string remap_name(RTLIL::IdString abc_name) { @@ -228,13 +224,13 @@ struct abc_output_filter void next_line(const std::string &line) { - int pi, po; - if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { - log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", - pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", - po, po_map.count(po) ? po_map.at(po).c_str() : "???"); - return; - } + //int pi, po; + //if (sscanf(line.c_str(), "Start-point = pi%d. End-point = po%d.", &pi, &po) == 2) { + // log("ABC: Start-point = pi%d (%s). End-point = po%d (%s).\n", + // pi, pi_map.count(pi) ? pi_map.at(pi).c_str() : "???", + // po, po_map.count(po) ? po_map.at(po).c_str() : "???"); + // return; + //} for (char ch : line) next_char(ch); @@ -250,11 +246,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module = current_module; map_autoidx = autoidx++; - signal_map.clear(); - pi_map.clear(); - po_map.clear(); - recover_init = false; - if (clk_str != "$") { clk_polarity = true; @@ -648,15 +639,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->connect(conn); } - if (recover_init) - for (auto wire : mapped_mod->wires()) { - if (wire->attributes.count("\\init")) { - Wire *w = module->wires_[remap_name(wire->name)]; - log_assert(w->attributes.count("\\init") == 0); - w->attributes["\\init"] = wire->attributes.at("\\init"); - } - } - for (auto &it : cell_stats) log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); int in_wires = 0, out_wires = 0; @@ -822,10 +804,6 @@ struct Abc9Pass : public Pass { log_push(); assign_map.clear(); - signal_map.clear(); - signal_init.clear(); - pi_map.clear(); - po_map.clear(); #ifdef ABCEXTERNAL std::string exe_file = ABCEXTERNAL; @@ -976,24 +954,6 @@ struct Abc9Pass : public Pass { } assign_map.set(mod); - signal_init.clear(); - - for (Wire *wire : mod->wires()) - if (wire->attributes.count("\\init")) { - SigSpec initsig = assign_map(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - switch (initval[i]) { - case State::S0: - signal_init[initsig[i]] = State::S0; - break; - case State::S1: - signal_init[initsig[i]] = State::S0; - break; - default: - break; - } - } if (!dff_mode || !clk_str.empty()) { abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, @@ -1152,10 +1112,6 @@ struct Abc9Pass : public Pass { Pass::call(design, "clean"); assign_map.clear(); - signal_map.clear(); - signal_init.clear(); - pi_map.clear(); - po_map.clear(); log_pop(); } From 7250c57c5a05139ca03544a31fe40b52e4e73486 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 10:28:51 -0700 Subject: [PATCH 429/514] Re-enable &dc2 --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0e4053e55..54aba3b18 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -29,7 +29,7 @@ "&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\ "&st; &if -g -K 6; &synch2; &if {W}; &save; &load" #else -#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l" +#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &st; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l" #endif From c15ee827f4a171abe3108dba8f9ad0d7078eb306 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 12:08:03 -0700 Subject: [PATCH 430/514] Try -W 300 --- techlibs/xilinx/synth_xilinx.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a11648873..45bc47f24 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,7 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define XC7_WIRE_DELAY "160" +#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) struct SynthXilinxPass : public ScriptPass { From b45d06d7a334c4b18e44793b33aaffcaf1f04b21 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 12:54:24 -0700 Subject: [PATCH 431/514] Fix leak removing cells during ABC integration; also preserve attr --- kernel/rtlil.cc | 12 ++++++++-- kernel/rtlil.h | 1 + passes/techmap/abc9.cc | 51 +++++++++++++++++++++--------------------- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 790ba52a3..f732b56b0 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1565,13 +1565,21 @@ void RTLIL::Module::remove(const pool &wires) void RTLIL::Module::remove(RTLIL::Cell *cell) { + auto it = cells_.find(cell->name); + log_assert(it != cells_.end()); + remove(it); +} + +dict::iterator RTLIL::Module::remove(dict::iterator it) +{ + RTLIL::Cell *cell = it->second; while (!cell->connections_.empty()) cell->unsetPort(cell->connections_.begin()->first); - log_assert(cells_.count(cell->name) != 0); log_assert(refcount_cells_ == 0); - cells_.erase(cell->name); + it = cells_.erase(it); delete cell; + return it; } void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f4fcf5dcf..4a0f8b4f8 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1040,6 +1040,7 @@ public: // Removing wires is expensive. If you have to remove wires, remove them all at once. void remove(const pool &wires); void remove(RTLIL::Cell *cell); + dict::iterator remove(dict::iterator it); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 54aba3b18..9c4e6bb39 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -500,24 +500,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - // Remove all AND, NOT, and ABC box instances - // in preparation for stitching mapped_mod in - dict erased_boxes; - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; - if (cell->type.in("$_AND_", "$_NOT_")) { - it = module->cells_.erase(it); - continue; - } - RTLIL::Module* box_module = design->module(cell->type); - if (box_module && box_module->attributes.count("\\abc_box_id")) { - erased_boxes.insert(std::make_pair(it->first, std::move(cell->parameters))); - it = module->cells_.erase(it); - continue; - } - ++it; - } - // Do the same for module connections for (auto &it : module->connections_) { auto &signal = it.first; auto bits = signal.bits(); @@ -527,6 +509,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri signal = std::move(bits); } + vector boxes; + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { + RTLIL::Cell* cell = it->second; + if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { + it = module->remove(it); + continue; + } + RTLIL::Module* box_module = design->module(cell->type); + if (box_module && box_module->attributes.count("\\abc_box_id")) + boxes.emplace_back(it->second); + ++it; + } + std::map cell_stats; for (auto c : mapped_mod->cells()) { @@ -595,18 +590,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; module->connect(my_y, my_a); + if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; continue; } } - else { - 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); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - cell->parameters = c->parameters; + RTLIL::Cell *existing_cell = module->cell(c->name); + if (existing_cell) { + cell->parameters = std::move(existing_cell->parameters); + cell->attributes = std::move(existing_cell->attributes); + } + else { + cell->parameters = std::move(c->parameters); + } for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { @@ -621,6 +619,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + for (auto cell : boxes) + module->remove(cell); + // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) { From 63fc879a5f698803d563a57275cc99a3df2d1414 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 13:19:45 -0700 Subject: [PATCH 432/514] Copy not move parameters/attributes --- passes/techmap/abc9.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 9c4e6bb39..184fbfaee 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -599,11 +599,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; RTLIL::Cell *existing_cell = module->cell(c->name); if (existing_cell) { - cell->parameters = std::move(existing_cell->parameters); - cell->attributes = std::move(existing_cell->attributes); + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; } else { - cell->parameters = std::move(c->parameters); + cell->parameters = c->parameters; + cell->attributes = c->attributes; } for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; From 4d6d593fe390a5a1dc650062306e05610908c13d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 13:32:08 -0700 Subject: [PATCH 433/514] &scorr before &sweep, remove &retime as recommended --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 184fbfaee..2f670dba2 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -29,7 +29,7 @@ "&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\ "&st; &if -g -K 6; &synch2; &if {W}; &save; &load" #else -#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &st; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l" #endif From 840562943fa9d01455833561aa11bc287c8755d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 17:06:01 -0700 Subject: [PATCH 434/514] Update LUT7/8 delays to take account for [ABC]OUTMUX delay --- techlibs/xilinx/abc_xc7.lut | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc_xc7.lut index ceb27c659..f69a923d0 100644 --- a/techlibs/xilinx/abc_xc7.lut +++ b/techlibs/xilinx/abc_xc7.lut @@ -8,8 +8,8 @@ 4 3 127 238 407 472 5 3 127 238 407 472 631 6 5 127 238 407 472 631 642 - # F7AMUX + F7BMUX / 2 -7 10 286 335 446 615 680 839 850 - # F8MUX - # F8MUX+F7MUX -8 20 273 390 439 550 719 784 943 954 + # F7AMUX.S+F7BMUX.S + AOUTMUX+COUTMUX / 2 +7 10 464 513 624 793 858 1017 1028 + # F8MUX.S+BOUTMUX + # F8MUX.I0+F7MUX.S+BOUTMUX +8 20 468 585 634 745 914 979 1138 1149 From 75f8b4cf10e45e9064ddac10ff0b088b863fd361 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 19:14:41 -0700 Subject: [PATCH 435/514] Simplify comment --- techlibs/xilinx/abc_xc7.lut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc_xc7.lut index f69a923d0..bcbdec127 100644 --- a/techlibs/xilinx/abc_xc7.lut +++ b/techlibs/xilinx/abc_xc7.lut @@ -8,7 +8,7 @@ 4 3 127 238 407 472 5 3 127 238 407 472 631 6 5 127 238 407 472 631 642 - # F7AMUX.S+F7BMUX.S + AOUTMUX+COUTMUX / 2 + # (F7[AB]MUX.S + [AC]OUTMUX) / 2 7 10 464 513 624 793 858 1017 1028 # F8MUX.S+BOUTMUX # F8MUX.I0+F7MUX.S+BOUTMUX From 2a35c4ef945a0ecf4006e9b9a1199a6baca1d2ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 22:24:35 -0700 Subject: [PATCH 436/514] Permute INIT for +/xilinx/lut_map.v --- techlibs/xilinx/lut_map.v | 90 +++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index d07c59dee..fa2a005b1 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -29,58 +29,84 @@ module \$lut (A, Y); input [WIDTH-1:0] A; output Y; + // Need to swap input ordering, and fix init accordingly, + // to match ABC's expectation of LUT inputs in non-decreasing + // delay order + localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH; + function [P_WIDTH-1:0] permute_index; + input [P_WIDTH-1:0] i; + integer j; + begin + permute_index = 0; + for (j = 0; j < P_WIDTH; j = j + 1) + permute_index[P_WIDTH-1 - j] = i[j]; + end + endfunction + + function [2**P_WIDTH-1:0] permute_init; + input [2**P_WIDTH-1:0] orig; + integer i; + begin + permute_init = 0; + for (i = 0; i < 2**P_WIDTH; i = i + 1) + permute_init[i] = orig[permute_index(i)]; + end + endfunction + + parameter [2**P_WIDTH-1:0] P_LUT = permute_init(LUT); + generate if (WIDTH == 1) begin - LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0])); end else if (WIDTH == 2) begin - LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1])); + LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[1]), .I1(A[0])); end else if (WIDTH == 3) begin - LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2])); + LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[2]), .I1(A[1]), .I2(A[0])); end else if (WIDTH == 4) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3])); + LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[3]), .I1(A[2]), .I2(A[1]), + .I3(A[0])); end else if (WIDTH == 5) begin - LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4])); + LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[4]), .I1(A[3]), .I2(A[2]), + .I3(A[1]), .I4(A[0])); end else if (WIDTH == 6) begin - LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); end else if (WIDTH == 7) begin wire T0, T1; - LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); end else if (WIDTH == 8) begin wire T0, T1, T2, T3, T4, T5; - LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); From 608a95eb01ec5c54d09102917e224ff5e0c39d47 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 22:29:22 -0700 Subject: [PATCH 437/514] Fix copy-pasta issue --- techlibs/xilinx/lut_map.v | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index fa2a005b1..2f246e46d 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -32,28 +32,27 @@ module \$lut (A, Y); // Need to swap input ordering, and fix init accordingly, // to match ABC's expectation of LUT inputs in non-decreasing // delay order - localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH; - function [P_WIDTH-1:0] permute_index; - input [P_WIDTH-1:0] i; + function [WIDTH-1:0] permute_index; + input [WIDTH-1:0] i; integer j; begin permute_index = 0; - for (j = 0; j < P_WIDTH; j = j + 1) - permute_index[P_WIDTH-1 - j] = i[j]; + for (j = 0; j < WIDTH; j = j + 1) + permute_index[WIDTH-1 - j] = i[j]; end endfunction - function [2**P_WIDTH-1:0] permute_init; - input [2**P_WIDTH-1:0] orig; + function [2**WIDTH-1:0] permute_init; + input [2**WIDTH-1:0] orig; integer i; begin permute_init = 0; - for (i = 0; i < 2**P_WIDTH; i = i + 1) + for (i = 0; i < 2**WIDTH; i = i + 1) permute_init[i] = orig[permute_index(i)]; end endfunction - parameter [2**P_WIDTH-1:0] P_LUT = permute_init(LUT); + parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT); generate if (WIDTH == 1) begin From da3d2eedd2b6391621e81b3eaaa28a571e058f9d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 09:49:57 -0700 Subject: [PATCH 438/514] Fix (do not) permute LUT inputs, but permute mux selects --- techlibs/xilinx/lut_map.v | 64 ++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index 2f246e46d..62ce374df 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -29,30 +29,32 @@ module \$lut (A, Y); input [WIDTH-1:0] A; output Y; - // Need to swap input ordering, and fix init accordingly, + // Need to swap input ordering of wide LUTs, and fix init accordingly, // to match ABC's expectation of LUT inputs in non-decreasing // delay order function [WIDTH-1:0] permute_index; input [WIDTH-1:0] i; integer j; begin - permute_index = 0; - for (j = 0; j < WIDTH; j = j + 1) - permute_index[WIDTH-1 - j] = i[j]; + if (WIDTH == 7) + permute_index = { i[5:0], i[6] }; + else if (WIDTH == 8) + permute_index = { i[5:0], i[6], i[7] }; + else + permute_index = i; end endfunction function [2**WIDTH-1:0] permute_init; - input [2**WIDTH-1:0] orig; integer i; begin permute_init = 0; for (i = 0; i < 2**WIDTH; i = i + 1) - permute_init[i] = orig[permute_index(i)]; + permute_init[i] = LUT[permute_index(i)]; end endfunction - parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT); + parameter [2**WIDTH-1:0] P_LUT = permute_init(); generate if (WIDTH == 1) begin @@ -61,54 +63,54 @@ module \$lut (A, Y); end else if (WIDTH == 2) begin LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[1]), .I1(A[0])); + .I0(A[0]), .I1(A[1])); end else if (WIDTH == 3) begin LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[2]), .I1(A[1]), .I2(A[0])); + .I0(A[0]), .I1(A[1]), .I2(A[2])); end else if (WIDTH == 4) begin LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[3]), .I1(A[2]), .I2(A[1]), - .I3(A[0])); + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3])); end else if (WIDTH == 5) begin LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[4]), .I1(A[3]), .I2(A[2]), - .I3(A[1]), .I4(A[0])); + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4])); end else if (WIDTH == 6) begin LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); end else if (WIDTH == 7) begin wire T0, T1; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[1]), .I1(A[2]), .I2(A[3]), + .I3(A[4]), .I4(A[5]), .I5(A[6])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); - MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); + .I0(A[1]), .I1(A[2]), .I2(A[3]), + .I3(A[4]), .I4(A[5]), .I5(A[6])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); end else if (WIDTH == 8) begin wire T0, T1, T2, T3, T4, T5; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[2]), .I1(A[3]), .I2(A[4]), + .I3(A[5]), .I4(A[6]), .I5(A[7])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[2]), .I1(A[3]), .I2(A[4]), + .I3(A[5]), .I4(A[6]), .I5(A[7])); LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[2]), .I1(A[3]), .I2(A[4]), + .I3(A[5]), .I4(A[6]), .I5(A[7])); LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); - MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); - MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); - MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); + .I0(A[2]), .I1(A[3]), .I2(A[4]), + .I3(A[5]), .I4(A[6]), .I5(A[7])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; end From b304744d1506ae5a672639b6baab43c9bce97f00 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 09:50:37 -0700 Subject: [PATCH 439/514] Clean up --- techlibs/ecp5/cells_map.v | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 53a89e8a3..b504d51e2 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -70,6 +70,8 @@ module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; + input [WIDTH-1:0] A; + output Y; // Need to swap input ordering, and fix init accordingly, // to match ABC's expectation of LUT inputs in non-decreasing @@ -86,19 +88,15 @@ module \$lut (A, Y); endfunction function [2**P_WIDTH-1:0] permute_init; - input [2**P_WIDTH-1:0] orig; integer i; begin permute_init = 0; for (i = 0; i < 2**P_WIDTH; i = i + 1) - permute_init[i] = orig[permute_index(i)]; + permute_init[i] = LUT[permute_index(i)]; end endfunction - parameter [2**P_WIDTH-1:0] P_LUT = permute_init(LUT); - - input [WIDTH-1:0] A; - output Y; + parameter [2**P_WIDTH-1:0] P_LUT = permute_init(); generate if (WIDTH == 1) begin From 8f5e6d73ff3c81d96fbb53e0c67572830800c301 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 11:35:21 -0700 Subject: [PATCH 440/514] Revert "Fix (do not) permute LUT inputs, but permute mux selects" This reverts commit da3d2eedd2b6391621e81b3eaaa28a571e058f9d. --- techlibs/xilinx/lut_map.v | 64 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index 62ce374df..2f246e46d 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -29,32 +29,30 @@ module \$lut (A, Y); input [WIDTH-1:0] A; output Y; - // Need to swap input ordering of wide LUTs, and fix init accordingly, + // Need to swap input ordering, and fix init accordingly, // to match ABC's expectation of LUT inputs in non-decreasing // delay order function [WIDTH-1:0] permute_index; input [WIDTH-1:0] i; integer j; begin - if (WIDTH == 7) - permute_index = { i[5:0], i[6] }; - else if (WIDTH == 8) - permute_index = { i[5:0], i[6], i[7] }; - else - permute_index = i; + permute_index = 0; + for (j = 0; j < WIDTH; j = j + 1) + permute_index[WIDTH-1 - j] = i[j]; end endfunction function [2**WIDTH-1:0] permute_init; + input [2**WIDTH-1:0] orig; integer i; begin permute_init = 0; for (i = 0; i < 2**WIDTH; i = i + 1) - permute_init[i] = LUT[permute_index(i)]; + permute_init[i] = orig[permute_index(i)]; end endfunction - parameter [2**WIDTH-1:0] P_LUT = permute_init(); + parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT); generate if (WIDTH == 1) begin @@ -63,54 +61,54 @@ module \$lut (A, Y); end else if (WIDTH == 2) begin LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1])); + .I0(A[1]), .I1(A[0])); end else if (WIDTH == 3) begin LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2])); + .I0(A[2]), .I1(A[1]), .I2(A[0])); end else if (WIDTH == 4) begin LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3])); + .I0(A[3]), .I1(A[2]), .I2(A[1]), + .I3(A[0])); end else if (WIDTH == 5) begin LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4])); + .I0(A[4]), .I1(A[3]), .I2(A[2]), + .I3(A[1]), .I4(A[0])); end else if (WIDTH == 6) begin LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); end else if (WIDTH == 7) begin wire T0, T1; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[1]), .I1(A[2]), .I2(A[3]), - .I3(A[4]), .I4(A[5]), .I5(A[6])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[1]), .I1(A[2]), .I2(A[3]), - .I3(A[4]), .I4(A[5]), .I5(A[6])); - MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); end else if (WIDTH == 8) begin wire T0, T1, T2, T3, T4, T5; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[2]), .I1(A[3]), .I2(A[4]), - .I3(A[5]), .I4(A[6]), .I5(A[7])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[2]), .I1(A[3]), .I2(A[4]), - .I3(A[5]), .I4(A[6]), .I5(A[7])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), - .I0(A[2]), .I1(A[3]), .I2(A[4]), - .I3(A[5]), .I4(A[6]), .I5(A[7])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), - .I0(A[2]), .I1(A[3]), .I2(A[4]), - .I3(A[5]), .I4(A[6]), .I5(A[7])); - MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); - MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1])); - MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0])); + .I0(A[5]), .I1(A[4]), .I2(A[3]), + .I3(A[2]), .I4(A[1]), .I5(A[0])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); end else begin wire _TECHMAP_FAIL_ = 1; end From 8e0a47fb920af1126adb67f884b5ce1443a9b4a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 11:48:48 -0700 Subject: [PATCH 441/514] Really permute Xilinx LUT mappings as default LUT6.I5:A6 --- techlibs/xilinx/lut_map.v | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v index 2f246e46d..13d3c3268 100644 --- a/techlibs/xilinx/lut_map.v +++ b/techlibs/xilinx/lut_map.v @@ -85,30 +85,30 @@ module \$lut (A, Y); if (WIDTH == 7) begin wire T0, T1; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[6]), .I1(A[5]), .I2(A[4]), + .I3(A[3]), .I4(A[2]), .I5(A[1])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); - MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); + .I0(A[6]), .I1(A[5]), .I2(A[4]), + .I3(A[3]), .I4(A[2]), .I5(A[1])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); end else if (WIDTH == 8) begin wire T0, T1, T2, T3, T4, T5; LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), - .I0(A[5]), .I1(A[4]), .I2(A[3]), - .I3(A[2]), .I4(A[1]), .I5(A[0])); - MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); - MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); - MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); + .I0(A[7]), .I1(A[6]), .I2(A[5]), + .I3(A[4]), .I4(A[3]), .I5(A[2])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0])); end else begin wire _TECHMAP_FAIL_ = 1; end From f2d541962e92fedce0fbb34d4cf5c1985c7cda40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: [PATCH 442/514] write_xaiger to skip POs driven by 1'bx --- backends/aiger/xaiger.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1485e2b0c..12b23cfe9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,9 +152,13 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (bit != RTLIL::Sx) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + else + log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); } } } From 3f34779d64bbaee7210b567d4ad9ced456f0e159 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:22:14 -0700 Subject: [PATCH 443/514] Do not call "setundef -zero" in abc9 --- passes/techmap/abc9.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2f670dba2..fc9da1173 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -380,9 +380,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); - // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero - Pass::call(design, "setundef -zero"); - Pass::call(design, "aigmap"); handle_loops(design); @@ -406,7 +403,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri reader.parse_xaiger(); } ifs.close(); - Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v")); + Pass::call(design, stringf("write_verilog -noexpr -norename")); design->remove(design->module("$__abc9__")); #endif @@ -479,7 +476,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri ifs.close(); #if 0 - Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "output.v")); + Pass::call(design, stringf("write_verilog -noexpr -norename")); #endif log_header(design, "Re-integrating ABC9 results.\n"); From 4e5836a5fb009751a6f3bd7ec3eba20e223861f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:47:20 -0700 Subject: [PATCH 444/514] Handle COs driven by 1'bx --- backends/aiger/xaiger.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 12b23cfe9..42f54209b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -355,10 +355,16 @@ struct XAigerWriter } int offset = 0; - for (const auto &b : rhs.bits()) { + for (auto b : rhs.bits()) { SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (b == RTLIL::Sx) + b = RTLIL::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = RTLIL::S0; + else + alias_map[b] = I; + } co_bits.emplace_back(b, cell, port_name, offset++, 0); unused_bits.erase(b); } From f11c9a419b99563b462356add5446d9fc2dbe2eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:45:09 -0700 Subject: [PATCH 445/514] Call opt_expr -mux_undef to get rid of 1'bx in muxes prior to abc --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 45bc47f24..86b49b13c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -281,6 +281,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_luts")) { + run("opt_expr -mux_undef"); if (abc == "abc9") run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + XC7_WIRE_DELAY + string(retime ? " -dff" : "")); else if (help_mode) From 014606affe3f1753ac16d2afd684967d72d83746 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 17:29:45 -0700 Subject: [PATCH 446/514] Fix issue with part of PI being 1'bx --- frontends/aiger/aigerparse.cc | 10 ++++++---- tests/simple_abc9/abc9.v | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3b53b0086..ea3315267 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -947,11 +947,13 @@ void AigerReader::post_process() if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i)); - else - module->connect(SigSpec(wire, i), other_wire); } + if (wire->port_input && other_wire) + module->connect(other_wire, SigSpec(wire, i)); + else + // Since we skip POs that are connected to Sx, + // re-connect them here + module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); } } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 0b83c34a3..64b625efe 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -262,3 +262,8 @@ endmodule module abc9_test025(input [3:0] i, output [3:0] o); abc9_test024_sub a(i[2:1], o[2:1]); endmodule + +module abc9_test026(output [3:0] o, p); +assign o = { 1'b1, 1'bx }; +assign p = { 1'b1, 1'bx, 1'b0 }; +endmodule From eb09ea6d54738b82924e33c26f47fe35fbdd24cd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:06:51 -0700 Subject: [PATCH 447/514] Run simple_abc9 tests --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index fb0eaf14d..fd4e90c15 100644 --- a/Makefile +++ b/Makefile @@ -681,6 +681,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +cd tests/opt && bash run-test.sh +cd tests/aiger && bash run-test.sh + +cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" From 9faeba7a66c34d57bcae6ad83580e640ee5907e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:27:00 -0700 Subject: [PATCH 448/514] Fix broken abc9.v test due to inout being 1'bx --- backends/aiger/xaiger.cc | 13 +++++++++++-- frontends/aiger/aigerparse.cc | 13 ++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42f54209b..f0a9ccdb9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -75,6 +75,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + bool omode = false; int mkgate(int a0, int a1) { @@ -409,9 +410,9 @@ struct XAigerWriter // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(input_bits.count(bit) && output_bits.count(bit)); + log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) @@ -486,6 +487,12 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } + + if (output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + omode = true; + } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -741,6 +748,8 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + if (omode && output_bits.empty()) + f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ea3315267..a98ea8314 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -839,6 +839,10 @@ void AigerReader::post_process() RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); + if (escaped_s == "$__dummy__") { + wire->port_output = false; + continue; + } if (index == 0) { // Cope with the fact that a CO might be identical @@ -948,12 +952,15 @@ void AigerReader::post_process() other_wire->port_input = false; other_wire->port_output = false; } - if (wire->port_input && other_wire) - module->connect(other_wire, SigSpec(wire, i)); - else + if (wire->port_input) { + if (other_wire) + module->connect(other_wire, SigSpec(wire, i)); + } + else { // Since we skip POs that are connected to Sx, // re-connect them here module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); + } } } From ad36eb24c05b578ec8610c9f199280aacefebe54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:31:22 -0700 Subject: [PATCH 449/514] Fix different abc9 test --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f0a9ccdb9..55a95d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -406,13 +406,14 @@ struct XAigerWriter } for (auto bit : input_bits) { + if (!output_bits.count(bit)) + continue; RTLIL::Wire *wire = bit.wire; // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) From 0e97e6a00dfda0b4755599d4decdafb545e07aaa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:37:03 -0700 Subject: [PATCH 450/514] Fix simple_abc9/generate test with 1'bx at MSB --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fc9da1173..d48877779 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -492,7 +492,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (w->port_output) { RTLIL::Wire *wire = module->wire(w->name); log_assert(wire); - for (int i = 0; i < GetSize(wire); i++) + for (int i = 0; i < GetSize(w); i++) output_bits.insert({wire, i}); } } From 8e56cfb6bbaa4e61b201c123b04a4eb4ca3403cf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:40:17 -0700 Subject: [PATCH 451/514] write_xaiger to flatten 1'bx/1'bz to 1'b0 again --- backends/aiger/xaiger.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 55a95d835..82f0f24b2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,8 +104,10 @@ struct XAigerWriter aig_map[bit] = bit2aig(alias_map.at(bit)); } - if (bit == State::Sx || bit == State::Sz) - log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + aig_map[bit] = 0; + } } log_assert(aig_map.at(bit) >= 0); From 54f3237720709f7c59f4e440ebfdbc61a63c926a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:53:27 -0700 Subject: [PATCH 452/514] Fix gcc warning of potentially uninitialised --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d48877779..e9f35be91 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -523,7 +523,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto c : mapped_mod->cells()) { if (c->type == "$_NOT_") { - RTLIL::Cell *cell; + RTLIL::Cell *cell = nullptr; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); if (!a_bit.wire) { @@ -577,7 +577,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); cell_stats[RTLIL::unescape_id(c->type)]++; } - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; From 32f8014e121cd3338d6786269455c8b3fe9f1631 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:55:08 -0700 Subject: [PATCH 453/514] Fix gcc error, due to dict invalidation during recursion --- Makefile | 4 ++-- backends/aiger/xaiger.cc | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fd4e90c15..f363be208 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -CONFIG := clang -# CONFIG := gcc +# CONFIG := clang +CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 82f0f24b2..32c3f9045 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -101,12 +101,13 @@ struct XAigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) { log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = 0; + aig_map[bit] = aig_map.at(State::S0); } } From 4422b7311b8d672df386f993b413d32baad8550b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: [PATCH 454/514] Fix gcc invalidation behaviour for write_aiger --- backends/aiger/aiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 4c2ea511a..4fb47f0d6 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -89,7 +89,8 @@ struct AigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) From e21f01d9380607ba0fb10466273d2dfc3d806282 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:09:13 -0700 Subject: [PATCH 455/514] Refactor bit2aig for less lookups --- backends/aiger/xaiger.cc | 53 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32c3f9045..48e902666 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,33 +86,36 @@ struct XAigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } - - if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = aig_map.at(State::S0); - } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + a = aig_map.at(State::S0); + } + + log_assert(a >= 0); + aig_map[bit] = a; + return a; } XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) From cbbd96aae9d847279628191d73d5307f3d832097 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:28:55 -0700 Subject: [PATCH 456/514] Revert Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f363be208..fd4e90c15 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -# CONFIG := clang -CONFIG := gcc +CONFIG := clang +# CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc From 6a336ca23ef5d98b3d68dac2f05de49360237149 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:29:40 -0700 Subject: [PATCH 457/514] Fix spacing --- backends/aiger/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 4fb47f0d6..2815abda8 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -89,7 +89,7 @@ struct AigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); aig_map[bit] = a; } From 70c93ea0c4ce023d61553df11198aa0b7e518455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: [PATCH 458/514] Move comment --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 48e902666..aa10aa55e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,14 +86,15 @@ struct XAigerWriter int bit2aig(SigBit bit) { - // NB: Cannot use iterator returned from aig_map.insert() - // since this function is called recursively auto it = aig_map.find(bit); if (it != aig_map.end()) { log_assert(it->second >= 0); return it->second; } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + int a = -1; if (not_map.count(bit)) { a = bit2aig(not_map.at(bit)) ^ 1; From bd7ec673dd5b542031698074e1043dcc32af2168 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:46:55 -0700 Subject: [PATCH 459/514] No point logging constant bit --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index aa10aa55e..6718e4f2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -110,7 +110,7 @@ struct XAigerWriter } if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n"); a = aig_map.at(State::S0); } From b75863ca3f835595d75a6943de3cdd01fc91e4ca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:23:39 -0700 Subject: [PATCH 460/514] Workaround issues exposed by gcc-4.8 --- frontends/aiger/aigerparse.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a98ea8314..221e3edfc 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -117,13 +117,20 @@ struct ConstEvalAig RTLIL::Cell *cell = sig2driver.at(output); RTLIL::SigBit sig_a = cell->getPort("\\A"); + sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); if (cell->type == "$_AND_") { RTLIL::SigSpec sig_b = cell->getPort("\\B"); + sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_b)) compute_deps(sig_b, inputs); } From 65c1199acd52f90de86106652dbbca86d4ac5ebc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: [PATCH 461/514] One more workaround for gcc-4.8 --- backends/aiger/xaiger.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6718e4f2c..637c54ff9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -429,12 +429,13 @@ struct XAigerWriter module->connect(new_bit, bit); if (not_map.count(bit)) not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); + else if (and_map.count(bit)) { + //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 + and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + } else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else - //log_abort(); alias_map[new_bit] = bit; output_bits.erase(bit); output_bits.insert(new_bit); From 7074ec9cd5d5b5c01e3bbaa8ee45dbae1272f185 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: [PATCH 462/514] Add log_push()/log_pop() inside write_xaiger --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 637c54ff9..2070cae8f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -664,6 +664,8 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { + log_push(); + // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); holes_module->check(); @@ -700,6 +702,8 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); + + log_pop(); } } From fddb027cabedff92441b912a6cc472650aa9f74d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:45:51 -0700 Subject: [PATCH 463/514] Replace assert with error message --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2070cae8f..23132f108 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -244,7 +244,8 @@ struct XAigerWriter if (c.second.is_fully_const()) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); - log_assert(is_input || is_output); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { for (auto b : c.second.bits()) { From ad296d77ab10266cd4b4df0779fbe7e5e0811c14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:46:45 -0700 Subject: [PATCH 464/514] Do not rename non LUT cells in abc9 --- passes/techmap/abc9.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e9f35be91..1783b4b1b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -522,8 +522,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri std::map cell_stats; for (auto c : mapped_mod->cells()) { + RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { - RTLIL::Cell *cell = nullptr; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); if (!a_bit.wire) { @@ -582,6 +582,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell_stats[RTLIL::unescape_id(c->type)]++; + RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; @@ -590,19 +591,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; continue; } + cell = module->addCell(remap_name(c->name), c->type); + } + else { + existing_cell = module->cell(c->name); + cell = module->addCell(remap_name(c->name), c->type); + module->swap_names(cell, existing_cell); } - RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - RTLIL::Cell *existing_cell = module->cell(c->name); - if (existing_cell) { - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; - } - else { - cell->parameters = c->parameters; - cell->attributes = c->attributes; - } + if (existing_cell) { + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; + } + else { + cell->parameters = c->parameters; + cell->attributes = c->attributes; + } for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { From f2ead4334ab278822743b856170a72bd11961bf7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:33:49 -0700 Subject: [PATCH 465/514] Reduce log_debug spam in parse_xaiger() --- frontends/aiger/aigerparse.cc | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 221e3edfc..efd265464 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -52,6 +52,9 @@ inline int32_t from_big_endian(int32_t i32) { #endif } +#define log_debug2(...) ; +//#define log_debug2(...) log_debug(__VA_ARGS__) + struct ConstEvalAig { RTLIL::Module *module; @@ -312,7 +315,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); + log_debug2("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); wire->port_input = wire->port_output = false; if (!invert) return wire; @@ -322,12 +325,12 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera if (module->cell(wire_inv_name)) return wire; } else { - log_debug("Creating %s\n", wire_inv_name.c_str()); + log_debug2("Creating %s\n", wire_inv_name.c_str()); wire_inv = module->addWire(wire_inv_name); wire_inv->port_input = wire_inv->port_output = false; } - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); return wire; @@ -403,13 +406,13 @@ void AigerReader::parse_xaiger() for (unsigned i = 0; i < lutNum; ++i) { uint32_t rootNodeID = parse_xaiger_literal(f); uint32_t cutLeavesM = parse_xaiger_literal(f); - log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); + log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID)); uint32_t nodeID; RTLIL::SigSpec input_sig; for (unsigned j = 0; j < cutLeavesM; ++j) { nodeID = parse_xaiger_literal(f); - log_debug("\t%u\n", nodeID); + log_debug2("\t%u\n", nodeID); RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID)); log_assert(wire); input_sig.append(wire); @@ -493,7 +496,7 @@ void AigerReader::parse_aiger_ascii() for (unsigned i = 1; i <= I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); - log_debug("%d is an input\n", l1); + log_debug2("%d is an input\n", l1); log_assert(!(l1 & 1)); // Inputs can't be inverted RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_input = true; @@ -506,7 +509,7 @@ void AigerReader::parse_aiger_ascii() log_assert(clk_name != ""); clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); + log_debug2("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; clk_wire->port_output = false; @@ -514,7 +517,7 @@ void AigerReader::parse_aiger_ascii() for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - log_debug("%d %d is a latch\n", l1, l2); + log_debug2("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); @@ -548,7 +551,7 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); + log_debug2("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix? @@ -569,7 +572,7 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1)) log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); - log_debug("%d is a bad state property\n", l1); + log_debug2("%d is a bad state property\n", l1); RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; bad_properties.push_back(wire); @@ -592,7 +595,7 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l1 >> l2 >> l3)) log_error("Line %u cannot be interpreted as an AND!\n", line_count); - log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_debug2("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); @@ -618,7 +621,7 @@ void AigerReader::parse_aiger_binary() // Parse inputs for (unsigned i = 1; i <= I; ++i) { - log_debug("%d is an input\n", i); + log_debug2("%d is an input\n", i); RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; log_assert(!wire->port_output); @@ -631,7 +634,7 @@ void AigerReader::parse_aiger_binary() log_assert(clk_name != ""); clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); + log_debug2("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; clk_wire->port_output = false; @@ -673,7 +676,7 @@ void AigerReader::parse_aiger_binary() if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); + log_debug2("%d is an output\n", l1); const unsigned variable = l1 >> 1; const bool invert = l1 & 1; RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix? @@ -695,7 +698,7 @@ void AigerReader::parse_aiger_binary() if (!(f >> l1)) log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); - log_debug("%d is a bad state property\n", l1); + log_debug2("%d is a bad state property\n", l1); RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; bad_properties.push_back(wire); @@ -721,7 +724,7 @@ void AigerReader::parse_aiger_binary() l2 = parse_next_delta_literal(f, l1); l3 = parse_next_delta_literal(f, l2); - log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_debug2("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); From 0f300e75c07dbcf21ab2d6128ef8af9ca6a98892 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:39:56 -0700 Subject: [PATCH 466/514] Fix CHANGELOG --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index fd72d5702..f7a6e9758 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,12 +16,14 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass + - Added "shregmap -tech xilinx" - Added "read_aiger" frontend - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - Extended "muxcover -mux{4,8,16}=" + - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) Yosys 0.7 .. Yosys 0.8 @@ -35,7 +37,7 @@ Yosys 0.7 .. Yosys 0.8 - Added "write_verilog -decimal" - Added "scc -set_attr" - Added "verilog_defines" command - - Remeber defines from one read_verilog to next + - Remember defines from one read_verilog to next - Added support for hierarchical defparam - Added FIRRTL back-end - Improved ABC default scripts From 65c022c2572036a66bd06bafd3e3efa088aafb79 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 20:41:14 -0700 Subject: [PATCH 467/514] Remove DFF and RAMD box info for now --- techlibs/xilinx/abc_xc7.box | 34 ---------------------------------- techlibs/xilinx/cells_sim.v | 2 -- 2 files changed, 36 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 8a48bad4e..c9d80a333 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -26,37 +26,3 @@ CARRY4 3 1 10 8 433 469 - - 494 465 445 - - 157 512 548 292 - 592 540 520 356 - 228 508 528 378 380 580 526 507 398 385 114 - -# SLICEM/A6LUT -# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE -# Outputs: DPO SPO -RAM64X1D 4 0 15 2 -- - - - - - - 124 124 124 124 124 124 - - -124 124 124 124 124 124 - - - - - - 124 - - - -# SLICEM/A6LUT + F7[AB]MUX -# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE -# Outputs: DPO SPO -RAM128X1D 5 0 17 2 -- - - - - - - - 314 314 314 314 314 314 292 - - -347 347 347 347 347 347 296 - - - - - - - - - - - -# Inputs: C CE D R -# Outputs: Q -FDRE 6 0 4 1 -- - - - - -# Inputs: C CE D S -# Outputs: Q -FDSE 7 0 4 1 -- - - - - -# Inputs: C CE CLR D -# Outputs: Q -FDCE 8 0 4 1 -- - - - - -# Inputs: C CE D PRE -# Outputs: Q -FDPE 9 0 4 1 -- - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index bf7a0ed44..84939818e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,7 +281,6 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -//(* abc_box_id = 4 /*, lib_whitebox*/ *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -299,7 +298,6 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -//(* abc_box_id = 5 /*, lib_whitebox*/ *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 7903ebe3e004c03e7870f1b21c4fb478481756eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:18:42 -0700 Subject: [PATCH 468/514] Carry in/out box ordering now move to end, not swap with end --- backends/aiger/xaiger.cc | 60 +++++++++++++++++++++---------------- techlibs/xilinx/abc_xc7.box | 24 +++++++-------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 23132f108..7cfe8272c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -309,38 +309,46 @@ struct XAigerWriter if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - RTLIL::Wire* last_in = nullptr, *last_out = nullptr; - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); + auto &ports = box_module->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*it); log_assert(w); - if (w->port_input) { - if (w->attributes.count("\\abc_carry_in")) { - log_assert(!carry_in); - carry_in = w; - } - log_assert(!last_in || last_in->port_id < w->port_id); - last_in = w; + if (w->port_input && w->attributes.count("\\abc_carry_in")) { + if (carry_in) + log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); + carry_in = w; + it = ports.erase(it); + continue; } - if (w->port_output) { - if (w->attributes.count("\\abc_carry_out")) { - log_assert(!carry_out); - carry_out = w; - } - log_assert(!last_out || last_out->port_id < w->port_id); - last_out = w; + if (w->port_output && w->attributes.count("\\abc_carry_out")) { + if (carry_out) + log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); + carry_out = w; + it = ports.erase(it); + continue; } + ++it; } - if (carry_in) { - log_assert(last_in); - std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); - std::swap(carry_in->port_id, last_in->port_id); - } - if (carry_out) { - log_assert(last_out); - std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); - std::swap(carry_out->port_id, last_out->port_id); + if (!carry_in) + log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); + if (!carry_out) + log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); + + for (const auto port_name : ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index c9d80a333..0a6a6eaf0 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -12,17 +12,17 @@ MUXF8 2 1 3 1 104 94 273 # CARRY4 + CARRY4_[ABCD]X -# Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI +# Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI # Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 -# (NB: carry chain input/output must be last input/output, -# swapped with what normally would have been the last -# output, here: CI <-> S, CO <-> O +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) CARRY4 3 1 10 8 -223 - - - 482 - - - - 222 -400 205 - - 598 407 - - - 334 -523 558 226 - 584 556 537 - - 239 -582 618 330 227 642 615 596 438 - 313 -340 - - - 536 379 - - - 271 -433 469 - - 494 465 445 - - 157 -512 548 292 - 592 540 520 356 - 228 -508 528 378 380 580 526 507 398 385 114 +482 - - - - 223 - - - 222 +598 407 - - - 400 205 - - 334 +584 556 537 - - 523 558 226 - 239 +642 615 596 438 - 582 618 330 227 313 +536 379 - - - 340 - - - 271 +494 465 445 - - 433 469 - - 157 +592 540 520 356 - 512 548 292 - 228 +580 526 507 398 385 508 528 378 380 114 From 63182ed57d3a62c8c5e316cea48216024afb38a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:27:41 -0700 Subject: [PATCH 469/514] Fix and cleanup ice40 boxes for carry in/out --- techlibs/ice40/abc_hx.box | 112 +++---------------------------------- techlibs/ice40/abc_lp.box | 110 +++--------------------------------- techlibs/ice40/abc_u.box | 112 +++---------------------------------- techlibs/ice40/cells_sim.v | 4 +- 4 files changed, 25 insertions(+), 313 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index a0655643d..f8e12b527 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -1,113 +1,17 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt # NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) -# Inputs: C D -# Outputs: Q -SB_DFF 1 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFE 2 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFSR 3 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFR 4 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFSS 5 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFS 6 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFESR 7 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFER 8 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFESS 9 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFES 10 0 4 1 -- - - - - -# Inputs: C D -# Outputs: Q -SB_DFFN 11 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFNE 12 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNSR 13 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNR 14 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNSS 15 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNS 16 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNESR 17 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNER 18 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNESS 19 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNES 20 0 4 1 -- - - - - -# Inputs: CI I0 I1 +# Inputs: I0 I1 CI # Outputs: CO -SB_CARRY 21 1 3 1 -126 259 231 +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +SB_CARRY 1 1 3 1 +259 231 126 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 1 4 1 +SB_LUT4 2 1 4 1 449 400 379 316 diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index eb1cd0937..fbe4c56e6 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -1,113 +1,17 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt # NB: Inputs/Outputs must be ordered alphabetically - -# Inputs: C D -# Outputs: Q -SB_DFF 1 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFE 2 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFSR 3 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFR 4 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFSS 5 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFS 6 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFESR 7 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFER 8 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFESS 9 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFES 10 0 4 1 -- - - - - -# Inputs: C D -# Outputs: Q -SB_DFFN 11 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFNE 12 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNSR 13 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNR 14 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNSS 15 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNS 16 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNESR 17 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNER 18 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNESS 19 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNES 20 0 4 1 -- - - - +# (with exceptions for carry in/out) # Inputs: CI I0 I1 # Outputs: CO -SB_CARRY 21 1 3 1 -186 675 609 +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +SB_CARRY 1 1 3 1 +675 609 186 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 1 4 1 +SB_LUT4 2 1 4 1 661 589 558 465 diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 3b5834e40..f44deabc4 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -1,113 +1,17 @@ # From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt # NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) -# Inputs: C D -# Outputs: Q -SB_DFF 1 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFE 2 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFSR 3 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFR 4 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFSS 5 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFS 6 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFESR 7 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFER 8 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFESS 9 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFES 10 0 4 1 -- - - - - -# Inputs: C D -# Outputs: Q -SB_DFFN 11 0 2 1 -- - - -# Inputs: C D E -# Outputs: Q -SB_DFFNE 12 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNSR 13 0 3 1 -- - - - -# Inputs: C D R -# Outputs: Q -SB_DFFNR 14 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNSS 15 0 3 1 -- - - - -# Inputs: C D S -# Outputs: Q -SB_DFFNS 16 0 3 1 -- - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNESR 17 0 4 1 -- - - - - -# Inputs: C D E R -# Outputs: Q -SB_DFFNER 18 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNESS 19 0 4 1 -- - - - - -# Inputs: C D E S -# Outputs: Q -SB_DFFNES 20 0 4 1 -- - - - - -# Inputs: CI I0 I1 +# Inputs: I0 I1 CI # Outputs: CO -SB_CARRY 21 1 3 1 -278 675 609 +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) +SB_CARRY 1 1 3 1 +675 609 278 # Inputs: I0 I1 I2 I3 # Outputs: O -SB_LUT4 22 1 4 1 +SB_LUT4 2 1 4 1 1285 1231 1205 874 diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 031afa85c..317ae2c1f 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -127,7 +127,7 @@ endmodule // SiliconBlue Logic Cells -(* abc_box_id = 22, lib_whitebox *) +(* abc_box_id = 2, lib_whitebox *) module SB_LUT4 (output O, input I0, I1, I2, I3); parameter [15:0] LUT_INIT = 0; wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; @@ -136,7 +136,7 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 21, abc_carry, lib_whitebox *) +(* abc_box_id = 1, abc_carry, lib_whitebox *) module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule From 792d0670c3bfe5af7946c6deb0df4656b820d195 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:28:24 -0700 Subject: [PATCH 470/514] Add comment to xc7 box --- techlibs/xilinx/abc_xc7.box | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 0a6a6eaf0..b5817a6e0 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -1,5 +1,8 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + # F7BMUX slower than F7AMUX # Inputs: I0 I1 S0 # Outputs: O From 6027549464bf91cee4d4bcbe9586e719dce78c80 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:33:47 -0700 Subject: [PATCH 471/514] Add comments to ecp5 box --- techlibs/ecp5/abc_5g.box | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc_5g.box index 72af6d9cb..15e26b5d5 100644 --- a/techlibs/ecp5/abc_5g.box +++ b/techlibs/ecp5/abc_5g.box @@ -1,5 +1,11 @@ +# NB: Inputs/Outputs must be ordered alphabetically +# (with exceptions for carry in/out) + # Box 1 : CCU2C (2xCARRY + 2xLUT4) # Outputs: S0, S1, COUT +# (NB: carry chain input/output must be last +# input/output and have been moved there +# overriding the alphabetical ordering) # name ID w/b ins outs CCU2C 1 1 9 3 From 9dca024a30e5f6cfb06e1abb584ce1320fb81f16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 21:52:53 -0700 Subject: [PATCH 472/514] Add tests/various/abc9.{v,ys} with SCC test --- tests/various/abc9.v | 5 +++++ tests/various/abc9.ys | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/various/abc9.v create mode 100644 tests/various/abc9.ys diff --git a/tests/various/abc9.v b/tests/various/abc9.v new file mode 100644 index 000000000..8271cd249 --- /dev/null +++ b/tests/various/abc9.v @@ -0,0 +1,5 @@ +module abc9_test027(output reg o); +initial o = 1'b0; +always @* + o <= ~o; +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys new file mode 100644 index 000000000..922f7005d --- /dev/null +++ b/tests/various/abc9.ys @@ -0,0 +1,14 @@ +read_verilog abc9.v +proc +design -save gold + +abc9 -lut 4 +check +design -stash gate + +design -import gold -as gold +design -import gate -as gate + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -show-ports miter + From 49a762ba4633ef7cda3e12f755cd5c8e97b7bf13 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 21:53:18 -0700 Subject: [PATCH 473/514] Fix abc9's scc breaker, also break on abc_scc_break attr --- passes/techmap/abc9.cc | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1783b4b1b..c0b0e4160 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -80,9 +80,6 @@ void handle_loops(RTLIL::Design *design) { Pass::call(design, "scc -set_attr abc_scc_id {}"); - design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = design->selection_stack.back(); - // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output // wires @@ -92,24 +89,49 @@ void handle_loops(RTLIL::Design *design) if (it != cell->attributes.end()) { auto r = ids_seen.insert(it->second); if (r.second) { - for (const auto &c : cell->connections()) { + for (auto &c : cell->connections_) { if (c.second.is_fully_const()) continue; if (cell->output(c.first)) { SigBit b = c.second.as_bit(); Wire *w = b.wire; + log_assert(!w->port_input); + w->port_input = true; + w = module->wire(stringf("%s.abci", log_id(w->name))); + if (!w) + w = module->addWire(stringf("%s.abci", log_id(b.wire->name)), GetSize(b.wire)); + log_assert(b.offset < GetSize(w)); + w->port_output = true; w->set_bool_attribute("\\abc_scc_break"); - sel.select(module, w); + module->swap_names(b.wire, w); + c.second = RTLIL::SigBit(w, b.offset); } } } cell->attributes.erase(it); } + RTLIL::Module* box_module = design->module(cell->type); + if (box_module) { + auto jt = box_module->attributes.find("\\abc_scc_break"); + if (jt != box_module->attributes.end()) { + auto it = cell->connections_.find(RTLIL::escape_id(jt->second.decode_string())); + log_assert(it != cell->connections_.end()); + auto &c = *it; + SigBit b = cell->getPort(RTLIL::escape_id(jt->second.decode_string())); + Wire *w = b.wire; + log_assert(!w->port_output); + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", log_id(w->name))); + if (!w) + w = module->addWire(stringf("%s.abci", log_id(b.wire->name)), GetSize(b.wire)); + log_assert(b.offset < GetSize(w)); + w->port_input = true; + c.second = RTLIL::SigBit(w, b.offset); + } + } } - // Then cut those selected wires to expose them as new PO/PI - Pass::call(design, "expose -cut -sep .abc"); - - design->selection_stack.pop_back(); + module->fixup_ports(); } std::string add_echos_to_abc_cmd(std::string str) From 152e682bd5e448aaca20e7c9349c88bbd4a8ed3b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 21:54:01 -0700 Subject: [PATCH 474/514] Add Xilinx dist RAM as comb boxes --- techlibs/xilinx/abc_xc7.box | 14 ++++++++++++++ techlibs/xilinx/cells_sim.v | 2 ++ 2 files changed, 16 insertions(+) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index b5817a6e0..40b92da0c 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -29,3 +29,17 @@ CARRY4 3 1 10 8 494 465 445 - - 433 469 - - 157 592 540 520 356 - 512 548 292 - 228 580 526 507 398 385 508 528 378 380 114 + +# SLICEM/A6LUT +# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE +# Outputs: DPO SPO +RAM64X1D 4 0 15 2 +- - - - - - - 124 124 124 124 124 124 - - +124 124 124 124 124 124 - - - - - - 124 - - + +# SLICEM/A6LUT + F7[AB]MUX +# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE +# Outputs: DPO SPO +RAM128X1D 5 0 17 2 +- - - - - - - - 314 314 314 314 314 314 292 - - +347 347 347 347 347 347 296 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 84939818e..8261286af 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,6 +281,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule +(* abc_box_id = 4, abc_scc_break="D" *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -298,6 +299,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule +(* abc_box_id = 5, abc_scc_break="D" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From ca0225fcfaa8c9c68647034351a1569464959edf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 21:55:54 -0700 Subject: [PATCH 475/514] Re-enable dist RAM boxes for ECP5 --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index f66147323..567942482 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -106,7 +106,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -//(* abc_box_id=2 *) +(* abc_box_id=2, abc_scc_break="D" *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From babadf59386550246cc56e96656c9fce775c80be Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:04:22 -0700 Subject: [PATCH 476/514] Do not use log_id as it strips \\, also fix scc for |wire| > 1 --- passes/techmap/abc9.cc | 43 +++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index c0b0e4160..c8272153d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -96,11 +96,15 @@ void handle_loops(RTLIL::Design *design) Wire *w = b.wire; log_assert(!w->port_input); w->port_input = true; - w = module->wire(stringf("%s.abci", log_id(w->name))); - if (!w) - w = module->addWire(stringf("%s.abci", log_id(b.wire->name)), GetSize(b.wire)); - log_assert(b.offset < GetSize(w)); - w->port_output = true; + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_output = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } w->set_bool_attribute("\\abc_scc_break"); module->swap_names(b.wire, w); c.second = RTLIL::SigBit(w, b.offset); @@ -118,14 +122,27 @@ void handle_loops(RTLIL::Design *design) auto &c = *it; SigBit b = cell->getPort(RTLIL::escape_id(jt->second.decode_string())); Wire *w = b.wire; - log_assert(!w->port_output); - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - w = module->wire(stringf("%s.abci", log_id(w->name))); - if (!w) - w = module->addWire(stringf("%s.abci", log_id(b.wire->name)), GetSize(b.wire)); - log_assert(b.offset < GetSize(w)); - w->port_input = true; + if (w->port_output) { + log_assert(w->get_bool_attribute("\\abc_scc_break")); + w = module->wire(stringf("%s.abci", w->name.c_str())); + log_assert(w); + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); + } + else { + log_assert(!w->port_output); + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_input = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } + } c.second = RTLIL::SigBit(w, b.offset); } } From a4a7e63d84dee73554d53587f38409e25db84b66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:10:28 -0700 Subject: [PATCH 477/514] Revert "Re-enable dist RAM boxes for ECP5" This reverts commit ca0225fcfaa8c9c68647034351a1569464959edf. --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 567942482..f66147323 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -106,7 +106,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -(* abc_box_id=2, abc_scc_break="D" *) +//(* abc_box_id=2 *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From 4fadb471a3028487d4b05b3e343b3be49349f78b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:12:50 -0700 Subject: [PATCH 478/514] Re-enable dist RAM boxes for ECP5 --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index f66147323..0239d1afe 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -106,7 +106,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -//(* abc_box_id=2 *) +(* abc_box_id=2, abc_scc_break="DI" *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From 5605002d8a583409a56d1187460de1f4a03d8454 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:12:55 -0700 Subject: [PATCH 479/514] More meaningful error message --- passes/techmap/abc9.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index c8272153d..6356d4fbf 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -118,6 +118,8 @@ void handle_loops(RTLIL::Design *design) auto jt = box_module->attributes.find("\\abc_scc_break"); if (jt != box_module->attributes.end()) { auto it = cell->connections_.find(RTLIL::escape_id(jt->second.decode_string())); + if (it == cell->connections_.end()) + log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", jt->second.decode_string().c_str(), log_id(box_module)); log_assert(it != cell->connections_.end()); auto &c = *it; SigBit b = cell->getPort(RTLIL::escape_id(jt->second.decode_string())); From a19226c174e31da444b831706adf7fa17e9cb9e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:16:56 -0700 Subject: [PATCH 480/514] Fix for abc_scc_break is bus --- passes/techmap/abc9.cc | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6356d4fbf..cd7954427 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -121,31 +121,33 @@ void handle_loops(RTLIL::Design *design) if (it == cell->connections_.end()) log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", jt->second.decode_string().c_str(), log_id(box_module)); log_assert(it != cell->connections_.end()); - auto &c = *it; - SigBit b = cell->getPort(RTLIL::escape_id(jt->second.decode_string())); - Wire *w = b.wire; - if (w->port_output) { - log_assert(w->get_bool_attribute("\\abc_scc_break")); - w = module->wire(stringf("%s.abci", w->name.c_str())); - log_assert(w); - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - else { - log_assert(!w->port_output); - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_input = true; + RTLIL::SigSpec sig; + for (auto b : it->second) { + Wire *w = b.wire; + if (w->port_output) { + log_assert(w->get_bool_attribute("\\abc_scc_break")); + w = module->wire(stringf("%s.abci", w->name.c_str())); + log_assert(w); + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); } else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); + log_assert(!w->port_output); + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_input = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } } + sig.append(RTLIL::SigBit(w, b.offset)); } - c.second = RTLIL::SigBit(w, b.offset); + it->second = sig; } } } From 2f770b7400f6b12ca13e68496977094f92c13680 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:02:53 -0700 Subject: [PATCH 481/514] Use LUT delays for dist RAM delays --- techlibs/xilinx/abc_xc7.box | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 40b92da0c..8c046cdbc 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -34,12 +34,12 @@ CARRY4 3 1 10 8 # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO RAM64X1D 4 0 15 2 -- - - - - - - 124 124 124 124 124 124 - - -124 124 124 124 124 124 - - - - - - 124 - - +- - - - - - - 642 631 472 407 238 127 - - +642 631 472 407 238 127 - - - - - - - - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO RAM128X1D 5 0 17 2 -- - - - - - - - 314 314 314 314 314 314 292 - - -347 347 347 347 347 347 296 - - - - - - - - - - +- - - - - - - - 1009 998 839 774 605 494 450 - - +1047 1036 877 812 643 532 478 - - - - - - - - - - From d2fed0a7f1bb72ee285657b974f4996c77641a23 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:37:01 -0700 Subject: [PATCH 482/514] nullptr check --- passes/techmap/abc9.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index cd7954427..52ca47a49 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -124,6 +124,7 @@ void handle_loops(RTLIL::Design *design) RTLIL::SigSpec sig; for (auto b : it->second) { Wire *w = b.wire; + if (!w) continue; if (w->port_output) { log_assert(w->get_bool_attribute("\\abc_scc_break")); w = module->wire(stringf("%s.abci", w->name.c_str())); From 609535739036c30efc35a57730e5ffe968267cdb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:54:35 -0700 Subject: [PATCH 483/514] Add RAM32X1D box info --- techlibs/xilinx/abc_xc7.box | 11 +++++++++-- techlibs/xilinx/cells_sim.v | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 8c046cdbc..1a7243f54 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -30,16 +30,23 @@ CARRY4 3 1 10 8 592 540 520 356 - 512 548 292 - 228 580 526 507 398 385 508 528 378 380 114 +# SLICEM/A6LUT +# Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE +# Outputs: DPO SPO +RAM32X1D 4 0 13 2 +- - - - - - 124 124 124 124 124 - - +124 124 124 124 124 - - - - - - - - + # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO -RAM64X1D 4 0 15 2 +RAM64X1D 5 0 15 2 - - - - - - - 642 631 472 407 238 127 - - 642 631 472 407 238 127 - - - - - - - - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO -RAM128X1D 5 0 17 2 +RAM128X1D 6 0 17 2 - - - - - - - - 1009 998 839 774 605 494 450 - - 1047 1036 877 812 643 532 478 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 67b221c95..04381e3b9 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,6 +281,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule +(* abc_box_id = 4, abc_scc_break="D" *) module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, @@ -298,7 +299,7 @@ module RAM32X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 4, abc_scc_break="D" *) +(* abc_box_id = 5, abc_scc_break="D" *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -316,7 +317,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 5, abc_scc_break="D" *) +(* abc_box_id = 6, abc_scc_break="D" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 480a04cb3c3b6a2eb097a78f68fa9ff79caad24e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:05:28 -0700 Subject: [PATCH 484/514] Realistic delays for RAM32X1D too --- techlibs/xilinx/abc_xc7.box | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 1a7243f54..96966a71c 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -34,8 +34,8 @@ CARRY4 3 1 10 8 # Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE # Outputs: DPO SPO RAM32X1D 4 0 13 2 -- - - - - - 124 124 124 124 124 - - -124 124 124 124 124 - - - - - - - - +- - - - - - 631 472 407 238 127 - - +631 472 407 238 127 - - - - - - - - # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE From 5db96b8aec7be2fb864d0f41ef21bb5168fa6b5c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 25 Jun 2019 10:38:42 -0700 Subject: [PATCH 485/514] Missing muxpack.o in Makefile --- passes/opt/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 337fee9e4..ea3646330 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -14,5 +14,6 @@ OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o OBJS += passes/opt/opt_lut.o OBJS += passes/opt/pmux2shiftx.o +OBJS += passes/opt/muxpack.o endif From 0dd850e6552a74430559ed63c3a9a67aa1c84512 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Jun 2019 11:39:44 +0100 Subject: [PATCH 486/514] abc9: Add wire delays to synth_ice40 Signed-off-by: David Shah --- techlibs/ice40/synth_ice40.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index d8e9786c5..a782f00b9 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -331,8 +331,16 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); } if (!noabc) { - if (abc == "abc9") - run(abc + stringf(" -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); + if (abc == "abc9") { + int wire_delay; + if (device_opt == "lp") + wire_delay = 400; + else if (device_opt == "u") + wire_delay = 750; + else + wire_delay = 250; + run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); + } else run(abc + " -dress -lut 4", "(skip if -noabc)"); } From 988e6163abae4ed0a01952c221d17f70bed9c244 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:23:29 -0700 Subject: [PATCH 487/514] Add _nowide variants of LUT libraries in -nowidelut flows --- techlibs/ecp5/abc_5g_nowide.lut | 12 ++++++++++++ techlibs/ecp5/synth_ecp5.cc | 5 ++++- techlibs/xilinx/abc_xc7_nowide.lut | 10 ++++++++++ techlibs/xilinx/synth_xilinx.cc | 30 ++++++++++++++++++------------ 4 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 techlibs/ecp5/abc_5g_nowide.lut create mode 100644 techlibs/xilinx/abc_xc7_nowide.lut diff --git a/techlibs/ecp5/abc_5g_nowide.lut b/techlibs/ecp5/abc_5g_nowide.lut new file mode 100644 index 000000000..60352d892 --- /dev/null +++ b/techlibs/ecp5/abc_5g_nowide.lut @@ -0,0 +1,12 @@ +# ECP5-5G LUT library for ABC +# Note that ECP5 architecture assigns difference +# in LUT input delay to interconnect, so this is +# considered too + + +# Simple LUTs +# area D C B A +1 1 141 +2 1 141 275 +3 1 141 275 379 +4 1 141 275 379 379 diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index c80ad0b08..f16a47f01 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -273,7 +273,10 @@ struct SynthEcp5Pass : public ScriptPass } run("techmap -map +/ecp5/latches_map.v"); if (abc9) { - run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200"); + if (nowidelut) + run("abc9 -lut +/ecp5/abc_5g_nowide.lut -box +/ecp5/abc_5g.box -W 200"); + else + run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200"); } else { if (nowidelut) run("abc -lut 4 -dress"); diff --git a/techlibs/xilinx/abc_xc7_nowide.lut b/techlibs/xilinx/abc_xc7_nowide.lut new file mode 100644 index 000000000..fab48c879 --- /dev/null +++ b/techlibs/xilinx/abc_xc7_nowide.lut @@ -0,0 +1,10 @@ +# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf +# and https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json + +# K area delay +1 1 127 +2 2 127 238 +3 3 127 238 407 +4 3 127 238 407 472 +5 3 127 238 407 472 631 +6 5 127 238 407 472 631 642 diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 69f9507c3..b17b9beb5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -100,14 +100,14 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, abc, arch; - bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut; + bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9; void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; edif_file.clear(); blif_file.clear(); - abc = "abc"; + arch = "xc7"; flatten = false; retime = false; vpr = false; @@ -117,7 +117,7 @@ struct SynthXilinxPass : public ScriptPass nosrl = false; nocarry = false; nowidelut = false; - arch = "xc7"; + abc9 = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -189,7 +189,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-abc9") { - abc = "abc9"; + abc9 = true; continue; } break; @@ -284,7 +284,7 @@ struct SynthXilinxPass : public ScriptPass techmap_files += " -map +/xilinx/arith_map.v"; if (vpr) techmap_files += " -D _EXPLICIT_CARRY"; - else if (abc == "abc9") + else if (abc9) techmap_files += " -D _CLB_CARRY"; } run("techmap " + techmap_files); @@ -298,14 +298,20 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef"); - if (abc == "abc9") - run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + XC7_WIRE_DELAY + string(retime ? " -dff" : "")); - else if (help_mode) + if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')"); - else if (nowidelut) - run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); - else - run(abc + " -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + else if (abc9) { + if (nowidelut) + run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); + else + run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); + } + else { + if (nowidelut) + run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); + else + run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + } run("clean"); // This shregmap call infers fixed length shift registers after abc From 5e1b8d458bcfb231284ce9d3756cdbb583aa928b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:33:07 -0700 Subject: [PATCH 488/514] Remove unused var --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b17b9beb5..83c2edc86 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -99,7 +99,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); } - std::string top_opt, edif_file, blif_file, abc, arch; + std::string top_opt, edif_file, blif_file, arch; bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9; void clear_flags() YS_OVERRIDE From 1d0be89214466aa5120d6fc0e155c6366ae8e802 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:17:11 -0700 Subject: [PATCH 489/514] Add write_xaiger into CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index f0154a81e..73115600c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "muxcover -dmux=" - Added "muxcover -nopartial" - Added "muxpack" pass + - Added "write_xaiger" backend - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) From 26efd6f0a9ee5930efef7e1d00724bbb87489885 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:57:54 -0700 Subject: [PATCH 490/514] Support more than one port in the abc_scc_break attr --- passes/techmap/abc9.cc | 80 ++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 52ca47a49..0671fc965 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -80,6 +80,8 @@ void handle_loops(RTLIL::Design *design) { Pass::call(design, "scc -set_attr abc_scc_id {}"); + dict> module_break; + // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output // wires @@ -113,44 +115,46 @@ void handle_loops(RTLIL::Design *design) } cell->attributes.erase(it); } - RTLIL::Module* box_module = design->module(cell->type); - if (box_module) { - auto jt = box_module->attributes.find("\\abc_scc_break"); - if (jt != box_module->attributes.end()) { - auto it = cell->connections_.find(RTLIL::escape_id(jt->second.decode_string())); - if (it == cell->connections_.end()) - log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", jt->second.decode_string().c_str(), log_id(box_module)); - log_assert(it != cell->connections_.end()); - RTLIL::SigSpec sig; - for (auto b : it->second) { - Wire *w = b.wire; - if (!w) continue; - if (w->port_output) { - log_assert(w->get_bool_attribute("\\abc_scc_break")); - w = module->wire(stringf("%s.abci", w->name.c_str())); - log_assert(w); - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - else { - log_assert(!w->port_output); - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_input = true; - } - else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); - } - } - sig.append(RTLIL::SigBit(w, b.offset)); - } - it->second = sig; - } - } + + auto jt = module_break.find(cell->type); + if (jt == module_break.end()) { + std::vector ports; + if (!yosys_celltypes.cell_known(cell->type)) { + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); + for (const auto &port_name : split_tokens(ports_csv, ",")) { + auto port_id = RTLIL::escape_id(port_name); + auto kt = cell->connections_.find(port_id); + if (kt == cell->connections_.end()) + log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", port_name.c_str(), log_id(box_module)); + ports.push_back(port_id); + } + } + jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; + } + + for (auto port_name : jt->second) { + RTLIL::SigSpec sig; + auto &rhs = cell->connections_.at(port_name); + for (auto b : rhs) { + Wire *w = b.wire; + if (!w) continue; + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_input = true; + } + else { + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); + } + sig.append(RTLIL::SigBit(w, b.offset)); + } + rhs = sig; + } } module->fixup_ports(); From b7bef15b16abf1674d9c2efc58536db3abaf0e3d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:58:09 -0700 Subject: [PATCH 491/514] Add "WE" to dist RAM's abc_scc_break --- techlibs/xilinx/cells_sim.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 04381e3b9..4ecf8277b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -281,7 +281,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4, abc_scc_break="D" *) +(* abc_box_id = 4, abc_scc_break="D,WE" *) module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, @@ -299,7 +299,7 @@ module RAM32X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 5, abc_scc_break="D" *) +(* abc_box_id = 5, abc_scc_break="D,WE" *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -317,7 +317,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 6, abc_scc_break="D" *) +(* abc_box_id = 6, abc_scc_break="D,WE" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From a7a88109f5b750862b8e45c194e8094fd32b8a5f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:00:15 -0700 Subject: [PATCH 492/514] Update comment on boxes --- techlibs/ecp5/abc_5g.box | 5 +++-- techlibs/xilinx/abc_xc7.box | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc_5g.box index 15e26b5d5..5309aca87 100644 --- a/techlibs/ecp5/abc_5g.box +++ b/techlibs/ecp5/abc_5g.box @@ -4,8 +4,9 @@ # Box 1 : CCU2C (2xCARRY + 2xLUT4) # Outputs: S0, S1, COUT # (NB: carry chain input/output must be last -# input/output and have been moved there -# overriding the alphabetical ordering) +# input/output and bus has been moved +# there overriding the otherwise +# alphabetical ordering) # name ID w/b ins outs CCU2C 1 1 9 3 diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 96966a71c..6dd71d758 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -18,8 +18,9 @@ MUXF8 2 1 3 1 # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI # Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 # (NB: carry chain input/output must be last -# input/output and have been moved there -# overriding the alphabetical ordering) +# input/output and the entire bus has been +# moved there overriding the otherwise +# alphabetical ordering) CARRY4 3 1 10 8 482 - - - - 223 - - - 222 598 407 - - - 400 205 - - 334 From 4de25a1949c14f4c343eae957b9402b5ddb574c9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:02:19 -0700 Subject: [PATCH 493/514] Add WE to ECP5 dist RAM's abc_scc_break too --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 0239d1afe..b678a14da 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -106,7 +106,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -(* abc_box_id=2, abc_scc_break="DI" *) +(* abc_box_id=2, abc_scc_break="DI,WRE" *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From 080a5ca536bcd7140ea3dc12483e49a8f076cd92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:02:38 -0700 Subject: [PATCH 494/514] Improve debugging message for comb loops --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cfe8272c..92df899c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -293,10 +293,12 @@ struct XAigerWriter #if 0 unsigned i = 0; for (auto &it : toposort.loops) { - log(" loop %d", i++); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); + log(" loop %d\n", i++); + for (auto cell_name : it) { + auto cell = module->cell(cell_name); + log_assert(cell); + log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); + } } #endif log_assert(no_loops); From c226af3f56957cc69b2ce8bb68a8259e26121ddc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:03:34 -0700 Subject: [PATCH 495/514] Fix spacing --- passes/techmap/abc9.cc | 74 +++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0671fc965..b4f15d6a1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -116,45 +116,45 @@ void handle_loops(RTLIL::Design *design) cell->attributes.erase(it); } - auto jt = module_break.find(cell->type); + auto jt = module_break.find(cell->type); if (jt == module_break.end()) { - std::vector ports; - if (!yosys_celltypes.cell_known(cell->type)) { - RTLIL::Module* box_module = design->module(cell->type); - log_assert(box_module); - auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); - for (const auto &port_name : split_tokens(ports_csv, ",")) { - auto port_id = RTLIL::escape_id(port_name); - auto kt = cell->connections_.find(port_id); - if (kt == cell->connections_.end()) - log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", port_name.c_str(), log_id(box_module)); - ports.push_back(port_id); - } - } - jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; - } + std::vector ports; + if (!yosys_celltypes.cell_known(cell->type)) { + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); + for (const auto &port_name : split_tokens(ports_csv, ",")) { + auto port_id = RTLIL::escape_id(port_name); + auto kt = cell->connections_.find(port_id); + if (kt == cell->connections_.end()) + log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", port_name.c_str(), log_id(box_module)); + ports.push_back(port_id); + } + } + jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; + } - for (auto port_name : jt->second) { - RTLIL::SigSpec sig; - auto &rhs = cell->connections_.at(port_name); - for (auto b : rhs) { - Wire *w = b.wire; - if (!w) continue; - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_input = true; - } - else { - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - sig.append(RTLIL::SigBit(w, b.offset)); - } - rhs = sig; - } + for (auto port_name : jt->second) { + RTLIL::SigSpec sig; + auto &rhs = cell->connections_.at(port_name); + for (auto b : rhs) { + Wire *w = b.wire; + if (!w) continue; + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_input = true; + } + else { + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); + } + sig.append(RTLIL::SigBit(w, b.offset)); + } + rhs = sig; + } } module->fixup_ports(); From 6c256b8cda66e2ba128d5fa3ba344fe4717711f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:20:15 -0700 Subject: [PATCH 496/514] Merge origin/master --- backends/btor/btor.cc | 30 ++- backends/smt2/smtio.py | 5 +- frontends/verilog/const2ast.cc | 2 +- passes/opt/opt_clean.cc | 6 +- passes/techmap/muxcover.cc | 31 +++- techlibs/ecp5/cells_map.v | 40 +++- techlibs/ecp5/cells_sim.v | 94 ++++++---- techlibs/xilinx/cells_sim.v | 2 +- techlibs/xilinx/synth_xilinx.cc | 15 +- tests/various/muxcover.ys | 320 ++++++++++++++++++++++++++++++++ 10 files changed, 480 insertions(+), 65 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 511a11942..a507b120b 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -17,6 +17,11 @@ * */ +// [[CITE]] Btor2 , BtorMC and Boolector 3.0 +// Aina Niemetz, Mathias Preiner, Clifford Wolf, Armin Biere +// Computer Aided Verification - 30th International Conference, CAV 2018 +// https://cs.stanford.edu/people/niemetz/publication/2018/niemetzpreinerwolfbiere-cav18/ + #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -875,9 +880,28 @@ struct BtorWorker else { if (bit_cell.count(bit) == 0) - log_error("No driver for signal bit %s.\n", log_signal(bit)); - export_cell(bit_cell.at(bit)); - log_assert(bit_nid.count(bit)); + { + SigSpec s = bit; + + while (i+GetSize(s) < GetSize(sig) && sig[i+GetSize(s)].wire != nullptr && + bit_cell.count(sig[i+GetSize(s)]) == 0) + s.append(sig[i+GetSize(s)]); + + log_warning("No driver for signal %s.\n", log_signal(s)); + + int sid = get_bv_sid(GetSize(s)); + int nid = next_nid++; + btorf("%d input %d %s\n", nid, sid); + nid_width[nid] = GetSize(s); + + i += GetSize(s)-1; + continue; + } + else + { + export_cell(bit_cell.at(bit)); + log_assert(bit_nid.count(bit)); + } } } diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index cea0fc56c..ae7968a1b 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1043,7 +1043,10 @@ class MkVcd: scope = scope[:-1] while uipath[:-1] != scope: - print("$scope module %s $end" % uipath[len(scope)], file=self.f) + scopename = uipath[len(scope)] + if scopename.startswith("$"): + scopename = "\\" + scopename + print("$scope module %s $end" % scopename, file=self.f) scope.append(uipath[len(scope)]) if path in self.clocks and self.clocks[path][1] == "event": diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 3a3634d34..f6a17b242 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -153,7 +153,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn { if (warn_z) { AstNode *ret = const2ast(code, case_type); - if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) + if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", current_filename.c_str(), get_line_num()); return ret; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cfb0f788a..a8a8e0bc7 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -326,8 +326,8 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) { // do not delete anything with "keep" or module ports or initialized wires } else - if (!purge_mode && check_public_name(wire->name)) { - // do not get rid of public names unless in purge mode + if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) { + // do not get rid of public names unless in purge mode or if the wire is entirely unused, not even aliased } else if (!raw_used_signals.check_any(s1)) { // delete wires that aren't used by anything directly @@ -480,7 +480,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool std::vector delcells; for (auto cell : module->cells()) - if (cell->type.in("$pos", "$_BUF_")) { + if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) { bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec y = cell->getPort("\\Y"); diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b0722134e..c84cfc39a 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -81,6 +81,23 @@ struct MuxcoverWorker decode_mux_counter = 0; } + bool xcmp(std::initializer_list list) + { + auto cursor = list.begin(), end = list.end(); + log_assert(cursor != end); + SigBit tmp = *(cursor++); + while (cursor != end) { + SigBit bit = *(cursor++); + if (bit == State::Sx) + continue; + if (tmp == State::Sx) + tmp = bit; + if (bit != tmp) + return false; + } + return true; + } + void treeify() { pool roots; @@ -144,6 +161,8 @@ struct MuxcoverWorker if (tree.muxes.count(bit) == 0) { if (first_layer || nopartial) return false; + while (path[0] && path[1]) + path++; if (path[0] == 'S') ret_bit = State::Sx; else @@ -280,7 +299,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S2, tree, bit, "BS"); if (nodecode) - ok = ok && S1 == S2; + ok = ok && xcmp({S1, S2}); ok = ok && follow_muxtree(T1, tree, bit, "S"); @@ -330,13 +349,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S4, tree, bit, "BBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4; + ok = ok && xcmp({S1, S2, S3, S4}); ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); if (nodecode) - ok = ok && T1 == T2; + ok = ok && xcmp({T1, T2}); ok = ok && follow_muxtree(U1, tree, bit, "S"); @@ -407,7 +426,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; + ok = ok && xcmp({S1, S2, S3, S4, S5, S6, S7, S8}); ok = ok && follow_muxtree(T1, tree, bit, "AAS"); ok = ok && follow_muxtree(T2, tree, bit, "ABS"); @@ -415,13 +434,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(T4, tree, bit, "BBS"); if (nodecode) - ok = ok && T1 == T2 && T2 == T3 && T3 == T4; + ok = ok && xcmp({T1, T2, T3, T4}); ok = ok && follow_muxtree(U1, tree, bit, "AS"); ok = ok && follow_muxtree(U2, tree, bit, "BS"); if (nodecode) - ok = ok && U1 == U2; + ok = ok && xcmp({U1, U2}); ok = ok && follow_muxtree(V1, tree, bit, "S"); diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index b504d51e2..6985fbbc8 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -47,6 +47,28 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED" module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +// TODO: Diamond flip-flops +// module FD1P3AX(); endmodule +// module FD1P3AY(); endmodule +// module FD1P3BX(); endmodule +// module FD1P3DX(); endmodule +// module FD1P3IX(); endmodule +// module FD1P3JX(); endmodule +// module FD1S3AX(); endmodule +// module FD1S3AY(); endmodule +module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +// module FL1P3AY(); endmodule +// module FL1P3AZ(); endmodule +// module FL1P3BX(); endmodule +// module FL1P3DX(); endmodule +// module FL1P3IY(); endmodule +// module FL1P3JY(); endmodule +// module FL1S3AX(); endmodule +// module FL1S3AY(); endmodule + // Diamond I/O buffers module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule @@ -62,8 +84,22 @@ module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #( module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule -// For Diamond compatibility, FIXME: add all Diamond flipflop mappings -module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +// Diamond I/O registers +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond I/O latches +// module IFS1S1B(input PD, D, SCLK, output Q); endmodule +// module IFS1S1D(input CD, D, SCLK, output Q); endmodule +// module IFS1S1I(input PD, D, SCLK, output Q); endmodule +// module IFS1S1J(input CD, D, SCLK, output Q); endmodule `ifndef NO_LUT module \$lut (A, Y); diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index b678a14da..08ae0a112 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -260,18 +260,6 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); endgenerate endmodule -// --------------------------------------- - -module OBZ(input I, T, output O); -assign O = T ? 1'bz : I; -endmodule - -// --------------------------------------- - -module IB(input I, output O); -assign O = I; -endmodule - // --------------------------------------- (* keep *) module TRELLIS_IO( @@ -303,19 +291,6 @@ endmodule // --------------------------------------- -module OB(input I, output O); -assign O = I; -endmodule - -// --------------------------------------- - -module BB(input I, T, output O, inout B); -assign B = T ? 1'bz : I; -assign O = B; -endmodule - -// --------------------------------------- - module INV(input A, output Z); assign Z = !A; endmodule @@ -568,19 +543,56 @@ module DP16KD( parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule -// For Diamond compatibility, FIXME: add all Diamond flipflop mappings -module FD1S3BX(input PD, D, CK, output Q); - TRELLIS_FF #( - .GSR("DISABLED"), - .CEMUX("1"), - .CLKMUX("CLK"), - .LSRMUX("LSR"), - .REGSET("SET"), - .SRMODE("ASYNC") - ) tff_i ( - .CLK(CK), - .LSR(PD), - .DI(D), - .Q(Q) - ); -endmodule +// TODO: Diamond flip-flops +// module FD1P3AX(); endmodule +// module FD1P3AY(); endmodule +// module FD1P3BX(); endmodule +// module FD1P3DX(); endmodule +// module FD1P3IX(); endmodule +// module FD1P3JX(); endmodule +// module FD1S3AX(); endmodule +// module FD1S3AY(); endmodule +module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +// module FL1P3AY(); endmodule +// module FL1P3AZ(); endmodule +// module FL1P3BX(); endmodule +// module FL1P3DX(); endmodule +// module FL1P3IY(); endmodule +// module FL1P3JY(); endmodule +// module FL1S3AX(); endmodule +// module FL1S3AY(); endmodule + +// Diamond I/O buffers +module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule +module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule +module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule +module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I)); endmodule +module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule +module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule +module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule +module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule +module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule +module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) tio (.B(A), .O(Z)); endmodule +module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule + +// Diamond I/O registers +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond I/O latches +// module IFS1S1B(input PD, D, SCLK, output Q); endmodule +// module IFS1S1D(input CD, D, SCLK, output Q); endmodule +// module IFS1S1I(input PD, D, SCLK, output Q); endmodule +// module IFS1S1J(input CD, D, SCLK, output Q); endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 4ecf8277b..5fd9973f4 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -286,7 +286,7 @@ module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, input A0, A1, A2, A3, A4, - input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, + input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 ); parameter INIT = 32'h0; parameter IS_WCLK_INVERTED = 1'b0; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 83c2edc86..fab070882 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -45,8 +45,9 @@ struct SynthXilinxPass : public ScriptPass log(" -top \n"); log(" use the specified module as top module\n"); log("\n"); - log(" -arch {xcup|xcu|xc7|xc6s}\n"); + log(" -family {xcup|xcu|xc7|xc6s}\n"); log(" run synthesis for the specified Xilinx architecture\n"); + log(" generate the synthesis netlist for the specified family.\n"); log(" default: xc7\n"); log("\n"); log(" -edif \n"); @@ -99,7 +100,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); } - std::string top_opt, edif_file, blif_file, arch; + std::string top_opt, edif_file, blif_file, family; bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9; void clear_flags() YS_OVERRIDE @@ -107,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass top_opt = "-auto-top"; edif_file.clear(); blif_file.clear(); - arch = "xc7"; + family = "xc7"; flatten = false; retime = false; vpr = false; @@ -132,8 +133,8 @@ struct SynthXilinxPass : public ScriptPass top_opt = "-top " + args[++argidx]; continue; } - if (args[argidx] == "-arch" && argidx+1 < args.size()) { - arch = args[++argidx]; + if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) { + family = args[++argidx]; continue; } if (args[argidx] == "-edif" && argidx+1 < args.size()) { @@ -196,8 +197,8 @@ struct SynthXilinxPass : public ScriptPass } extra_args(args, argidx, design); - if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s") - log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str()); + if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s") + log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 8ef619b46..67e9625e6 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -188,3 +188,323 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter +## MUX2 in MUX4 :: https://github.com/YosysHQ/yosys/issues/1132 + +design -reset +read_verilog -formal < Date: Thu, 27 Jun 2019 11:20:40 -0700 Subject: [PATCH 497/514] Remove unneeded include --- frontends/aiger/aigerparse.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index efd265464..43337f4c2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,9 +22,6 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf -#ifdef _WIN32 -#include -#endif // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include From 1237a4c11679685808a677593e261e21b950749a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:22:49 -0700 Subject: [PATCH 498/514] Add warning if synth_xilinx -abc9 with family != xc7 --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index fab070882..7dbd98055 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -302,6 +302,8 @@ struct SynthXilinxPass : public ScriptPass if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')"); else if (abc9) { + if (family != "xc7") + log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); if (nowidelut) run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); else From fb30fcb7c582406f627ebb15833791411091f738 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:03:21 -0700 Subject: [PATCH 499/514] Undo iterator based Module::remove() for cells, as containers will not invalidate --- kernel/rtlil.cc | 12 ++---------- kernel/rtlil.h | 1 - 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 502b45cfd..a09f4a0d1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1592,21 +1592,13 @@ void RTLIL::Module::remove(const pool &wires) void RTLIL::Module::remove(RTLIL::Cell *cell) { - auto it = cells_.find(cell->name); - log_assert(it != cells_.end()); - remove(it); -} - -dict::iterator RTLIL::Module::remove(dict::iterator it) -{ - RTLIL::Cell *cell = it->second; while (!cell->connections_.empty()) cell->unsetPort(cell->connections_.begin()->first); + log_assert(cells_.count(cell->name) != 0); log_assert(refcount_cells_ == 0); - it = cells_.erase(it); + cells_.erase(cell->name); delete cell; - return it; } void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 4a0f8b4f8..f4fcf5dcf 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1040,7 +1040,6 @@ public: // Removing wires is expensive. If you have to remove wires, remove them all at once. void remove(const pool &wires); void remove(RTLIL::Cell *cell); - dict::iterator remove(dict::iterator it); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); From 6bf73e3546450671660e793991c982eeadf1872e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:15:56 -0700 Subject: [PATCH 500/514] Cleanup abc9.cc --- passes/techmap/abc9.cc | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b4f15d6a1..f25b02a88 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -80,7 +80,7 @@ void handle_loops(RTLIL::Design *design) { Pass::call(design, "scc -set_attr abc_scc_id {}"); - dict> module_break; + dict> abc_scc_break; // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output @@ -116,12 +116,11 @@ void handle_loops(RTLIL::Design *design) cell->attributes.erase(it); } - auto jt = module_break.find(cell->type); - if (jt == module_break.end()) { + auto jt = abc_scc_break.find(cell->type); + if (jt == abc_scc_break.end()) { std::vector ports; - if (!yosys_celltypes.cell_known(cell->type)) { - RTLIL::Module* box_module = design->module(cell->type); - log_assert(box_module); + RTLIL::Module* box_module = design->module(cell->type); + if (box_module) { auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); for (const auto &port_name : split_tokens(ports_csv, ",")) { auto port_id = RTLIL::escape_id(port_name); @@ -131,7 +130,7 @@ void handle_loops(RTLIL::Design *design) ports.push_back(port_id); } } - jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; + jt = abc_scc_break.insert(std::make_pair(cell->type, std::move(ports))).first; } for (auto port_name : jt->second) { @@ -554,17 +553,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri signal = std::move(bits); } + dict abc_box; vector boxes; - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; - if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { - it = module->remove(it); + for (auto cell : module->cells()) { + if (cell->type.in("$_AND_", "$_NOT_")) { + module->remove(cell); continue; } - RTLIL::Module* box_module = design->module(cell->type); - if (box_module && box_module->attributes.count("\\abc_box_id")) - boxes.emplace_back(it->second); - ++it; + auto it = abc_box.find(cell->type); + if (it == abc_box.end()) { + RTLIL::Module* box_module = design->module(cell->type); + it = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first; + } + if (it->second) + boxes.emplace_back(cell); } std::map cell_stats; From 137c91d9a98e05199b7acfe1d63139b79d278277 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:17:39 -0700 Subject: [PATCH 501/514] Remove &retime when abc9 -fast --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f25b02a88..e2a82f0c8 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -33,7 +33,7 @@ #endif -#define ABC_FAST_COMMAND_LUT "&st; &retime; &if {W}" +#define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" #include "kernel/register.h" #include "kernel/sigtools.h" From 312c03e4ca71f1560a9f47dcd2e9d3de1202179e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:28:55 -0700 Subject: [PATCH 502/514] Remove redundant doc --- techlibs/xilinx/synth_xilinx.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7dbd98055..c24f66e52 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -62,9 +62,6 @@ struct SynthXilinxPass : public ScriptPass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); - log(" -nocarry\n"); - log(" disable inference of carry chains\n"); - log("\n"); log(" -nobram\n"); log(" disable inference of block rams\n"); log("\n"); From a625854ac5e2ff3d6bf11e97b7ac676b362e7461 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:29:20 -0700 Subject: [PATCH 503/514] Do not use Module::remove() iterator version --- passes/techmap/abc9.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index e2a82f0c8..3721b82b7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -555,17 +555,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri dict abc_box; vector boxes; - for (auto cell : module->cells()) { + for (const auto &it : module->cells_) { + auto cell = it.second; if (cell->type.in("$_AND_", "$_NOT_")) { module->remove(cell); continue; } - auto it = abc_box.find(cell->type); - if (it == abc_box.end()) { + auto jt = abc_box.find(cell->type); + if (jt == abc_box.end()) { RTLIL::Module* box_module = design->module(cell->type); - it = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first; + jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first; } - if (it->second) + if (jt->second) boxes.emplace_back(cell); } From 9398921af1d21b47aa291d240a1f274418adcaf2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:07:14 -0700 Subject: [PATCH 504/514] Refactor for one "abc_carry" attribute on module --- backends/aiger/xaiger.cc | 80 +++++++++++++++++------------------ frontends/aiger/aigerparse.cc | 70 ++++++++++++++++-------------- techlibs/ecp5/cells_sim.v | 8 ++-- techlibs/ice40/cells_sim.v | 4 +- techlibs/xilinx/cells_sim.v | 4 +- 5 files changed, 84 insertions(+), 82 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 92df899c2..ae690ec49 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -284,8 +284,6 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - #if 0 toposort.analyze_loops = true; #endif @@ -303,54 +301,54 @@ struct XAigerWriter #endif log_assert(no_loops); + pool seen_boxes; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); + log_assert(cell); + RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { - RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - auto &ports = box_module->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = box_module->wire(*it); - log_assert(w); - if (w->port_input && w->attributes.count("\\abc_carry_in")) { - if (carry_in) - log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); - carry_in = w; - it = ports.erase(it); - continue; - } - if (w->port_output && w->attributes.count("\\abc_carry_out")) { - if (carry_out) - log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); - carry_out = w; - it = ports.erase(it); - continue; - } - ++it; - } + if (seen_boxes.insert(cell->type).second) { + auto it = box_module->attributes.find("\\abc_carry"); + if (it != box_module->attributes.end()) { + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + auto carry_in_out = it->second.decode_string(); + auto pos = carry_in_out.find(','); + if (pos == std::string::npos) + log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + carry_in = box_module->wire(carry_in_name); + if (!carry_in || !carry_in->port_input) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); - if (!carry_in) - log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); - if (!carry_out) - log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); + auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + carry_out = box_module->wire(carry_out_name); + if (!carry_out || !carry_out->port_output) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); - for (const auto port_name : ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); + auto &ports = box_module->ports; + for (auto jt = ports.begin(); jt != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*jt); + log_assert(w); + if (w == carry_in || w == carry_out) { + jt = ports.erase(jt); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++jt; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 43337f4c2..7008d0542 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -732,44 +732,50 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { - pool abc_carry_modules; + pool seen_boxes; unsigned ci_count = 0, co_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { - RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - RTLIL::Wire* last_in = nullptr, *last_out = nullptr; - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - if (w->port_input) { - if (w->attributes.count("\\abc_carry_in")) { - log_assert(!carry_in); - carry_in = w; - } - log_assert(!last_in || last_in->port_id < w->port_id); - last_in = w; - } - if (w->port_output) { - if (w->attributes.count("\\abc_carry_out")) { - log_assert(!carry_out); - carry_out = w; - } - log_assert(!last_out || last_out->port_id < w->port_id); - last_out = w; - } - } + if (seen_boxes.insert(cell->type).second) { + auto it = box_module->attributes.find("\\abc_carry"); + if (it != box_module->attributes.end()) { + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + auto carry_in_out = it->second.decode_string(); + auto pos = carry_in_out.find(','); + if (pos == std::string::npos) + log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + carry_in = box_module->wire(carry_in_name); + if (!carry_in || !carry_in->port_input) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); - if (carry_in != last_in) { - std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]); - std::swap(carry_in->port_id, last_in->port_id); - } - if (carry_out != last_out) { - log_assert(last_out); - std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]); - std::swap(carry_out->port_id, last_out->port_id); + auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + carry_out = box_module->wire(carry_out_name); + if (!carry_out || !carry_out->port_output) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); + + auto &ports = box_module->ports; + for (auto jt = ports.begin(); jt != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*jt); + log_assert(w); + if (w == carry_in || w == carry_out) { + jt = ports.erase(jt); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++jt; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } } diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 08ae0a112..98f915777 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -15,11 +15,9 @@ module L6MUX21 (input D0, D1, SD, output Z); endmodule // --------------------------------------- -(* abc_box_id=1, abc_carry, lib_whitebox *) -module CCU2C((* abc_carry_in *) input CIN, - input A0, B0, C0, D0, A1, B1, C1, D1, - output S0, S1, - (* abc_carry_out *) output COUT); +(* abc_box_id=1, abc_carry="CIN,COUT", lib_whitebox *) +module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1, + output S0, S1, COUT); parameter [15:0] INIT0 = 16'h0000; parameter [15:0] INIT1 = 16'h0000; diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 317ae2c1f..c7e4101e1 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -136,8 +136,8 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 1, abc_carry, lib_whitebox *) -module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI); +(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *) +module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 5fd9973f4..5a148be01 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -173,8 +173,8 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, abc_carry, lib_whitebox *) -module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S); +(* abc_box_id = 3, abc_carry="CI,CO", lib_whitebox *) +module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; assign CO[1] = S[1] ? CO[0] : DI[1]; From 4daa74679779a45542b36c1f3630bd1fbae9ec7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:11:39 -0700 Subject: [PATCH 505/514] Remove noise from ice40/cells_sim.v --- techlibs/ice40/cells_sim.v | 5 ----- 1 file changed, 5 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index c7e4101e1..b746ba4e5 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -144,12 +144,8 @@ endmodule // Positive Edge SiliconBlue FF Cells module SB_DFF (output `SB_DFF_REG, input C, D); -`ifndef _ABC always @(posedge C) Q <= D; -`else - always @* Q <= D; -`endif endmodule module SB_DFFE (output `SB_DFF_REG, input C, E, D); @@ -896,7 +892,6 @@ module SB_WARMBOOT ( ); endmodule -(* nomem2reg *) module SB_SPRAM256KA ( input [13:0] ADDRESS, input [15:0] DATAIN, From af8a5ae5fe35d65742eb17db8cd2bacda93e916e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:12:20 -0700 Subject: [PATCH 506/514] Extraneous newline --- techlibs/ice40/synth_ice40.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index a782f00b9..caef420d4 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -105,7 +105,6 @@ struct SynthIce40Pass : public ScriptPass log("\n"); } - string top_opt, blif_file, edif_file, json_file, abc, device_opt; bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr; int min_ce_use; From 00f63d82ce4fbaa0f63ff2c68d4941f7eb16dfc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:13:22 -0700 Subject: [PATCH 507/514] Reduce diff with upstream --- techlibs/xilinx/cells_map.v | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index b5114758c..9a316fc96 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -20,16 +20,14 @@ // Convert negative-polarity reset to positive-polarity (* techmap_celltype = "$_DFF_NN0_" *) -module _90_dff_nn0_to_np0(input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule (* techmap_celltype = "$_DFF_PN0_" *) -module _90_dff_pn0_to_pp0(input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule - +module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule (* techmap_celltype = "$_DFF_NN1_" *) module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule (* techmap_celltype = "$_DFF_PN1_" *) module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule - module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; From b9ddee0c87ef3f089995d734ad7f5ea1c65eedce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:45:40 -0700 Subject: [PATCH 508/514] Fix DO4 typo --- techlibs/ecp5/abc_5g.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc_5g.box index 5309aca87..c757d137d 100644 --- a/techlibs/ecp5/abc_5g.box +++ b/techlibs/ecp5/abc_5g.box @@ -16,7 +16,7 @@ CCU2C 1 1 9 3 516 516 516 516 412 412 278 278 43 # Box 2 : TRELLIS_DPR16X4 (16x4 dist ram) -# Outputs: DO0, DO1, DO2, DO3, DO4 +# Outputs: DO0, DO1, DO2, DO3 # name ID w/b ins outs TRELLIS_DPR16X4 2 0 14 4 From 0318860b93f7fa4eee148597811c77d67171e5d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:45:48 -0700 Subject: [PATCH 509/514] Add write address to abc_scc_break of ECP5 dist RAM --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 98f915777..acfb6960e 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -104,7 +104,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -(* abc_box_id=2, abc_scc_break="DI,WRE" *) +(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From 3f87575cb6cdace3de8dbe1b494e4d29a478878e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:46:36 -0700 Subject: [PATCH 510/514] Disable boxing of ECP5 dist RAM due to regression --- techlibs/ecp5/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index acfb6960e..ca88d0a5b 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -104,7 +104,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- -(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *) +//(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, From 03705f69f4e7fbd19181297cd4de68472a5f4ba3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:49:01 -0700 Subject: [PATCH 511/514] Update synth_ice40 -device doc to be relevant for -abc9 only --- techlibs/ice40/synth_ice40.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index caef420d4..9dd5d81f7 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -38,8 +38,8 @@ struct SynthIce40Pass : public ScriptPass log("This command runs synthesis for iCE40 FPGAs.\n"); log("\n"); log(" -device < hx | lp | u >\n"); - log(" optimise the synthesis netlist for the specified device.\n"); - log(" HX is the default target if no device argument specified.\n"); + log(" relevant only for '-abc9' flow, optimise timing for the specified device.\n"); + log(" default: hx\n"); log("\n"); log(" -top \n"); log(" use the specified module as top module\n"); From 36e2eb06bb63714d852b758062471222022930c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:51:43 -0700 Subject: [PATCH 512/514] Fix more potential for undefined behaviour due to container invalidation --- backends/aiger/xaiger.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae690ec49..d373ca77e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -436,14 +436,18 @@ struct XAigerWriter new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) { - //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 - and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + if (not_map.count(bit)) { + auto a = not_map.at(bit); + not_map[new_bit] = a; + } + else if (and_map.count(bit)) { + auto a = and_map.at(bit); + and_map[new_bit] = a; + } + else if (alias_map.count(bit)) { + auto a = alias_map.at(bit); + alias_map[new_bit] = a; } - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); else alias_map[new_bit] = bit; output_bits.erase(bit); From 524af2131741ae2c74a810cab3b925d5ce950e6e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:55:07 -0700 Subject: [PATCH 513/514] Also fix write_aiger for UB --- backends/aiger/aiger.cc | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 2815abda8..7c851bb91 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -70,35 +70,35 @@ struct AigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (initstate_bits.count(bit)) { - log_assert(initstate_ff > 0); - aig_map[bit] = initstate_ff; - } else - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } - - if (bit == State::Sx || bit == State::Sz) - log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) + log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + + log_assert(a >= 0); + aig_map[bit] = a; + return a; } AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) From 38d8806bd74b9bb448c7488ec571e197fe2f96d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:59:47 -0700 Subject: [PATCH 514/514] Add generic __builtin_bswap32 function --- backends/aiger/xaiger.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d373ca77e..eb3d47569 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,21 @@ #elif defined(__APPLE__) #include #define __builtin_bswap32 OSSwapInt32 +#elif !defined(__GNUC__) +#include +inline uint32_t __builtin_bswap32(uint32_t x) +{ + // https://stackoverflow.com/a/27796212 + register uint32_t value = number_to_be_reversed; + uint8_t lolo = (value >> 0) & 0xFF; + uint8_t lohi = (value >> 8) & 0xFF; + uint8_t hilo = (value >> 16) & 0xFF; + uint8_t hihi = (value >> 24) & 0xFF; + return (hihi << 24) + | (hilo << 16) + | (lohi << 8) + | (lolo << 0); +} #endif #include "kernel/yosys.h"