From e25a22015f1b422a7a5cb176fd1c509af056e796 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:23:54 -0800 Subject: [PATCH 001/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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/927] 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 0a94441579f25f3661071692d2290c5c3b224a6a Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Tue, 26 Feb 2019 20:53:31 -0500 Subject: [PATCH 098/927] dockerize yosys --- Dockerfile | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..3a4358335 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +FROM ubuntu:16.04 as builder +LABEL author="Abdelrahman Hosny " + +RUN apt-get update && apt-get install -y build-essential \ + clang \ + bison \ + flex \ + libreadline-dev \ + gawk \ + tcl-dev \ + libffi-dev \ + git \ + graphviz \ + xdot \ + pkg-config \ + python3 + +COPY . / +RUN make && \ + make install + + +FROM ubuntu:16.04 +RUN apt-get update && apt-get install -y clang \ + bison \ + flex \ + libreadline-dev \ + gawk \ + tcl-dev \ + libffi-dev \ + git \ + graphviz \ + xdot \ + pkg-config \ + python3 +COPY --from=builder /yosys /build/yosys +COPY --from=builder /yosys-abc /build/yosys-abc +COPY --from=builder /yosys-config /build/yosys-config +COPY --from=builder /yosys-filterlib /build/yosys-filterlib +COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc + +ENV PATH /build:$PATH + +RUN mkdir /data +WORKDIR /data + +ENTRYPOINT ["yosys"] From 3e3b115e0f3c9f0f9a37884cd3449bfbecfdc9f6 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Tue, 26 Feb 2019 21:02:02 -0500 Subject: [PATCH 099/927] add dockerignore file --- .dockerignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..9910e9954 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.editorconfig +.gitignore +.gitmodules +.github +.git +Dockerfile +README.md +manual +CodingReadme +CodeOfConduct +.travis +.travis.yml + From ed358b237b597f2198c6e354e7c4084faf769d3a Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Fri, 1 Mar 2019 20:06:43 -0500 Subject: [PATCH 100/927] address review comments --- Dockerfile | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3a4358335..3c7188d82 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:16.04 as builder +FROM ubuntu:18.04 as builder LABEL author="Abdelrahman Hosny " - +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y build-essential \ clang \ bison \ @@ -10,29 +10,17 @@ RUN apt-get update && apt-get install -y build-essential \ tcl-dev \ libffi-dev \ git \ - graphviz \ - xdot \ pkg-config \ - python3 - + python3 && \ + rm -rf /var/lib/apt/lists COPY . / RUN make && \ make install +FROM ubuntu:18.04 +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y libreadline-dev tcl-dev -FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y clang \ - bison \ - flex \ - libreadline-dev \ - gawk \ - tcl-dev \ - libffi-dev \ - git \ - graphviz \ - xdot \ - pkg-config \ - python3 COPY --from=builder /yosys /build/yosys COPY --from=builder /yosys-abc /build/yosys-abc COPY --from=builder /yosys-config /build/yosys-config @@ -40,8 +28,6 @@ COPY --from=builder /yosys-filterlib /build/yosys-filterlib COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc ENV PATH /build:$PATH - -RUN mkdir /data -WORKDIR /data - +RUN useradd -m yosys +USER yosys ENTRYPOINT ["yosys"] From 36efec01b8b2b29fadc015d5e061a3a21319aea5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:37:22 -0700 Subject: [PATCH 101/927] 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 102/927] 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 103/927] 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 104/927] 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 105/927] 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 106/927] 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 107/927] 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 108/927] 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 109/927] 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 110/927] 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 111/927] 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 112/927] 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 113/927] 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 114/927] 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 115/927] 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 116/927] 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 117/927] 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 118/927] 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 119/927] 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 120/927] 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 121/927] 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 122/927] 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 123/927] 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 124/927] 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 125/927] 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 126/927] 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 127/927] 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 128/927] 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 129/927] 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 130/927] 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 131/927] 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 132/927] 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 133/927] 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 134/927] 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 135/927] 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 136/927] 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 137/927] 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 138/927] 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 139/927] 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 140/927] 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 141/927] 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 142/927] 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 143/927] 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 144/927] 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 145/927] 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 146/927] 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 147/927] 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 148/927] 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 149/927] 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 150/927] 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 151/927] 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 152/927] 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 153/927] 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 154/927] 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 155/927] 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 156/927] 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 157/927] 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 158/927] 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 159/927] 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 160/927] 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 161/927] 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 162/927] 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 163/927] 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 164/927] 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 165/927] 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 166/927] 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 167/927] 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 168/927] 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 169/927] 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 170/927] 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 171/927] 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 172/927] 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 173/927] 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 174/927] 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 175/927] 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 176/927] 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 177/927] 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 178/927] 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 179/927] 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 180/927] 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 181/927] 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 182/927] 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 183/927] 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 184/927] 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 185/927] 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 186/927] 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 187/927] 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 188/927] 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 189/927] 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 190/927] 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 191/927] 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 192/927] 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 193/927] 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 194/927] 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 195/927] 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 196/927] 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 197/927] 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 198/927] 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 199/927] 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 200/927] 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 201/927] 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 202/927] 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 203/927] 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 204/927] 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 205/927] 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 206/927] 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 207/927] 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 208/927] 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 209/927] 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 210/927] 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 211/927] 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 212/927] 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 213/927] 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 214/927] 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 215/927] 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 216/927] 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 217/927] 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 218/927] 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 219/927] 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 220/927] 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 221/927] 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 222/927] 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 223/927] 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 224/927] 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 225/927] 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 226/927] 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 227/927] 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 228/927] 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 229/927] 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 230/927] 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 231/927] 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 232/927] 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 233/927] 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 234/927] 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 235/927] 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 236/927] 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 237/927] 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 238/927] 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 239/927] 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 240/927] 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 241/927] 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 242/927] 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 243/927] 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 244/927] 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 245/927] 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 246/927] 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 247/927] 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 248/927] 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 249/927] 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 250/927] 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 98e5a625c45ae1ec8e6aa37a1db2238250e7a097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Tue, 30 Apr 2019 12:54:21 +0200 Subject: [PATCH 251/927] synth_xilinx: Add -nocarry and -nomux options. --- techlibs/xilinx/synth_xilinx.cc | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 58dd928a0..cc70823ef 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -72,6 +72,12 @@ struct SynthXilinxPass : public Pass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); + log(" -nocarry\n"); + log(" do not use XORCY/MUXCY cells in output netlist\n"); + log("\n"); + log(" -nomux\n"); + log(" do not use MUXF[78] muxes to implement LUTs larger than LUT6s\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"); @@ -154,6 +160,8 @@ struct SynthXilinxPass : public Pass std::string run_from, run_to; bool flatten = false; bool retime = false; + bool nocarry = false; + bool nomux = false; bool vpr = false; bool nobram = false; bool nodram = false; @@ -190,6 +198,14 @@ struct SynthXilinxPass : public Pass retime = true; continue; } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } + if (args[argidx] == "-nomux") { + nomux = true; + continue; + } if (args[argidx] == "-vpr") { vpr = true; continue; @@ -268,13 +284,13 @@ struct SynthXilinxPass : public Pass Pass::call(design, "memory_map"); 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, "opt -fast"); } @@ -303,7 +319,10 @@ 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, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + if (nomux) + Pass::call(design, "abc -luts 2:2,3,6:5" + string(retime ? " -dff" : "")); + else + Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming From 3b5e8c86a4516c202e877ee5ca154062682e15b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 2 May 2019 11:00:49 -0700 Subject: [PATCH 252/927] 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 253/927] 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 254/927] 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 255/927] 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 256/927] 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 257/927] 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 ac10e7d96da4965751fd60a8dd42a8998c011c39 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Fri, 3 May 2019 03:10:43 +0300 Subject: [PATCH 258/927] Initial implementation of elaboration system tasks (IEEE1800-2017 section 20.11) This PR allows us to use $info/$warning/$error/$fatal **at elaboration time** within a generate block. This is very useful to stop a synthesis of a parametrized block when an illegal combination of parameters is chosen. --- frontends/ast/ast.cc | 1 + frontends/ast/ast.h | 4 ++- frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 47 ++++++++++++++++++++++++++++-- frontends/verilog/verilog_lexer.l | 5 ++++ frontends/verilog/verilog_parser.y | 11 ++++++- kernel/log.cc | 11 +++++++ kernel/log.h | 1 + tests/various/elab_sys_tasks.sv | 30 +++++++++++++++++++ tests/various/elab_sys_tasks.ys | 1 + 10 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 tests/various/elab_sys_tasks.sv create mode 100644 tests/various/elab_sys_tasks.ys diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 9f88b08c1..d28345503 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) X(AST_GENIF) X(AST_GENCASE) X(AST_GENBLOCK) + X(AST_TECALL) X(AST_POSEDGE) X(AST_NEGEDGE) X(AST_EDGE) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 281cbe086..b3e6fbaa0 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -137,7 +137,8 @@ namespace AST AST_GENIF, AST_GENCASE, AST_GENBLOCK, - + AST_TECALL, + AST_POSEDGE, AST_NEGEDGE, AST_EDGE, @@ -233,6 +234,7 @@ namespace AST bool mem2reg_check(pool &mem2reg_set); void mem2reg_remove(pool &mem2reg_set, vector &delnodes); void meminfo(int &mem_width, int &mem_size, int &addr_bits); + bool check_elab_tasks(void); // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index b3a2a84be..d5e7d94ab 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -856,6 +856,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENVAR: case AST_GENFOR: case AST_GENBLOCK: + case AST_TECALL: case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 4d4b9dfe1..e6132995d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1146,7 +1146,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_GENFOR) { for (size_t i = 0; i < buf->children.size(); i++) { - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } } else { @@ -1261,7 +1262,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } for (size_t i = 0; i < buf->children.size(); i++) { - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -1340,7 +1342,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } for (size_t i = 0; i < buf->children.size(); i++) { - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -2969,6 +2972,44 @@ static void mark_memories_assign_lhs_complex(dict> & } } +// handle $info(), $warning(), $error(), $fatal() +// we don't do that in simplify() because we don't know +bool AstNode::check_elab_tasks(void) +{ + if (type == AST_TECALL) { + int sz = children.size(); + if (str == "$info") { + if (sz > 0) + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_info(filename, linenum, "\n"); + } else if (str == "$warning") { + if (sz > 0) + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_warning(filename, linenum, "\n"); + } else if (str == "$error") { + if (sz > 0) + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "\n"); + } else if (str == "$fatal") { + // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() + // if no parameter is given, default value is 1 + // dollar_finish(sz ? children[0] : 1); + // perhaps create & use log_file_fatal() + if (sz > 0) + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "FATAL.\n"); + } else { + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); + } + return true; + } + return false; + +} // find memories that should be replaced by registers void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg_places, dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 6ef38252a..1c6810b47 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -301,6 +301,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/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 40968d17a..1965f090e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -105,7 +105,7 @@ static void free_attr(std::map *al) bool boolean; } -%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL +%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL TOK_ELAB_TASK %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM @@ -1869,6 +1869,15 @@ gen_stmt: if ($6 != NULL) delete $6; ast_stack.pop_back(); + } | + TOK_ELAB_TASK { + AstNode *node = new AstNode(AST_TECALL); + node->str = *$1; + delete $1; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + } opt_arg_list ';'{ + ast_stack.pop_back(); }; gen_stmt_block: diff --git a/kernel/log.cc b/kernel/log.cc index 9a9104e26..d2a661bb0 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -278,6 +278,17 @@ void log_file_warning(const std::string &filename, int lineno, va_end(ap); } +void log_file_info(const std::string &filename, int lineno, + const char *format, ...) +{ + va_list ap; + va_start(ap, format); + std::string prefix = stringf("%s:%d: Info: ", + filename.c_str(), lineno); + logv_warning_with_prefix(prefix.c_str(), format, ap); + va_end(ap); +} + YS_ATTRIBUTE(noreturn) static void logv_error_with_prefix(const char *prefix, const char *format, va_list ap) diff --git a/kernel/log.h b/kernel/log.h index e6afae716..3e1facae8 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -80,6 +80,7 @@ void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); // Log with filename to report a problem in a source file. void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); +void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); diff --git a/tests/various/elab_sys_tasks.sv b/tests/various/elab_sys_tasks.sv new file mode 100644 index 000000000..774d85b32 --- /dev/null +++ b/tests/various/elab_sys_tasks.sv @@ -0,0 +1,30 @@ +module test; +localparam X=1; +genvar i; +generate +if (X == 1) + $info("X is 1"); +if (X == 1) + $warning("X is 1"); +else + $error("X is not 1"); +case (X) + 1: $info("X is 1 in a case statement"); +endcase +//case (X-1) +// 1: $warn("X is 2"); +// default: $warn("X might be anything in a case statement"); +//endcase +for (i = 0; i < 3; i = i + 1) +begin + case(i) + 0: $info; + 1: $warning; + default: $info("default case statemnent"); + endcase +end + +$info("This is a standalone $info(). Next $info has no parameters"); +$info; +endgenerate +endmodule diff --git a/tests/various/elab_sys_tasks.ys b/tests/various/elab_sys_tasks.ys new file mode 100644 index 000000000..45bee3a60 --- /dev/null +++ b/tests/various/elab_sys_tasks.ys @@ -0,0 +1 @@ +read_verilog -sv elab_sys_tasks.sv From f06cb75b930d6ef5d8f4f12825ce0ef8f296ce17 Mon Sep 17 00:00:00 2001 From: Jakob Wenzel Date: Thu, 9 May 2019 12:37:31 +0200 Subject: [PATCH 259/927] initialize more registers in setundef -init --- passes/cmds/setundef.cc | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index f6949c820..5b43d528c 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -404,22 +404,29 @@ struct SetundefPass : public Pass { initwires.insert(wire); } - for (int wire_types = 0; wire_types < 2; wire_types++) - for (auto wire : module->wires()) - { - if (wire->name[0] == (wire_types ? '\\' : '$')) - next_wire: - continue; + for (int wire_types = 0; wire_types < 2; wire_types++) { + pool ffbitsToErase; + for (auto wire : module->wires()) { + if (wire->name[0] == (wire_types ? '\\' : '$')) { + next_wire: + continue; + } - for (auto bit : sigmap(wire)) - if (!ffbits.count(bit)) - goto next_wire; + for (auto bit : sigmap(wire)) + if (!ffbits.count(bit)) { + goto next_wire; + } - for (auto bit : sigmap(wire)) - ffbits.erase(bit); + for (auto bit : sigmap(wire)) { + ffbitsToErase.insert(bit); + } - initwires.insert(wire); - } + initwires.insert(wire); + } + for (const auto &bit : ffbitsToErase) { + ffbits.erase(bit); + } + } for (auto wire : initwires) { From 36a219063ad7b4e70581bf83a00365db764737bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 14:31:19 -0700 Subject: [PATCH 260/927] 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 261/927] 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 262/927] 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 263/927] 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 264/927] 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 265/927] 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 266/927] 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 267/927] 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 268/927] 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 269/927] 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 270/927] 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 271/927] 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 272/927] 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 273/927] 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 274/927] 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 275/927] 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 276/927] 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 277/927] 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 278/927] 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 279/927] 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 280/927] 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 281/927] 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 282/927] 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 283/927] 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 284/927] 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 285/927] 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 286/927] 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 287/927] 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 288/927] 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 289/927] 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 9a468f81c412f8b63d25e739f28932815c6882fb Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 28 May 2019 08:48:21 +0200 Subject: [PATCH 290/927] Optimizing DFFs whose initial value prevents their value from changing This is a proof of concept implementation that invokes SAT solver via Pass::call method. --- passes/opt/opt_rmdff.cc | 58 ++++++++++++++++++++++++++++++++++++++--- passes/sat/sat.cc | 4 +++ tests/opt/opt_ff_sat.v | 15 +++++++++++ tests/opt/opt_ff_sat.ys | 4 +++ 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tests/opt/opt_ff_sat.v create mode 100644 tests/opt/opt_ff_sat.ys diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 2abffa2a9..72eac9111 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -30,6 +30,7 @@ SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; bool keepdc; +bool sat; void remove_init_attr(SigSpec sig) { @@ -258,7 +259,7 @@ delete_dlatch: return true; } -bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) +bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) { RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::Const val_cp, val_rp, val_rv, val_ep; @@ -452,6 +453,52 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\E"); } + if (sat && has_init) { + std::vector removed_sigbits; + + // for (auto &sigbit : sig_q.bits()) { + for (int position =0; position < GetSize(sig_d); position += 1) { + RTLIL::SigBit q_sigbit = sig_q[position]; + RTLIL::SigBit d_sigbit = sig_d[position]; + RTLIL::Const sigbit_init_val = val_init.extract(position); + + if ((!q_sigbit.wire) || (!d_sigbit.wire)) { + continue; + } + + char str[1024]; + sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", + log_id(d_sigbit.wire), + d_sigbit.offset, + sigbit_init_val.as_string().c_str(), + log_id(q_sigbit.wire), + q_sigbit.offset, + sigbit_init_val.as_string().c_str() + ); + log("Running: %s\n", str); + + log_flush(); + + pass->call(mod->design, str); + if (mod->design->scratchpad_get_bool("sat.success", false)) { + sprintf(str, "connect -set %s[%d] %s", + log_id(q_sigbit.wire), + q_sigbit.offset, + sigbit_init_val.as_string().c_str() + ); + log("Running: %s\n", str); + log_flush(); + pass->call(mod->design, str); + // mod->connect(q_sigbit, sigbit_init_val); + removed_sigbits.push_back(position); + } + } + + if (!removed_sigbits.empty()) { + return true; + } + } + return false; delete_dff: @@ -467,7 +514,7 @@ struct OptRmdffPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" opt_rmdff [-keepdc] [selection]\n"); + log(" opt_rmdff [-keepdc] [-sat] [selection]\n"); log("\n"); log("This pass identifies flip-flops with constant inputs and replaces them with\n"); log("a constant driver.\n"); @@ -479,6 +526,7 @@ struct OptRmdffPass : public Pass { log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n"); keepdc = false; + sat = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -486,6 +534,10 @@ struct OptRmdffPass : public Pass { keepdc = true; continue; } + if (args[argidx] == "-sat") { + sat = true; + continue; + } break; } extra_args(args, argidx, design); @@ -568,7 +620,7 @@ struct OptRmdffPass : public Pass { for (auto &id : dff_list) { if (module->cell(id) != nullptr && - handle_dff(module, module->cells_[id])) + handle_dff(module, module->cells_[id], this)) total_count++; } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index cbba738f0..453ae8cca 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1548,6 +1548,7 @@ struct SatPass : public Pass { print_proof_failed(); tip_failed: + design->scratchpad_set_bool("sat.success", false); if (verify) { log("\n"); log_error("Called with -verify and proof did fail!\n"); @@ -1555,6 +1556,7 @@ struct SatPass : public Pass { if (0) tip_success: + design->scratchpad_set_bool("sat.success", true); if (falsify) { log("\n"); log_error("Called with -falsify and proof did succeed!\n"); @@ -1628,6 +1630,7 @@ struct SatPass : public Pass { if (sathelper.solve()) { + design->scratchpad_set_bool("sat.success", false); if (max_undef) { log("SAT model found. maximizing number of undefs.\n"); sathelper.maximize_undefs(); @@ -1667,6 +1670,7 @@ struct SatPass : public Pass { } else { + design->scratchpad_set_bool("sat.success", true); if (sathelper.gotTimeout) goto timeout; if (rerun_counter) diff --git a/tests/opt/opt_ff_sat.v b/tests/opt/opt_ff_sat.v new file mode 100644 index 000000000..fc1e61980 --- /dev/null +++ b/tests/opt/opt_ff_sat.v @@ -0,0 +1,15 @@ +module top( + input clk, + input a, + output b + ); + reg b_reg; + initial begin + b_reg <= 0; + end + + assign b = b_reg; + always @(posedge clk) begin + b_reg <= a && b_reg; + end +endmodule diff --git a/tests/opt/opt_ff_sat.ys b/tests/opt/opt_ff_sat.ys new file mode 100644 index 000000000..13e4ad29b --- /dev/null +++ b/tests/opt/opt_ff_sat.ys @@ -0,0 +1,4 @@ +read_verilog opt_ff_sat.v +prep -flatten +opt_rmdff -sat +synth From 29a78267d7c84699bdcebfa87719b31d9b65909b Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 28 May 2019 15:45:04 +0200 Subject: [PATCH 291/927] Fix the regression --- passes/sat/sat.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 453ae8cca..4492fc2b7 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1554,13 +1554,14 @@ struct SatPass : public Pass { log_error("Called with -verify and proof did fail!\n"); } - if (0) + if (0) { tip_success: design->scratchpad_set_bool("sat.success", true); if (falsify) { log("\n"); log_error("Called with -falsify and proof did succeed!\n"); } + } } else { From 4a76b425cc0588ef5a8e46c06eecbfab869a35d9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 08:44:59 -0700 Subject: [PATCH 292/927] 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 293/927] 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 294/927] 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 295/927] 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 296/927] 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 297/927] 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 298/927] 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 299/927] 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 300/927] 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 301/927] 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 14bd40cd3d760e22eeaf6f9622e210412e2b93a6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 29 May 2019 18:57:03 +0200 Subject: [PATCH 302/927] Aded one more load of .conf to support change of prefix --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 05b28f33d..76dac48a5 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,10 @@ OS := $(shell uname -s) PREFIX ?= /usr/local INSTALL_SUDO := +ifneq ($(wildcard Makefile.conf),) +include Makefile.conf +endif + BINDIR := $(PREFIX)/bin LIBDIR := $(PREFIX)/lib DATDIR := $(PREFIX)/share/yosys From ecaa7856e96dad8de5ef162bb1c9c5814de5254f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:21:41 -0700 Subject: [PATCH 303/927] 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 304/927] 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 305/927] 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 306/927] 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 307/927] 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 308/927] 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 309/927] 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 310/927] 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 311/927] 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 312/927] 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 2faa1d0e80d213461d4403e36499aaaf1c8088b8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 30 May 2019 10:03:54 +0200 Subject: [PATCH 313/927] Enable Verific flag veri_elaborate_top_level_modules_having_interface_ports, fixes #1055 Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 21a1bbbbe..33d2ac7a8 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2016,6 +2016,9 @@ struct VerificPass : public Pass { // WARNING: instantiating unknown module 'XYZ' (VERI-1063) Message::SetMessageType("VERI-1063", VERIFIC_ERROR); + // https://github.com/YosysHQ/yosys/issues/1055 + RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ; + #ifndef DB_PRESERVE_INITIAL_VALUE # warning Verific was built without DB_PRESERVE_INITIAL_VALUE. #endif From fdfc18be91123e2939f134dafc12e1e0c1a82f7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 01:23:36 -0700 Subject: [PATCH 314/927] 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 315/927] 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 316/927] 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 317/927] 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 318/927] 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 319/927] 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 320/927] 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 321/927] 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 322/927] 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 90ec2cda4217115fb91206a712befb3e6fa797e5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 31 May 2019 09:28:51 +0200 Subject: [PATCH 323/927] Fix "tee" handling of log_streams Signed-off-by: Clifford Wolf --- passes/cmds/tee.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index ee96ace86..1a44bdaec 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -52,7 +52,9 @@ struct TeePass : public Pass { void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::vector backup_log_files, files_to_close; + std::vector backup_log_streams; int backup_log_verbose_level = log_verbose_level; + backup_log_streams = log_streams; backup_log_files = log_files; size_t argidx; @@ -60,6 +62,7 @@ struct TeePass : public Pass { { if (args[argidx] == "-q" && files_to_close.empty()) { log_files.clear(); + log_streams.clear(); continue; } if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) { @@ -89,6 +92,7 @@ struct TeePass : public Pass { for (auto cf : files_to_close) fclose(cf); log_files = backup_log_files; + log_streams = backup_log_streams; throw; } @@ -97,6 +101,7 @@ struct TeePass : public Pass { log_verbose_level = backup_log_verbose_level; log_files = backup_log_files; + log_streams = backup_log_streams; } } TeePass; From a6cadf6318f4eff6197d6c6f0e052c2417689f38 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Fri, 31 May 2019 12:24:12 +0200 Subject: [PATCH 324/927] Added support for parsing attributes on port connections. Signed-off-by: Maciej Kurc --- frontends/verilog/verilog_parser.y | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8244a8f44..82a1d9d39 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1532,27 +1532,27 @@ cell_port_list_rules: cell_port | cell_port_list_rules ',' cell_port; cell_port: - /* empty */ { + attr { AstNode *node = new AstNode(AST_ARGUMENT); astbuf2->children.push_back(node); } | - expr { + attr expr { AstNode *node = new AstNode(AST_ARGUMENT); astbuf2->children.push_back(node); - node->children.push_back($1); + node->children.push_back($2); } | - '.' TOK_ID '(' expr ')' { + attr '.' TOK_ID '(' expr ')' { AstNode *node = new AstNode(AST_ARGUMENT); - node->str = *$2; + node->str = *$3; astbuf2->children.push_back(node); - node->children.push_back($4); - delete $2; + node->children.push_back($5); + delete $3; } | - '.' TOK_ID '(' ')' { + attr '.' TOK_ID '(' ')' { AstNode *node = new AstNode(AST_ARGUMENT); - node->str = *$2; + node->str = *$3; astbuf2->children.push_back(node); - delete $2; + delete $3; }; always_stmt: From a379234f56753c3d72a6966c380ac6f83fde789c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 12:50:11 -0700 Subject: [PATCH 325/927] 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 326/927] 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 327/927] 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 328/927] 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 329/927] 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 330/927] 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 36120fcc3064d0be20d5b9871a804b226471ceae Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 2 Jun 2019 10:14:50 +0200 Subject: [PATCH 331/927] Only support Symbiotic EDA flavored Verific Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 33d2ac7a8..2bf99e58e 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -48,6 +48,14 @@ USING_YOSYS_NAMESPACE #include "VhdlUnits.h" #include "VeriLibrary.h" +#ifndef SYMBIOTIC_VERIFIC_API_VERSION +# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific." +#endif + +#if SYMBIOTIC_VERIFIC_API_VERSION < 1 +# error "Please update your version of Symbiotic EDA flavored Verific." +#endif + #ifdef __clang__ #pragma clang diagnostic pop #endif From 5739cf52650ccb3627868d9c9d7e02888efad12b Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Mon, 3 Jun 2019 09:12:51 +0200 Subject: [PATCH 332/927] Added tests for attributes Signed-off-by: Maciej Kurc --- tests/simple/attrib01_module.v | 21 ++++++++++++++ tests/simple/attrib02_port_decl.v | 25 +++++++++++++++++ tests/simple/attrib03_parameter.v | 28 +++++++++++++++++++ tests/simple/attrib04_net_var.v | 32 ++++++++++++++++++++++ tests/simple/attrib05_port_conn.v.DISABLED | 21 ++++++++++++++ tests/simple/attrib06_operator_suffix.v | 23 ++++++++++++++++ tests/simple/attrib07_func_call.v.DISABLED | 21 ++++++++++++++ tests/simple/attrib08_mod_inst.v | 22 +++++++++++++++ tests/simple/attrib09_case.v | 26 ++++++++++++++++++ 9 files changed, 219 insertions(+) create mode 100644 tests/simple/attrib01_module.v create mode 100644 tests/simple/attrib02_port_decl.v create mode 100644 tests/simple/attrib03_parameter.v create mode 100644 tests/simple/attrib04_net_var.v create mode 100644 tests/simple/attrib05_port_conn.v.DISABLED create mode 100644 tests/simple/attrib06_operator_suffix.v create mode 100644 tests/simple/attrib07_func_call.v.DISABLED create mode 100644 tests/simple/attrib08_mod_inst.v create mode 100644 tests/simple/attrib09_case.v diff --git a/tests/simple/attrib01_module.v b/tests/simple/attrib01_module.v new file mode 100644 index 000000000..adef34f5b --- /dev/null +++ b/tests/simple/attrib01_module.v @@ -0,0 +1,21 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output reg out; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= ~inp; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output wire out; + + bar bar_instance (clk, rst, inp, out); +endmodule + diff --git a/tests/simple/attrib02_port_decl.v b/tests/simple/attrib02_port_decl.v new file mode 100644 index 000000000..3505e7265 --- /dev/null +++ b/tests/simple/attrib02_port_decl.v @@ -0,0 +1,25 @@ +module bar(clk, rst, inp, out); + (* this_is_clock = 1 *) + input wire clk; + (* this_is_reset = 1 *) + input wire rst; + input wire inp; + (* an_output_register = 1*) + output reg out; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= ~inp; + +endmodule + +module foo(clk, rst, inp, out); + (* this_is_the_master_clock *) + input wire clk; + input wire rst; + input wire inp; + output wire out; + + bar bar_instance (clk, rst, inp, out); +endmodule + diff --git a/tests/simple/attrib03_parameter.v b/tests/simple/attrib03_parameter.v new file mode 100644 index 000000000..562d225cd --- /dev/null +++ b/tests/simple/attrib03_parameter.v @@ -0,0 +1,28 @@ +module bar(clk, rst, inp, out); + + (* bus_width *) + parameter WIDTH = 2; + + (* an_attribute_on_localparam = 55 *) + localparam INCREMENT = 5; + + input wire clk; + input wire rst; + input wire [WIDTH-1:0] inp; + output reg [WIDTH-1:0] out; + + always @(posedge clk) + if (rst) out <= 0; + else out <= inp + INCREMENT; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire [7:0] inp; + output wire [7:0] out; + + bar # (.WIDTH(8)) bar_instance (clk, rst, inp, out); +endmodule + diff --git a/tests/simple/attrib04_net_var.v b/tests/simple/attrib04_net_var.v new file mode 100644 index 000000000..8b5523406 --- /dev/null +++ b/tests/simple/attrib04_net_var.v @@ -0,0 +1,32 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output reg out; + + (* this_is_a_prescaler *) + reg [7:0] counter; + + (* temp_wire *) + wire out_val; + + always @(posedge clk) + counter <= counter + 1; + + assign out_val = inp ^ counter[4]; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= out_val; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output wire out; + + bar bar_instance (clk, rst, inp, out); +endmodule + diff --git a/tests/simple/attrib05_port_conn.v.DISABLED b/tests/simple/attrib05_port_conn.v.DISABLED new file mode 100644 index 000000000..e20e66319 --- /dev/null +++ b/tests/simple/attrib05_port_conn.v.DISABLED @@ -0,0 +1,21 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output reg out; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= ~inp; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output wire out; + + bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out); +endmodule + diff --git a/tests/simple/attrib06_operator_suffix.v b/tests/simple/attrib06_operator_suffix.v new file mode 100644 index 000000000..e21173c58 --- /dev/null +++ b/tests/simple/attrib06_operator_suffix.v @@ -0,0 +1,23 @@ +module bar(clk, rst, inp_a, inp_b, out); + input wire clk; + input wire rst; + input wire [7:0] inp_a; + input wire [7:0] inp_b; + output reg [7:0] out; + + always @(posedge clk) + if (rst) out <= 0; + else out <= inp_a + (* ripple_adder *) inp_b; + +endmodule + +module foo(clk, rst, inp_a, inp_b, out); + input wire clk; + input wire rst; + input wire [7:0] inp_a; + input wire [7:0] inp_b; + output wire [7:0] out; + + bar bar_instance (clk, rst, inp_a, inp_b, out); +endmodule + diff --git a/tests/simple/attrib07_func_call.v.DISABLED b/tests/simple/attrib07_func_call.v.DISABLED new file mode 100644 index 000000000..f55ef2316 --- /dev/null +++ b/tests/simple/attrib07_func_call.v.DISABLED @@ -0,0 +1,21 @@ +function [7:0] do_add; + input [7:0] inp_a; + input [7:0] inp_b; + + do_add = inp_a + inp_b; + +endfunction + +module foo(clk, rst, inp_a, inp_b, out); + input wire clk; + input wire rst; + input wire [7:0] inp_a; + input wire [7:0] inp_b; + output wire [7:0] out; + + always @(posedge clk) + if (rst) out <= 0; + else out <= do_add (* combinational_adder *) (inp_a, inp_b); + +endmodule + diff --git a/tests/simple/attrib08_mod_inst.v b/tests/simple/attrib08_mod_inst.v new file mode 100644 index 000000000..c5a32234e --- /dev/null +++ b/tests/simple/attrib08_mod_inst.v @@ -0,0 +1,22 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output reg out; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= ~inp; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output wire out; + + (* my_module_instance = 99 *) + bar bar_instance (clk, rst, inp, out); +endmodule + diff --git a/tests/simple/attrib09_case.v b/tests/simple/attrib09_case.v new file mode 100644 index 000000000..8551bf9d0 --- /dev/null +++ b/tests/simple/attrib09_case.v @@ -0,0 +1,26 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire [1:0] inp; + output reg [1:0] out; + + always @(inp) + (* full_case, parallel_case *) + case(inp) + 2'd0: out <= 2'd3; + 2'd1: out <= 2'd2; + 2'd2: out <= 2'd1; + 2'd3: out <= 2'd0; + endcase + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire [1:0] inp; + output wire [1:0] out; + + bar bar_instance (clk, rst, inp, out); +endmodule + From 9f44a7171528b90e85b2f33ef8823660fbd95609 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 09:23:43 -0700 Subject: [PATCH 333/927] 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 334/927] 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 335/927] 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 336/927] 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 337/927] 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 338/927] 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 339/927] 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 340/927] 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 0ad50332d94dfd4e08dcb8e862ccdd91b4262eb2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 19:36:09 -0700 Subject: [PATCH 341/927] Execute techmap and arith_map simultaneously --- 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 c20cac09b..a569c20f4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -229,11 +229,6 @@ struct SynthXilinxPass : public ScriptPass run("dff2dffe"); run("opt -full"); - if (!vpr || help_mode) - run("techmap -map +/xilinx/arith_map.v"); - else - run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here @@ -242,7 +237,12 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - run("techmap"); + 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"); + + run("opt -fast"); } From c9a0bac5413dff55e141deb4098b63ca4c62e5b1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 19:45:56 -0700 Subject: [PATCH 342/927] 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 02973474df5b0b88b1744baa9cec703d089ff007 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 20:04:47 -0700 Subject: [PATCH 343/927] Remove extra newline --- techlibs/xilinx/synth_xilinx.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a569c20f4..a293081f1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -242,7 +242,6 @@ struct SynthXilinxPass : public ScriptPass else run("techmap -map +/techmap.v +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - run("opt -fast"); } From b6e59741ae6e4ec57affb9ab168a9d08cdb6d04f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 20:21:41 -0700 Subject: [PATCH 344/927] 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 345/927] 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 346/927] 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 347/927] 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 348/927] 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 b79bd5b3ca086718e308c75cbece0b07bbe48733 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 4 Jun 2019 10:42:42 +0200 Subject: [PATCH 349/927] Moved tests that fail with Icarus Verilog to /tests/various. Those tests are just for parsing Verilog. Signed-off-by: Maciej Kurc --- tests/various/attrib05_port_conn.v | 21 +++++++++++++++++++++ tests/various/attrib05_port_conn.ys | 2 ++ tests/various/attrib07_func_call.v | 21 +++++++++++++++++++++ tests/various/attrib07_func_call.ys | 2 ++ 4 files changed, 46 insertions(+) create mode 100644 tests/various/attrib05_port_conn.v create mode 100644 tests/various/attrib05_port_conn.ys create mode 100644 tests/various/attrib07_func_call.v create mode 100644 tests/various/attrib07_func_call.ys diff --git a/tests/various/attrib05_port_conn.v b/tests/various/attrib05_port_conn.v new file mode 100644 index 000000000..e20e66319 --- /dev/null +++ b/tests/various/attrib05_port_conn.v @@ -0,0 +1,21 @@ +module bar(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output reg out; + + always @(posedge clk) + if (rst) out <= 1'd0; + else out <= ~inp; + +endmodule + +module foo(clk, rst, inp, out); + input wire clk; + input wire rst; + input wire inp; + output wire out; + + bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out); +endmodule + diff --git a/tests/various/attrib05_port_conn.ys b/tests/various/attrib05_port_conn.ys new file mode 100644 index 000000000..27a016733 --- /dev/null +++ b/tests/various/attrib05_port_conn.ys @@ -0,0 +1,2 @@ +# Read and parse Verilog file +read_verilog attrib05_port_conn.v diff --git a/tests/various/attrib07_func_call.v b/tests/various/attrib07_func_call.v new file mode 100644 index 000000000..f55ef2316 --- /dev/null +++ b/tests/various/attrib07_func_call.v @@ -0,0 +1,21 @@ +function [7:0] do_add; + input [7:0] inp_a; + input [7:0] inp_b; + + do_add = inp_a + inp_b; + +endfunction + +module foo(clk, rst, inp_a, inp_b, out); + input wire clk; + input wire rst; + input wire [7:0] inp_a; + input wire [7:0] inp_b; + output wire [7:0] out; + + always @(posedge clk) + if (rst) out <= 0; + else out <= do_add (* combinational_adder *) (inp_a, inp_b); + +endmodule + diff --git a/tests/various/attrib07_func_call.ys b/tests/various/attrib07_func_call.ys new file mode 100644 index 000000000..774827651 --- /dev/null +++ b/tests/various/attrib07_func_call.ys @@ -0,0 +1,2 @@ +# Read and parse Verilog file +read_verilog attrib07_func_call.v From c66d644b66f13d5cc54c78051bf97c0143d9940e Mon Sep 17 00:00:00 2001 From: Tux3 Date: Tue, 4 Jun 2019 10:45:41 +0200 Subject: [PATCH 350/927] README.md: Missing formatting for --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19306cda3..94ea9538f 100644 --- a/README.md +++ b/README.md @@ -413,7 +413,7 @@ Verilog Attributes and non-standard features $ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v' - Sized constants (the syntax ``'s?[bodh]``) support constant - expressions as . If the expression is not a simple identifier, it + expressions as ````. If the expression is not a simple identifier, it must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010`` - The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in From e260150321f3410056da64f83783b470caa89384 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 09:51:47 -0700 Subject: [PATCH 351/927] 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 352/927] 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 353/927] 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 354/927] 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 355/927] 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 356/927] 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 357/927] 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 dd3c333c0a206708ba2d821395fbf58a0e541f7b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 08:57:33 +0200 Subject: [PATCH 358/927] Remove yosys_banner() from python wrapper init, fixes #1056 Signed-off-by: Clifford Wolf --- misc/py_wrap_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 09f934040..9f2c72915 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -2060,7 +2060,6 @@ namespace YOSYS_PYTHON { Yosys::log_streams.push_back(&std::cout); Yosys::log_error_stderr = true; Yosys::yosys_setup(); - Yosys::yosys_banner(); } } From 8a6f9977f659d350cca936b45cb8b441d5a67eeb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 09:14:12 +0200 Subject: [PATCH 359/927] Suppress driver-driver conflict warning for unknown cell types, fixes #1065 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 7011d4602..cfb0f788a 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose) if (raw_bit.wire == nullptr) continue; auto bit = sigmap(raw_bit); - if (bit.wire == nullptr) + if (bit.wire == nullptr && ct_all.cell_known(cell->type)) driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); From 4190d7c09477f4bdd35cbd7bf5388254764b2321 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 09:26:44 +0200 Subject: [PATCH 360/927] Fix typo in fmcombine log message, fixes #1063 Signed-off-by: Clifford Wolf --- passes/sat/fmcombine.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index f64d99dc2..00c098542 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -332,7 +332,7 @@ struct FmcombinePass : public Pass { gate_cell = module->cell(gate_name); if (gate_cell == nullptr) - log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); + log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); } else { @@ -351,7 +351,7 @@ struct FmcombinePass : public Pass { if (!gold_cell->parameters.empty()) log_cmd_error("Gold cell has unresolved instance parameters.\n"); if (!gate_cell->parameters.empty()) - log_cmd_error("Gold cell has unresolved instance parameters.\n"); + log_cmd_error("Gate cell has unresolved instance parameters.\n"); FmcombineWorker worker(design, gold_cell->type, opts); worker.generate(); From 6cc60ffd67784fa74e3ccbf9c2c273ad610e14b2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 09:53:06 +0200 Subject: [PATCH 361/927] Indent fix Signed-off-by: Clifford Wolf --- passes/cmds/setundef.cc | 42 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index 5b43d528c..e46d0a1dc 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -404,29 +404,31 @@ struct SetundefPass : public Pass { initwires.insert(wire); } - for (int wire_types = 0; wire_types < 2; wire_types++) { - pool ffbitsToErase; - for (auto wire : module->wires()) { - if (wire->name[0] == (wire_types ? '\\' : '$')) { - next_wire: - continue; - } + for (int wire_types = 0; wire_types < 2; wire_types++) + { + pool ffbitsToErase; + for (auto wire : module->wires()) + { + if (wire->name[0] == (wire_types ? '\\' : '$')) { + next_wire: + continue; + } - for (auto bit : sigmap(wire)) - if (!ffbits.count(bit)) { - goto next_wire; - } + for (auto bit : sigmap(wire)) + if (!ffbits.count(bit)) { + goto next_wire; + } - for (auto bit : sigmap(wire)) { - ffbitsToErase.insert(bit); - } + for (auto bit : sigmap(wire)) { + ffbitsToErase.insert(bit); + } - initwires.insert(wire); - } - for (const auto &bit : ffbitsToErase) { - ffbits.erase(bit); - } - } + initwires.insert(wire); + } + for (const auto & bit : ffbitsToErase) { + ffbits.erase(bit); + } + } for (auto wire : initwires) { From b33176dafb03589952d3ac425e7cd8eeec61ea6a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 10:26:48 +0200 Subject: [PATCH 362/927] Major rewrite of wire selection in setundef -init Signed-off-by: Clifford Wolf --- passes/cmds/setundef.cc | 121 ++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index e46d0a1dc..3eedc86b8 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -393,53 +393,112 @@ struct SetundefPass : public Pass { ffbits.insert(bit); } - for (auto wire : module->wires()) + auto process_initwires = [&]() { - if (!wire->attributes.count("\\init")) - continue; + dict wire_weights; - for (auto bit : sigmap(wire)) - ffbits.erase(bit); + for (auto wire : initwires) + { + int weight = 0; - initwires.insert(wire); - } + for (auto bit : sigmap(wire)) + weight += ffbits.count(bit) ? +1 : -1; + + wire_weights[wire] = weight; + } + + initwires.sort([&](Wire *a, Wire *b) { return wire_weights.at(a) > wire_weights.at(b); }); + + for (auto wire : initwires) + { + Const &initval = wire->attributes["\\init"]; + initval.bits.resize(GetSize(wire), State::Sx); + + for (int i = 0; i < GetSize(wire); i++) { + SigBit bit = sigmap(SigBit(wire, i)); + if (initval[i] == State::Sx && ffbits.count(bit)) { + initval[i] = worker.next_bit(); + ffbits.erase(bit); + } + } + + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + } + + initwires.clear(); + }; for (int wire_types = 0; wire_types < 2; wire_types++) { - pool ffbitsToErase; - for (auto wire : module->wires()) + // prioritize wires that already have an init attribute + if (!ffbits.empty()) { - if (wire->name[0] == (wire_types ? '\\' : '$')) { - next_wire: + for (auto wire : module->wires()) + { + if (wire->name[0] == (wire_types ? '\\' : '$')) + continue; + + if (!wire->attributes.count("\\init")) + continue; + + Const &initval = wire->attributes["\\init"]; + initval.bits.resize(GetSize(wire), State::Sx); + + if (initval.is_fully_undef()) { + wire->attributes.erase("\\init"); + continue; + } + + for (int i = 0; i < GetSize(wire); i++) + if (initval[i] != State::Sx) + ffbits.erase(sigmap(SigBit(wire, i))); + + initwires.insert(wire); + } + + process_initwires(); + } + + // next consider wires that completely contain bits to be initialized + if (!ffbits.empty()) + { + for (auto wire : module->wires()) + { + if (wire->name[0] == (wire_types ? '\\' : '$')) + continue; + + for (auto bit : sigmap(wire)) + if (!ffbits.count(bit)) + goto next_wire; + + initwires.insert(wire); + + next_wire: continue; } - for (auto bit : sigmap(wire)) - if (!ffbits.count(bit)) { - goto next_wire; - } + process_initwires(); + } - for (auto bit : sigmap(wire)) { - ffbitsToErase.insert(bit); + // finally use whatever wire we can find. + if (!ffbits.empty()) + { + for (auto wire : module->wires()) + { + if (wire->name[0] == (wire_types ? '\\' : '$')) + continue; + + for (auto bit : sigmap(wire)) + if (ffbits.count(bit)) + initwires.insert(wire); } - initwires.insert(wire); - } - for (const auto & bit : ffbitsToErase) { - ffbits.erase(bit); + process_initwires(); } } - for (auto wire : initwires) - { - Const &initval = wire->attributes["\\init"]; - - for (int i = 0; i < GetSize(wire); i++) - if (GetSize(initval) <= i) - initval.bits.push_back(worker.next_bit()); - else if (initval.bits[i] == State::Sx) - initval.bits[i] = worker.next_bit(); - } + log_assert(ffbits.empty()); } module->rewrite_sigspecs(worker); From 03e0d3a17cf27858d16e0169614b6575c7dac538 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Wed, 5 Jun 2019 10:42:43 +0200 Subject: [PATCH 363/927] Fixed memory leak. Signed-off-by: Maciej Kurc --- frontends/verilog/verilog_parser.y | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 82a1d9d39..ccdab987f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1535,11 +1535,13 @@ cell_port: attr { AstNode *node = new AstNode(AST_ARGUMENT); astbuf2->children.push_back(node); + free_attr($1); } | attr expr { AstNode *node = new AstNode(AST_ARGUMENT); astbuf2->children.push_back(node); node->children.push_back($2); + free_attr($1); } | attr '.' TOK_ID '(' expr ')' { AstNode *node = new AstNode(AST_ARGUMENT); @@ -1547,12 +1549,14 @@ cell_port: astbuf2->children.push_back(node); node->children.push_back($5); delete $3; + free_attr($1); } | attr '.' TOK_ID '(' ')' { AstNode *node = new AstNode(AST_ARGUMENT); node->str = *$3; astbuf2->children.push_back(node); delete $3; + free_attr($1); }; always_stmt: From 45d1bdf83ae6d51628e917b66f1b6043c8a3baee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 10:21:57 -0700 Subject: [PATCH 364/927] 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 365/927] 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 366/927] 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 367/927] 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 368/927] 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 369/927] 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 370/927] 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 371/927] 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 372/927] 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 feb2ddb52bd7ca590596e22f73a5d3c153907391 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 14:08:14 -0700 Subject: [PATCH 373/927] Fix typo in opt_rmdff --- passes/opt/opt_rmdff.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 2abffa2a9..eeb992a3e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -292,8 +292,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_q = dff->getPort("\\Q"); sig_c = dff->getPort("\\C"); sig_e = dff->getPort("\\E"); - val_cp = RTLIL::Const(dff->type[6] == 'P', 1); - val_ep = RTLIL::Const(dff->type[7] == 'P', 1); + val_cp = RTLIL::Const(dff->type[7] == 'P', 1); + val_ep = RTLIL::Const(dff->type[8] == 'P', 1); } else if (dff->type == "$ff") { sig_d = dff->getPort("\\D"); From dd134914cc93f7506504ad95aad438a468bb0fe8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 14:16:24 -0700 Subject: [PATCH 374/927] Error out if no top module given before 'sim' --- passes/sat/sim.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 53e248adf..4c3022c70 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -88,6 +88,8 @@ struct SimInstance SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : shared(shared), module(module), instance(instance), parent(parent), sigmap(module) { + log_assert(module); + if (parent) { log_assert(parent->children.count(instance) == 0); parent->children[instance] = this; @@ -848,6 +850,9 @@ struct SimPass : public Pass { if (design->full_selection()) { top_mod = design->top_module(); + + if (!top_mod) + log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n"); } else { auto mods = design->selected_whole_modules(); if (GetSize(mods) != 1) From fd8ef128bfdc01b6bcf90ca5a3426aac22811161 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 14:21:44 -0700 Subject: [PATCH 375/927] Missing doc for -tech xilinx in shregmap --- passes/techmap/shregmap.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 75eedfbcc..21dfe9619 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -606,6 +606,9 @@ struct ShregmapPass : public Pass { log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); log("\n"); + log(" -tech xilinx\n"); + log(" map to xilinx dynamic-length shift registers.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From f3a26730b610e1d80ca408e6913311bdfc82914c Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 6 Jun 2019 10:03:03 +0000 Subject: [PATCH 376/927] ECP5: implement all Diamond I/O buffer primitives. --- techlibs/ecp5/cells_map.v | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 6ab4b69f2..f6c71a03d 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -47,6 +47,21 @@ 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 +// 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 +module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule +module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule +module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +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 From 88f59770932720cfc1e987c98e53faedd7388ed8 Mon Sep 17 00:00:00 2001 From: tux3 Date: Wed, 5 Jun 2019 00:47:54 +0200 Subject: [PATCH 377/927] SystemVerilog support for implicit named port connections This is the `foo foo(.port1, .port2);` SystemVerilog syntax introduced in IEEE1800-2005. --- frontends/verilog/verilog_parser.y | 26 +++++++++++++++++--------- tests/simple/run-test.sh | 3 ++- tests/tools/autotest.sh | 15 +++++++++++++-- tests/various/implicit_ports.sv | 19 +++++++++++++++++++ tests/various/implicit_ports.ys | 8 ++++++++ 5 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 tests/various/implicit_ports.sv create mode 100644 tests/various/implicit_ports.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8244a8f44..983445011 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -154,7 +154,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list +%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list named_port %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1541,18 +1541,26 @@ cell_port: astbuf2->children.push_back(node); node->children.push_back($1); } | - '.' TOK_ID '(' expr ')' { - AstNode *node = new AstNode(AST_ARGUMENT); - node->str = *$2; - astbuf2->children.push_back(node); - node->children.push_back($4); - delete $2; + named_port '(' ')' | // not connected + named_port '(' expr ')' { + ($1)->children.push_back($3); } | - '.' TOK_ID '(' ')' { + named_port { + // SV implied port + if (!sv_mode) + frontend_verilog_yyerror("Implicit .name port connection in port list (%s). This is not supported unless read_verilog is called with -sv!", $1->str.c_str()); + auto id_node = new AstNode(AST_IDENTIFIER); + id_node->str = ($1)->str; + ($1)->children.push_back(id_node); + }; + +named_port: + '.' TOK_ID { AstNode *node = new AstNode(AST_ARGUMENT); node->str = *$2; - astbuf2->children.push_back(node); delete $2; + astbuf2->children.push_back(node); + $$ = node; }; always_stmt: diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh index aaa1cf940..967ac49f2 100755 --- a/tests/simple/run-test.sh +++ b/tests/simple/run-test.sh @@ -17,4 +17,5 @@ if ! which iverilog > /dev/null ; then exit 1 fi -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v +shopt -s nullglob +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 920474a84..0a511f29c 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -89,6 +89,13 @@ done compile_and_run() { exe="$1"; output="$2"; shift 2 + ext=${1##*.} + if [ "$ext" == "sv" ]; then + language_gen="-g2012" + else + language_gen="-g2005" + fi + if $use_modelsim; then altver=$( ls -v /opt/altera/ | grep '^[0-9]' | tail -n1; ) /opt/altera/$altver/modelsim_ase/bin/vlib work @@ -99,7 +106,7 @@ compile_and_run() { /opt/Xilinx/Vivado/$xilver/bin/xvlog $xinclude_opts -d outfile=\"$output\" "$@" /opt/Xilinx/Vivado/$xilver/bin/xelab -R work.testbench else - iverilog $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" + iverilog $language_gen $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" vvp -n "$exe" fi } @@ -110,7 +117,7 @@ for fn do bn=${fn%.*} ext=${fn##*.} - if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then + if [[ "$ext" != "v" ]] && [[ "$ext" != "sv" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then echo "Invalid argument: $fn" >&2 exit 1 fi @@ -123,6 +130,10 @@ do echo -n "Test: $bn " fi + if [ "$ext" == sv ]; then + frontend="$frontend -sv" + fi + rm -f ${bn}.{err,log,skip} mkdir -p ${bn}.out rm -rf ${bn}.out/* diff --git a/tests/various/implicit_ports.sv b/tests/various/implicit_ports.sv new file mode 100644 index 000000000..6a766bd51 --- /dev/null +++ b/tests/various/implicit_ports.sv @@ -0,0 +1,19 @@ +// Test implicit port connections +module alu (input [2:0] a, input [2:0] b, input cin, output cout, output [2:0] result); + assign cout = cin; + assign result = a + b; +endmodule + +module named_ports(output [2:0] alu_result, output cout); + wire [2:0] a = 3'b010, b = 3'b100; + wire cin = 1; + + alu alu ( + .a(a), + .b, // Implicit connection is equivalent to .b(b) + .cin(), // Explicitely unconnected + .cout(cout), + .result(alu_result) + ); +endmodule + diff --git a/tests/various/implicit_ports.ys b/tests/various/implicit_ports.ys new file mode 100644 index 000000000..7b4764921 --- /dev/null +++ b/tests/various/implicit_ports.ys @@ -0,0 +1,8 @@ +read_verilog -sv implicit_ports.sv +proc; opt + +flatten +select -module named_ports + +sat -verify -prove alu_result 6 +sat -verify -set-all-undef cout From 7bd1c664a6f0d9a20a2f3f0c0f136403918afacf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 10:51:02 -0700 Subject: [PATCH 378/927] Initial adaptation of muxpack from shregmap --- passes/techmap/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cf9e198ad..561636080 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,6 +37,7 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o +OBJS += passes/techmap/muxpack.o endif GENFILES += passes/techmap/techmap.inc From 543dd11c7e46f9c88bd1f0d21474bac95d1ab6d1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 11:03:45 -0700 Subject: [PATCH 379/927] Missing file --- passes/techmap/muxpack.cc | 232 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 passes/techmap/muxpack.cc diff --git a/passes/techmap/muxpack.cc b/passes/techmap/muxpack.cc new file mode 100644 index 000000000..4945affb0 --- /dev/null +++ b/passes/techmap/muxpack.cc @@ -0,0 +1,232 @@ +/* + * 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; + + 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") && !cell->get_bool_attribute("\\keep")) + { + SigSpec a_sig = sigmap(cell->getPort("\\A")); + 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; + + 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 it : sig_chain_next) + { + for (auto bit : it.first.bits()) + if (sigbit_with_non_chain_users.count(bit)) + goto start_cell; + + if (sig_chain_prev.count(it.first) != 0) + { + Cell *c1 = sig_chain_prev.at(it.first); + Cell *c2 = it.second; + + if (c1->type != c2->type) + goto start_cell; + + if (c1->parameters != c2->parameters) + goto start_cell; + + continue; + } + + start_cell: + chain_start_cells.insert(it.second); + } + } + + 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* cursor_cell = chain[cursor+i]; + b_sig.append(cursor_cell->getPort("\\B")); + s_sig.append(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(); + } + + 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", "TODO") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" muxpack [options] [selection]\n"); + log("\n"); + log("TODO"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing MUXPACK pass (TODO).\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 3e76e3a6fa4355e7223b10bba394f986d6821551 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 11:54:38 -0700 Subject: [PATCH 380/927] Add tests, fix for != --- passes/techmap/muxpack.cc | 41 +++++++++++++++++++++++++++++--------- tests/various/muxpack.v | 36 +++++++++++++++++++++++++++++++++ tests/various/muxpack.ys | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 tests/various/muxpack.v create mode 100644 tests/various/muxpack.ys diff --git a/passes/techmap/muxpack.cc b/passes/techmap/muxpack.cc index 4945affb0..54c52150a 100644 --- a/passes/techmap/muxpack.cc +++ b/passes/techmap/muxpack.cc @@ -54,14 +54,21 @@ struct MuxpackWorker if (cell->type.in("$mux") && !cell->get_bool_attribute("\\keep")) { SigSpec a_sig = sigmap(cell->getPort("\\A")); + SigSpec 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 + else sig_chain_next[a_sig] = cell; + 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; + sig_chain_prev[y_sig] = cell; continue; } @@ -77,13 +84,22 @@ struct MuxpackWorker { for (auto it : sig_chain_next) { + SigSpec next_sig; + for (auto bit : it.first.bits()) if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - if (sig_chain_prev.count(it.first) != 0) + next_sig = it.second->getPort("\\A"); + if (sig_chain_prev.count(next_sig) == 0) { + next_sig = it.second->getPort("\\B"); + if (sig_chain_prev.count(next_sig) == 0) + next_sig = SigSpec(); + } + + if (!next_sig.empty()) { - Cell *c1 = sig_chain_prev.at(it.first); + Cell *c1 = sig_chain_prev.at(next_sig); Cell *c2 = it.second; if (c1->type != c2->type) @@ -149,15 +165,22 @@ struct MuxpackWorker pmux_count += 1; first_cell->type = "$pmux"; - SigSpec b_sig = first_cell->getPort("\\B"); - SigSpec s_sig = first_cell->getPort("\\S"); + SigSpec b_sig = first_cell->getPort("\\B"); + SigSpec s_sig = first_cell->getPort("\\S"); for (int i = 1; i < cases; i++) { - Cell* cursor_cell = chain[cursor+i]; - b_sig.append(cursor_cell->getPort("\\B")); - s_sig.append(cursor_cell->getPort("\\S")); + 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); diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v new file mode 100644 index 000000000..abc87ba44 --- /dev/null +++ b/tests/various/muxpack.v @@ -0,0 +1,36 @@ +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 diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys new file mode 100644 index 000000000..58c01cf05 --- /dev/null +++ b/tests/various/muxpack.ys @@ -0,0 +1,42 @@ +read_verilog muxpack.v +design -save read +hierarchy -top mux_if_unbal_4_1 +prep +design -save gold +muxpack +opt +stat +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 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 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 5d4eca5a298d2f98de220cfd0efe5452ab4052d8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 11:59:41 -0700 Subject: [PATCH 381/927] Add a few more special case tests --- tests/various/muxpack.v | 23 +++++++++++++++++++++++ tests/various/muxpack.ys | 28 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index abc87ba44..333908fcb 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -34,3 +34,26 @@ always @* 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_5_3_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 diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 58c01cf05..174eea74b 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -40,3 +40,31 @@ 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 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_5_3_missing +prep +design -save gold +muxpack +opt +stat +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 b8620f7b3dde4460e5a8ed3ea7fd7aef54aa7da1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:03:44 -0700 Subject: [PATCH 382/927] One more and tidy up --- tests/various/muxpack.v | 20 ++++++++++++++------ tests/various/muxpack.ys | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index 333908fcb..c2c2537a0 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -5,7 +5,6 @@ always @* 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); @@ -17,7 +16,6 @@ always @* begin 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); @@ -32,7 +30,6 @@ always @* 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); @@ -44,10 +41,9 @@ always @* begin if (s == 3) o <= i[3*W+:W]; if (s == 4) o <= i[4*W+:W]; end - endmodule -module mux_if_unbal_5_3_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); +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]; @@ -55,5 +51,17 @@ always @* begin 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 + + diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 174eea74b..a967ddfef 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -56,7 +56,21 @@ 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_missing +hierarchy -top mux_if_unbal_4_1_missing +prep +design -save gold +muxpack +opt +stat +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 From 030f1d30e9cd04b4412114bdc93a15a39a4597c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:04:42 -0700 Subject: [PATCH 383/927] Add to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 36b64e111..e67d9c903 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass + - Added "muxpack" pass - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From 3dd0682f298cec18f60c2d9da6417e287a385dd4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:11:59 -0700 Subject: [PATCH 384/927] Update doc --- passes/techmap/muxpack.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/passes/techmap/muxpack.cc b/passes/techmap/muxpack.cc index 54c52150a..9668b0d43 100644 --- a/passes/techmap/muxpack.cc +++ b/passes/techmap/muxpack.cc @@ -218,19 +218,20 @@ struct MuxpackWorker }; struct MuxpackPass : public Pass { - MuxpackPass() : Pass("muxpack", "TODO") { } + MuxpackPass() : Pass("muxpack", "$mux cell cascades to $pmux") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" muxpack [options] [selection]\n"); + log(" muxpack [selection]\n"); log("\n"); - log("TODO"); + log("This pass converts cascaded chains of $mux cells (e.g. those created by if-else\n"); + log("constructs) into $pmux cells.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing MUXPACK pass (TODO).\n"); + log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) From 83450a94898321a239f67f92e05fb9a246f4dd6d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:15:13 -0700 Subject: [PATCH 385/927] Move muxpack from passes/techmap to passes/opt --- passes/opt/Makefile.inc | 1 + passes/{techmap => opt}/muxpack.cc | 0 passes/techmap/Makefile.inc | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename passes/{techmap => opt}/muxpack.cc (100%) 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 diff --git a/passes/techmap/muxpack.cc b/passes/opt/muxpack.cc similarity index 100% rename from passes/techmap/muxpack.cc rename to passes/opt/muxpack.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 561636080..cf9e198ad 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,7 +37,6 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o -OBJS += passes/techmap/muxpack.o endif GENFILES += passes/techmap/techmap.inc From 705388eb24022d2a310ae72cd81e67a2f0ce7586 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:44:06 -0700 Subject: [PATCH 386/927] Add non exclusive test --- tests/various/muxpack.v | 20 ++++++++++++++++++++ tests/various/muxpack.ys | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index c2c2537a0..e847fef27 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -64,4 +64,24 @@ always @* begin 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=4, parameter W=1) (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 diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index a967ddfef..178860b88 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -6,6 +6,7 @@ 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 @@ -20,6 +21,7 @@ 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 @@ -34,6 +36,7 @@ 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 @@ -48,6 +51,7 @@ 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 @@ -62,6 +66,7 @@ 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 @@ -76,6 +81,37 @@ 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 From d2172c6846f710e9a362708e3308dd302110deb2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:44:50 -0700 Subject: [PATCH 387/927] Non chain user check using next_sig --- passes/opt/muxpack.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 9668b0d43..963083107 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -84,19 +84,17 @@ struct MuxpackWorker { for (auto it : sig_chain_next) { - SigSpec next_sig; - - for (auto bit : it.first.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - next_sig = it.second->getPort("\\A"); + SigSpec next_sig = it.second->getPort("\\A"); if (sig_chain_prev.count(next_sig) == 0) { next_sig = it.second->getPort("\\B"); if (sig_chain_prev.count(next_sig) == 0) next_sig = SigSpec(); } + for (auto bit : next_sig.bits()) + if (sigbit_with_non_chain_users.count(bit)) + goto start_cell; + if (!next_sig.empty()) { Cell *c1 = sig_chain_prev.at(next_sig); From 978fda94f684185a7d583a3865b7a68459344e46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:46:42 -0700 Subject: [PATCH 388/927] Fix spacing --- passes/opt/muxpack.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 963083107..cb13a45b0 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -43,9 +43,8 @@ struct MuxpackWorker for (auto wire : module->wires()) { if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) { + for (auto bit : sigmap(wire)) sigbit_with_non_chain_users.insert(bit); - } } } @@ -58,8 +57,8 @@ struct MuxpackWorker 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); + for (auto a_bit : a_sig.bits()) + sigbit_with_non_chain_users.insert(a_bit); else sig_chain_next[a_sig] = cell; @@ -70,7 +69,7 @@ struct MuxpackWorker sig_chain_next[b_sig] = cell; sig_chain_prev[y_sig] = cell; - continue; + continue; } for (auto conn : cell->connections()) @@ -182,7 +181,7 @@ struct MuxpackWorker first_cell->setPort("\\B", b_sig); first_cell->setPort("\\S", s_sig); - first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); + first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); first_cell->setPort("\\Y", last_cell->getPort("\\Y")); cursor += cases; From dc7b8c4b942f9d9bc61a87a81291244d0b73843b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:56:34 -0700 Subject: [PATCH 389/927] More cleanup --- passes/opt/muxpack.cc | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index cb13a45b0..ae4b67db2 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -37,6 +37,7 @@ struct MuxpackWorker dict sig_chain_prev; pool sigbit_with_non_chain_users; pool chain_start_cells; + pool candidate_cells; void make_sig_chain_next_prev() { @@ -59,14 +60,18 @@ struct MuxpackWorker if (sig_chain_next.count(a_sig)) for (auto a_bit : a_sig.bits()) sigbit_with_non_chain_users.insert(a_bit); - else + else { sig_chain_next[a_sig] = cell; + candidate_cells.insert(cell); + } if (sig_chain_next.count(b_sig)) for (auto b_bit : b_sig.bits()) sigbit_with_non_chain_users.insert(b_bit); - else + else { sig_chain_next[b_sig] = cell; + candidate_cells.insert(cell); + } sig_chain_prev[y_sig] = cell; continue; @@ -81,35 +86,34 @@ struct MuxpackWorker void find_chain_start_cells() { - for (auto it : sig_chain_next) + for (auto cell : candidate_cells) { - SigSpec next_sig = it.second->getPort("\\A"); + SigSpec next_sig = cell->getPort("\\A"); if (sig_chain_prev.count(next_sig) == 0) { - next_sig = it.second->getPort("\\B"); + next_sig = cell->getPort("\\B"); if (sig_chain_prev.count(next_sig) == 0) - next_sig = SigSpec(); + goto start_cell; } - for (auto bit : next_sig.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - if (!next_sig.empty()) { + 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 = it.second; + Cell *c2 = cell; if (c1->type != c2->type) goto start_cell; if (c1->parameters != c2->parameters) goto start_cell; - - continue; } + continue; + start_cell: - chain_start_cells.insert(it.second); + chain_start_cells.insert(cell); } } @@ -197,6 +201,7 @@ struct MuxpackWorker sig_chain_next.clear(); sig_chain_prev.clear(); chain_start_cells.clear(); + candidate_cells.clear(); } MuxpackWorker(Module *module) : From ccdf989025e57da7dfd5ab609676ebe3cfb2c2d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 13:51:22 -0700 Subject: [PATCH 390/927] Support cascading $pmux.A with $mux.A and $mux.B --- passes/opt/muxpack.cc | 42 ++++++++++++++++++++++++---------------- tests/various/muxpack.v | 25 ++++++++++++++++++++++++ tests/various/muxpack.ys | 15 ++++++++++++++ 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ae4b67db2..f9e5c8f09 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -51,10 +51,12 @@ struct MuxpackWorker for (auto cell : module->cells()) { - if (cell->type.in("$mux") && !cell->get_bool_attribute("\\keep")) + if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep")) { SigSpec a_sig = sigmap(cell->getPort("\\A")); - SigSpec b_sig = sigmap(cell->getPort("\\B")); + 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)) @@ -65,12 +67,14 @@ struct MuxpackWorker candidate_cells.insert(cell); } - 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); + 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; @@ -88,10 +92,16 @@ struct MuxpackWorker { 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) { - next_sig = cell->getPort("\\B"); - 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; } @@ -103,10 +113,7 @@ struct MuxpackWorker Cell *c1 = sig_chain_prev.at(next_sig); Cell *c2 = cell; - if (c1->type != c2->type) - goto start_cell; - - if (c1->parameters != c2->parameters) + if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) goto start_cell; } @@ -220,15 +227,16 @@ struct MuxpackWorker }; struct MuxpackPass : public Pass { - MuxpackPass() : Pass("muxpack", "$mux cell cascades to $pmux") { } + 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 $mux cells (e.g. those created by if-else\n"); - log("constructs) into $pmux cells.\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 diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index e847fef27..fe0150532 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -85,3 +85,28 @@ always @* begin if (s == 0) o <= i[2*W+:W]; end endmodule + +module mux_case_unbal_7_7#(parameter N=7, 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 index 178860b88..4dcb9ed89 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -118,3 +118,18 @@ 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_7_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 0a66720f6f67b087fe6342d01d45944506240942 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:01:42 -0700 Subject: [PATCH 391/927] Fix warnings --- tests/various/muxpack.v | 4 ++-- tests/various/muxpack.ys | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index fe0150532..7c189fff8 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -74,7 +74,7 @@ always @* else o <= {W{1'bx}}; endmodule -module mux_if_unbal_5_3_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); +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]; @@ -86,7 +86,7 @@ always @* begin end endmodule -module mux_case_unbal_7_7#(parameter N=7, parameter W=7) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o); +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) diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 4dcb9ed89..0c5b82818 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -120,7 +120,7 @@ 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_7_7 +hierarchy -top mux_case_unbal_8_7 prep design -save gold muxpack From 5c277c6325b78bfe18cf294b63ea69ff272e69c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:21:34 -0700 Subject: [PATCH 392/927] Fix and test for balanced case --- passes/opt/muxpack.cc | 24 ++++++++++++++---------- tests/various/muxpack.v | 26 ++++++++++++++++++++++++++ tests/various/muxpack.ys | 15 +++++++++++++++ 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index f9e5c8f09..8c4db4e4d 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -94,23 +94,27 @@ struct MuxpackWorker { 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 + 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)) goto start_cell; } + else log_abort(); { - for (auto bit : next_sig.bits()) + for (auto bit : a_sig.bits()) if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - Cell *c1 = sig_chain_prev.at(next_sig); + Cell *c1 = sig_chain_prev.at(a_sig); Cell *c2 = cell; if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index 7c189fff8..f1bd5ea8e 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -110,3 +110,29 @@ 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 0c5b82818..9ea743b9f 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -133,3 +133,18 @@ 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 7166dbe418420bf8f0696b21bff22d5f66a4cc8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:35:38 -0700 Subject: [PATCH 393/927] 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 394/927] 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 395/927] 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 396/927] $__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 d018e026142b9903a6f51b0a76ab109e86c4c59b Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Fri, 7 Jun 2019 09:47:33 +0200 Subject: [PATCH 397/927] remove boost/log/exceptions.hpp from wrapper generator --- misc/py_wrap_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 9f2c72915..9e5727499 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -2026,7 +2026,6 @@ def gen_wrappers(filename, debug_level_ = 0): #include #include #include -#include USING_YOSYS_NAMESPACE From a0b57f2a6ffae3b5770e38bf5a9af0df50db8522 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 11:46:16 +0200 Subject: [PATCH 398/927] Cleanup tux3-implicit_named_connection Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 2 +- tests/{various => simple}/implicit_ports.sv | 5 +---- tests/various/implicit_ports.ys | 8 -------- 3 files changed, 2 insertions(+), 13 deletions(-) rename tests/{various => simple}/implicit_ports.sv (78%) delete mode 100644 tests/various/implicit_ports.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2fffc7536..6d3afed0e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -154,7 +154,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list named_port +%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr diff --git a/tests/various/implicit_ports.sv b/tests/simple/implicit_ports.sv similarity index 78% rename from tests/various/implicit_ports.sv rename to tests/simple/implicit_ports.sv index 6a766bd51..8b0a6f386 100644 --- a/tests/various/implicit_ports.sv +++ b/tests/simple/implicit_ports.sv @@ -4,10 +4,8 @@ module alu (input [2:0] a, input [2:0] b, input cin, output cout, output [2:0] r assign result = a + b; endmodule -module named_ports(output [2:0] alu_result, output cout); - wire [2:0] a = 3'b010, b = 3'b100; +module named_ports(input [2:0] a, b, output [2:0] alu_result, output cout); wire cin = 1; - alu alu ( .a(a), .b, // Implicit connection is equivalent to .b(b) @@ -16,4 +14,3 @@ module named_ports(output [2:0] alu_result, output cout); .result(alu_result) ); endmodule - diff --git a/tests/various/implicit_ports.ys b/tests/various/implicit_ports.ys deleted file mode 100644 index 7b4764921..000000000 --- a/tests/various/implicit_ports.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog -sv implicit_ports.sv -proc; opt - -flatten -select -module named_ports - -sat -verify -prove alu_result 6 -sat -verify -set-all-undef cout From 211d85cfcc1ae701bb9392347bcbb9750e3045b0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 12:41:09 +0200 Subject: [PATCH 399/927] Fixes and cleanups in AST_TECALL handling Signed-off-by: Clifford Wolf --- frontends/ast/ast.h | 1 - frontends/ast/genrtlil.cc | 32 +++++++++++++++++++++++++- frontends/ast/simplify.cc | 47 +++------------------------------------ kernel/log.cc | 8 +++---- 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 93997ab86..b8cde060e 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -234,7 +234,6 @@ namespace AST bool mem2reg_check(pool &mem2reg_set); void mem2reg_remove(pool &mem2reg_set, vector &delnodes); void meminfo(int &mem_width, int &mem_size, int &addr_bits); - bool check_elab_tasks(void); // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 60a087282..32ed401eb 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -858,7 +858,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENVAR: case AST_GENFOR: case AST_GENBLOCK: - case AST_TECALL: case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: @@ -1576,6 +1575,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) delete always; } break; + case AST_TECALL: { + int sz = children.size(); + if (str == "$info") { + if (sz > 0) + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_info(filename, linenum, "\n"); + } else if (str == "$warning") { + if (sz > 0) + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_warning(filename, linenum, "\n"); + } else if (str == "$error") { + if (sz > 0) + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "\n"); + } else if (str == "$fatal") { + // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() + // if no parameter is given, default value is 1 + // dollar_finish(sz ? children[0] : 1); + // perhaps create & use log_file_fatal() + if (sz > 0) + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "FATAL.\n"); + } else { + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); + } + } break; + case AST_FCALL: { if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 66fd243d3..e947125bf 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1146,8 +1146,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_GENFOR) { for (size_t i = 0; i < buf->children.size(); i++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } } else { @@ -1260,8 +1259,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } for (size_t i = 0; i < buf->children.size(); i++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -1340,8 +1338,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } for (size_t i = 0; i < buf->children.size(); i++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -2971,44 +2968,6 @@ static void mark_memories_assign_lhs_complex(dict> & } } -// handle $info(), $warning(), $error(), $fatal() -// we don't do that in simplify() because we don't know -bool AstNode::check_elab_tasks(void) -{ - if (type == AST_TECALL) { - int sz = children.size(); - if (str == "$info") { - if (sz > 0) - log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_info(filename, linenum, "\n"); - } else if (str == "$warning") { - if (sz > 0) - log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_warning(filename, linenum, "\n"); - } else if (str == "$error") { - if (sz > 0) - log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_error(filename, linenum, "\n"); - } else if (str == "$fatal") { - // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() - // if no parameter is given, default value is 1 - // dollar_finish(sz ? children[0] : 1); - // perhaps create & use log_file_fatal() - if (sz > 0) - log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); - else - log_file_error(filename, linenum, "FATAL.\n"); - } else { - log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); - } - return true; - } - return false; - -} // find memories that should be replaced by registers void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg_places, dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) diff --git a/kernel/log.cc b/kernel/log.cc index 9ce952cae..a7820950c 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -277,7 +277,7 @@ void log_file_warning(const std::string &filename, int lineno, va_list ap; va_start(ap, format); std::string prefix = stringf("%s:%d: Warning: ", - filename.c_str(), lineno); + filename.c_str(), lineno); logv_warning_with_prefix(prefix.c_str(), format, ap); va_end(ap); } @@ -287,9 +287,9 @@ void log_file_info(const std::string &filename, int lineno, { va_list ap; va_start(ap, format); - std::string prefix = stringf("%s:%d: Info: ", - filename.c_str(), lineno); - logv_warning_with_prefix(prefix.c_str(), format, ap); + std::string fmt = stringf("%s:%d: Info: %s", + filename.c_str(), lineno, format); + logv(fmt.c_str(), ap); va_end(ap); } From f01a61f093528e5111e5dac8aedbf8c7c468be1c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 13:12:25 +0200 Subject: [PATCH 400/927] Rename implicit_ports.sv test to implicit_ports.v Signed-off-by: Clifford Wolf --- tests/simple/{implicit_ports.sv => implicit_ports.v} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/simple/{implicit_ports.sv => implicit_ports.v} (100%) diff --git a/tests/simple/implicit_ports.sv b/tests/simple/implicit_ports.v similarity index 100% rename from tests/simple/implicit_ports.sv rename to tests/simple/implicit_ports.v From fe4394fb9aacfaee840d2c72b88c5da666fbcb28 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 08:30:39 -0700 Subject: [PATCH 401/927] 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 30abdaf3b2e0c3f21af0a7fdf2dc91ea59c7d54f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 08:30:39 -0700 Subject: [PATCH 402/927] 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 0f6e914ef63d06ae77b54d246b61118c19647f26 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 08:34:58 -0700 Subject: [PATCH 403/927] Another muxpack test --- tests/various/muxpack.v | 17 +++++++++++++++++ tests/various/muxpack.ys | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index f1bd5ea8e..41dfed396 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -136,3 +136,20 @@ always @* else o <= i[7*W+:W]; endmodule + +module mux_if_bal_5_1 #(parameter N=5, 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] == 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 + o <= i[4*W+:W]; +endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 9ea743b9f..dd3c143d8 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -148,3 +148,18 @@ 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_5_1 +prep +design -save gold +muxpack +opt +stat +select -assert-count 2 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 1b113a05742377f5b18d52bc5bf50b1991e88c19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:05:25 -0700 Subject: [PATCH 404/927] Add symbols to AIGER test inputs for ABC --- tests/aiger/and.aig | 3 --- tests/aiger/{and.aag => and_.aag} | 3 +++ tests/aiger/and_.aig | 5 +++++ tests/aiger/buffer.aag | 2 ++ tests/aiger/buffer.aig | 2 ++ tests/aiger/cnt1.aag | 1 + tests/aiger/cnt1.aig | 1 + tests/aiger/cnt1e.aag | 1 + tests/aiger/cnt1e.aig | 3 ++- tests/aiger/false.aag | 1 + tests/aiger/false.aig | 1 + tests/aiger/inverter.aag | 2 ++ tests/aiger/inverter.aig | 2 ++ tests/aiger/notcnt1e.aag | 1 + tests/aiger/notcnt1e.aig | 3 ++- tests/aiger/or.aig | 3 --- tests/aiger/{or.aag => or_.aag} | 3 +++ tests/aiger/or_.aig | 5 +++++ tests/aiger/toggle.aag | 2 ++ tests/aiger/toggle.aig | 2 ++ tests/aiger/true.aag | 1 + tests/aiger/true.aig | 1 + 22 files changed, 40 insertions(+), 8 deletions(-) delete mode 100644 tests/aiger/and.aig rename tests/aiger/{and.aag => and_.aag} (55%) create mode 100644 tests/aiger/and_.aig delete mode 100644 tests/aiger/or.aig rename tests/aiger/{or.aag => or_.aag} (55%) create mode 100644 tests/aiger/or_.aig diff --git a/tests/aiger/and.aig b/tests/aiger/and.aig deleted file mode 100644 index da0fa0719..000000000 --- a/tests/aiger/and.aig +++ /dev/null @@ -1,3 +0,0 @@ -aig 3 2 0 1 1 -6 - \ No newline at end of file diff --git a/tests/aiger/and.aag b/tests/aiger/and_.aag similarity index 55% rename from tests/aiger/and.aag rename to tests/aiger/and_.aag index d1ef2c5a5..cadd505f0 100644 --- a/tests/aiger/and.aag +++ b/tests/aiger/and_.aag @@ -3,3 +3,6 @@ aag 3 2 0 1 1 4 6 6 2 4 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/and_.aig b/tests/aiger/and_.aig new file mode 100644 index 000000000..13c7a0c17 --- /dev/null +++ b/tests/aiger/and_.aig @@ -0,0 +1,5 @@ +aig 3 2 0 1 1 +6 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/buffer.aag b/tests/aiger/buffer.aag index 94a6fb1ed..211106ed6 100644 --- a/tests/aiger/buffer.aag +++ b/tests/aiger/buffer.aag @@ -1,3 +1,5 @@ aag 1 1 0 1 0 2 2 +i0 pi0 +o0 po0 diff --git a/tests/aiger/buffer.aig b/tests/aiger/buffer.aig index 0c715fdeb..01df6f1cf 100644 --- a/tests/aiger/buffer.aig +++ b/tests/aiger/buffer.aig @@ -1,2 +1,4 @@ aig 1 1 0 1 0 2 +i0 pi0 +o0 po0 diff --git a/tests/aiger/cnt1.aag b/tests/aiger/cnt1.aag index ce4f28fcb..75598862c 100644 --- a/tests/aiger/cnt1.aag +++ b/tests/aiger/cnt1.aag @@ -1,3 +1,4 @@ aag 1 0 1 0 0 1 2 3 2 +b0 po0 diff --git a/tests/aiger/cnt1.aig b/tests/aiger/cnt1.aig index 8d0ba13b1..6fcf62522 100644 --- a/tests/aiger/cnt1.aig +++ b/tests/aiger/cnt1.aig @@ -1,3 +1,4 @@ aig 1 0 1 0 0 1 3 2 +b0 po0 diff --git a/tests/aiger/cnt1e.aag b/tests/aiger/cnt1e.aag index 6db3f0ffd..35cd5a482 100644 --- a/tests/aiger/cnt1e.aag +++ b/tests/aiger/cnt1e.aag @@ -6,3 +6,4 @@ aag 5 1 1 0 3 1 8 4 2 10 9 7 b0 AIGER_NEVER +i0 po0 diff --git a/tests/aiger/cnt1e.aig b/tests/aiger/cnt1e.aig index d8d159f11..7284dd42a 100644 --- a/tests/aiger/cnt1e.aig +++ b/tests/aiger/cnt1e.aig @@ -1,4 +1,5 @@ aig 5 1 1 0 3 1 10 4 -b0 AIGER_NEVER +i0 po0 +b0 AIGER_NEVER diff --git a/tests/aiger/false.aag b/tests/aiger/false.aag index 421e64a91..bab4a06a6 100644 --- a/tests/aiger/false.aag +++ b/tests/aiger/false.aag @@ -1,2 +1,3 @@ aag 0 0 0 1 0 0 +o0 po0 diff --git a/tests/aiger/false.aig b/tests/aiger/false.aig index ad7d039fa..4dc442d7b 100644 --- a/tests/aiger/false.aig +++ b/tests/aiger/false.aig @@ -1,2 +1,3 @@ aig 0 0 0 1 0 0 +o0 po0 diff --git a/tests/aiger/inverter.aag b/tests/aiger/inverter.aag index ff7c28542..428bad9e4 100644 --- a/tests/aiger/inverter.aag +++ b/tests/aiger/inverter.aag @@ -1,3 +1,5 @@ aag 1 1 0 1 0 2 3 +i0 pi0 +o0 po0 diff --git a/tests/aiger/inverter.aig b/tests/aiger/inverter.aig index 525d82392..5bec90ae3 100644 --- a/tests/aiger/inverter.aig +++ b/tests/aiger/inverter.aig @@ -1,2 +1,4 @@ aig 1 1 0 1 0 3 +i0 pi0 +o0 po0 diff --git a/tests/aiger/notcnt1e.aag b/tests/aiger/notcnt1e.aag index 141c864f7..2ed645d84 100644 --- a/tests/aiger/notcnt1e.aag +++ b/tests/aiger/notcnt1e.aag @@ -6,3 +6,4 @@ aag 5 1 1 0 3 1 8 4 2 10 9 7 b0 AIGER_NEVER +i0 pi0 diff --git a/tests/aiger/notcnt1e.aig b/tests/aiger/notcnt1e.aig index 7c85a7290..fd7e94508 100644 --- a/tests/aiger/notcnt1e.aig +++ b/tests/aiger/notcnt1e.aig @@ -1,4 +1,5 @@ aig 5 1 1 0 3 1 10 5 -b0 AIGER_NEVER +i0 pi0 +b0 AIGER_NEVER diff --git a/tests/aiger/or.aig b/tests/aiger/or.aig deleted file mode 100644 index 75c9e4480..000000000 --- a/tests/aiger/or.aig +++ /dev/null @@ -1,3 +0,0 @@ -aig 3 2 0 1 1 -7 - \ No newline at end of file diff --git a/tests/aiger/or.aag b/tests/aiger/or_.aag similarity index 55% rename from tests/aiger/or.aag rename to tests/aiger/or_.aag index f780e339f..0f619dba3 100644 --- a/tests/aiger/or.aag +++ b/tests/aiger/or_.aag @@ -3,3 +3,6 @@ aag 3 2 0 1 1 4 7 6 3 5 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/or_.aig b/tests/aiger/or_.aig new file mode 100644 index 000000000..051687512 --- /dev/null +++ b/tests/aiger/or_.aig @@ -0,0 +1,5 @@ +aig 3 2 0 1 1 +7 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/toggle.aag b/tests/aiger/toggle.aag index 09651012d..b1a1582d7 100644 --- a/tests/aiger/toggle.aag +++ b/tests/aiger/toggle.aag @@ -2,3 +2,5 @@ aag 1 0 1 2 0 2 3 2 3 +o0 po0 +o1 po1 diff --git a/tests/aiger/toggle.aig b/tests/aiger/toggle.aig index b69e21aaf..68b41763f 100644 --- a/tests/aiger/toggle.aig +++ b/tests/aiger/toggle.aig @@ -2,3 +2,5 @@ aig 1 0 1 2 0 3 2 3 +o0 po0 +o1 po1 diff --git a/tests/aiger/true.aag b/tests/aiger/true.aag index 366893648..66a9eab46 100644 --- a/tests/aiger/true.aag +++ b/tests/aiger/true.aag @@ -1,2 +1,3 @@ aag 0 0 0 1 0 1 +o0 po0 diff --git a/tests/aiger/true.aig b/tests/aiger/true.aig index 10086f389..f9bad6000 100644 --- a/tests/aiger/true.aig +++ b/tests/aiger/true.aig @@ -1,2 +1,3 @@ aig 0 0 0 1 0 1 +o0 po0 From ebe29b66593414d0317879359d1f1d1f61a9ecc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:05:36 -0700 Subject: [PATCH 405/927] Use ABC to convert AIGER to Verilog, then sat against Yosys --- tests/aiger/run-test.sh | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index e0a34f023..70300d305 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -1,24 +1,18 @@ #!/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 +set -e +for aig in *.aig; do + ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" + ../../yosys -p " +read_verilog ${aig%.*}_ref.v +prep +design -stash gold +read_aiger -clk_name clock $aig +prep +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 -seq 16 miter +" 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 - -echo "===== AAG ======" -${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" - -echo "===== AIG ======" -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aig EXTRA_FLAGS="-f aiger" From abc40924ed5dc4aba91c7f1e83ca90f54e9eb455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:06:57 -0700 Subject: [PATCH 406/927] Use ABC to convert from AIGER to Verilog --- tests/tools/autotest.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 0a511f29c..23964a751 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -146,9 +146,10 @@ do rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then + "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v" else - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} - frontend="verilog -noblackbox" + cp ../${fn} ${bn}_ref.${ext} fi if [ ! -f ../${bn}_tb.v ]; then From a04521c6b70396a590f0ddb3081c4c5d6b01671e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:07:15 -0700 Subject: [PATCH 407/927] Fix read_aiger -- create zero driver, fix init width, parse 'b' --- frontends/aiger/aigerparse.cc | 64 ++++++++++++++++++++++++++++------- frontends/aiger/aigerparse.h | 1 + 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 38348cd65..26b101e4c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -81,11 +81,26 @@ end_of_header: else log_abort(); + RTLIL::Wire* n0 = module->wire("\\n0"); + 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; for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o') { + if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { f.ignore(1); if (!(f >> l1 >> s)) log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); @@ -97,11 +112,12 @@ end_of_header: if (c == 'i') wire = inputs[l1]; else if (c == 'l') wire = latches[l1]; else if (c == 'o') wire = outputs[l1]; + else if (c == 'b') wire = bad_properties[l1]; else log_abort(); module->rename(wire, stringf("\\%s", s.c_str())); } - else if (c == 'b' || c == 'j' || c == 'f') { + else if (c == 'j' || c == 'f') { // TODO } else if (c == 'c') { @@ -153,7 +169,7 @@ void AigerReader::parse_aiger_ascii() unsigned l1, l2, l3; // Parse inputs - for (unsigned i = 0; i < I; ++i, ++line_count) { + 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); @@ -187,8 +203,10 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l3)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(l3); + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -197,7 +215,7 @@ void AigerReader::parse_aiger_ascii() } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::S0; } latches.push_back(q_wire); } @@ -214,8 +232,17 @@ void AigerReader::parse_aiger_ascii() } std::getline(f, line); // Ignore up to start of next line - // TODO: Parse bad state properties - for (unsigned i = 0; i < B; ++i, ++line_count) + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + 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); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints @@ -290,8 +317,10 @@ void AigerReader::parse_aiger_binary() if (!(f >> l3)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(l3); + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -300,7 +329,7 @@ void AigerReader::parse_aiger_binary() } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::S0; } latches.push_back(q_wire); } @@ -317,8 +346,17 @@ void AigerReader::parse_aiger_binary() } std::getline(f, line); // Ignore up to start of next line - // TODO: Parse bad state properties - for (unsigned i = 0; i < B; ++i, ++line_count) + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + 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); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index c49cd152d..0e3719cc4 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -39,6 +39,7 @@ struct AigerReader std::vector inputs; std::vector latches; std::vector outputs; + std::vector bad_properties; AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); void parse_aiger(); From 65924fd12f48b4ec5a4d51efeea977992d033ecf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:28:05 -0700 Subject: [PATCH 408/927] Test *.aag too, by using *.aig as reference --- tests/aiger/run-test.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 70300d305..e56d0fa80 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -1,6 +1,25 @@ #!/bin/bash set -e + +for aag in *.aag; do + # Since ABC cannot read *.aag, read the *.aig instead + # (which would have been created by the reference aig2aig utility) + ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + ../../yosys -p " +read_verilog ${aag%.*}_ref.v +prep +design -stash gold +read_aiger -clk_name clock $aag +prep +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 -seq 16 miter +" +done + for aig in *.aig; do ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" ../../yosys -p " From d00ae1d6a8c0a1e147599ee27f6a4ea68f43267e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:28:25 -0700 Subject: [PATCH 409/927] Remove unnecessary std::getline() for ASCII --- frontends/aiger/aigerparse.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 26b101e4c..d0338e45d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -230,7 +230,6 @@ void AigerReader::parse_aiger_ascii() wire->port_output = true; outputs.push_back(wire); } - std::getline(f, line); // Ignore up to start of next line // Parse bad properties for (unsigned i = 0; i < B; ++i, ++line_count) { @@ -242,8 +241,6 @@ void AigerReader::parse_aiger_ascii() wire->port_output = true; bad_properties.push_back(wire); } - if (B > 0) - std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints for (unsigned i = 0; i < C; ++i, ++line_count) From 6934f4bdd53cb226d0c8631eff691d9a96aebbce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:30:36 -0700 Subject: [PATCH 410/927] Fix spacing (entire file is wrong anyway, will fix later) --- 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 d0338e45d..32be4cf6c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -81,9 +81,9 @@ end_of_header: else log_abort(); - RTLIL::Wire* n0 = module->wire("\\n0"); - if (n0) - module->connect(n0, RTLIL::S0); + RTLIL::Wire* n0 = module->wire("\\n0"); + if (n0) + module->connect(n0, RTLIL::S0); for (unsigned i = 0; i < outputs.size(); ++i) { RTLIL::Wire *wire = outputs[i]; From 5ab59cd59ee90abc4b6991486854dbe4c3f4d0a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:36:19 -0700 Subject: [PATCH 411/927] Resolve @cliffordwolf comment on sigmap --- passes/opt/muxpack.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 8c4db4e4d..b060389e3 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -94,9 +94,9 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec a_sig = cell->getPort("\\A"); + SigSpec a_sig = sigmap(cell->getPort("\\A")); if (cell->type == "$mux") { - SigSpec b_sig = cell->getPort("\\B"); + SigSpec b_sig = sigmap(cell->getPort("\\B")); if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) goto start_cell; From 887df8914c64220b9f306b7d21f199fa247224fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:37:52 -0700 Subject: [PATCH 412/927] Resolve @cliffordwolf comment on redundant check --- passes/opt/muxpack.cc | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index b060389e3..15a646e2e 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -109,17 +109,9 @@ struct MuxpackWorker } else log_abort(); - { - for (auto bit : a_sig.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - Cell *c1 = sig_chain_prev.at(a_sig); - Cell *c2 = cell; - - if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) + for (auto bit : a_sig.bits()) + if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - } continue; From e263bc249b905195120fbc074c6f80d03fb21cf8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:54:29 -0700 Subject: [PATCH 413/927] Add nonexclusive test from @cliffordwolf --- tests/various/muxpack.v | 13 +++++++++++++ tests/various/muxpack.ys | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index 41dfed396..f3c25db8d 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -153,3 +153,16 @@ always @* else o <= i[4*W+:W]; endmodule + +module cliffordwolf_nonexclusive_select ( + input wire x, y, z, + input wire a, b, c, d, + output reg o +); + always @* begin + o = a; + if (x) o = b; + if (y) o = c; + if (z) o = d; + end +endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index dd3c143d8..7c3fe5070 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -163,3 +163,18 @@ 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 cliffordwolf_nonexclusive_select +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 1da12c5071a738504d22e68d66cab7c5c5afb07e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 12:12:11 -0700 Subject: [PATCH 414/927] Add @cliffordwolf freduce testcase --- tests/various/muxpack.v | 13 +++++++++++++ tests/various/muxpack.ys | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index f3c25db8d..d45ce4045 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -166,3 +166,16 @@ module cliffordwolf_nonexclusive_select ( if (z) o = d; end endmodule + +module cliffordwolf_freduce ( + input wire [1:0] s, + input wire a, b, c, d, + output reg [3:0] o +); + always @* begin + o = {4{a}}; + if (s == 0) o = {3{b}}; + if (s == 1) o = {2{c}}; + if (s == 2) o = d; + end +endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 7c3fe5070..afdacdf30 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -178,3 +178,20 @@ 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 cliffordwolf_freduce +prep +design -save gold +proc; opt; freduce; opt +write_verilog -noexpr -norename +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 f48c6920b7aa777c0c569f444e3db88211835cec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 13:12:48 -0700 Subject: [PATCH 415/927] Add read_aiger to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 36b64e111..839fefcf1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass + - Added "read_aiger" frontend - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From 9b408838f191bb0390b6edff55770cab8e8ca15d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 14:18:17 -0700 Subject: [PATCH 416/927] Add ExclusiveDatabase to check exclusive $eq/$logic_not cell results --- passes/opt/muxpack.cc | 65 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 15a646e2e..0cf9e0e30 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -24,6 +24,58 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct ExclusiveDatabase +{ + Module *module; + const SigMap &sigmap; + + dict sig_cmp_prev; + dict> sig_exclusive; + + ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) + { + SigSpec a_port, b_port, y_port; + for (auto cell : module->cells()) { + if (cell->type == "$eq") { + a_port = sigmap(cell->getPort("\\A")); + b_port = sigmap(cell->getPort("\\B")); + if (!b_port.is_fully_const()) { + if (!a_port.is_fully_const()) + continue; + std::swap(a_port, b_port); + } + y_port = sigmap(cell->getPort("\\Y")); + } + else if (cell->type == "$logic_not") { + a_port = sigmap(cell->getPort("\\A")); + b_port = Const(RTLIL::S0, GetSize(a_port)); + y_port = sigmap(cell->getPort("\\Y")); + } + else continue; + + auto r = sig_exclusive[a_port].insert(b_port.as_const()); + if (!r.second) + continue; + sig_cmp_prev[y_port] = a_port; + } + } + + bool query(const SigSpec& sig1, const SigSpec& sig2) const + { + auto it = sig_cmp_prev.find(sig1); + if (it == sig_cmp_prev.end()) + return false; + + auto jt = sig_cmp_prev.find(sig2); + if (jt == sig_cmp_prev.end()) + return false; + + log("query = %s %s\n", log_signal(it->second), log_signal(jt->second)); + return it->second == jt->second; + } +}; + + struct MuxpackWorker { Module *module; @@ -39,6 +91,8 @@ struct MuxpackWorker pool chain_start_cells; pool candidate_cells; + ExclusiveDatabase excl_db; + void make_sig_chain_next_prev() { for (auto wire : module->wires()) @@ -90,6 +144,7 @@ struct MuxpackWorker void find_chain_start_cells() { + Cell* first_cell = nullptr; for (auto cell : candidate_cells) { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); @@ -102,6 +157,13 @@ struct MuxpackWorker if (!sig_chain_prev.count(a_sig)) a_sig = b_sig; + + if (first_cell) { + SigSpec s_sig = sigmap(cell->getPort("\\S")); + SigSpec prev_s_sig = sigmap(first_cell->getPort("\\S")); + if (!excl_db.query(prev_s_sig, s_sig)) + goto start_cell; + } } else if (cell->type == "$pmux") { if (!sig_chain_prev.count(a_sig)) @@ -117,6 +179,7 @@ struct MuxpackWorker start_cell: chain_start_cells.insert(cell); + first_cell = cell; } } @@ -208,7 +271,7 @@ struct MuxpackWorker } MuxpackWorker(Module *module) : - module(module), sigmap(module), mux_count(0), pmux_count(0) + module(module), sigmap(module), mux_count(0), pmux_count(0), excl_db(module, sigmap) { make_sig_chain_next_prev(); find_chain_start_cells(); From ba52d9b4716b287b0a469597b748f9859e897329 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:34:16 -0700 Subject: [PATCH 417/927] Extend ExclusiveDatabase to query SigSpec-s (for $pmux) --- passes/opt/muxpack.cc | 44 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 0cf9e0e30..4b02df394 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,7 +29,7 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict sig_cmp_prev; + dict sig_cmp_prev; dict> sig_exclusive; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) @@ -62,16 +62,23 @@ struct ExclusiveDatabase bool query(const SigSpec& sig1, const SigSpec& sig2) const { - auto it = sig_cmp_prev.find(sig1); - if (it == sig_cmp_prev.end()) - return false; + // FIXME: O(N) + for (auto bit1 : sig1.bits()) { + auto it = sig_cmp_prev.find(bit1); + if (it == sig_cmp_prev.end()) + return false; - auto jt = sig_cmp_prev.find(sig2); - if (jt == sig_cmp_prev.end()) - return false; + for (auto bit2 : sig2.bits()) { + auto jt = sig_cmp_prev.find(bit2); + if (jt == sig_cmp_prev.end()) + return false; - log("query = %s %s\n", log_signal(it->second), log_signal(jt->second)); - return it->second == jt->second; + if (it->second != jt->second) + return false; + } + } + + return true; } }; @@ -144,7 +151,6 @@ struct MuxpackWorker void find_chain_start_cells() { - Cell* first_cell = nullptr; for (auto cell : candidate_cells) { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); @@ -157,13 +163,6 @@ struct MuxpackWorker if (!sig_chain_prev.count(a_sig)) a_sig = b_sig; - - if (first_cell) { - SigSpec s_sig = sigmap(cell->getPort("\\S")); - SigSpec prev_s_sig = sigmap(first_cell->getPort("\\S")); - if (!excl_db.query(prev_s_sig, s_sig)) - goto start_cell; - } } else if (cell->type == "$pmux") { if (!sig_chain_prev.count(a_sig)) @@ -175,11 +174,19 @@ struct MuxpackWorker if (sigbit_with_non_chain_users.count(bit)) goto start_cell; + { + Cell *prev_cell = sig_chain_prev.at(a_sig); + log_assert(prev_cell); + SigSpec s_sig = sigmap(cell->getPort("\\S")); + SigSpec next_s_sig = sigmap(prev_cell->getPort("\\S")); + if (!excl_db.query(s_sig, next_s_sig)) + goto start_cell; + } + continue; start_cell: chain_start_cells.insert(cell); - first_cell = cell; } } @@ -243,6 +250,7 @@ struct MuxpackWorker s_sig.append(cursor_cell->getPort("\\S")); } else { + log_assert(cursor_cell->type == "$mux"); b_sig.append(cursor_cell->getPort("\\A")); s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S"))); } From b959bf79c004fdf81ccc397d5aa774b67a09d6da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:35:15 -0700 Subject: [PATCH 418/927] Add nonexcl case test, comment out two others --- tests/various/muxpack.v | 18 ++++++++++++ tests/various/muxpack.ys | 61 +++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index d45ce4045..3a1086dbf 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -179,3 +179,21 @@ module cliffordwolf_freduce ( if (s == 2) o = d; end endmodule + +module case_nonexclusive_select ( + input wire [1:0] x, y, + input wire a, b, c, d, e, + output reg o +); + always @* begin + case (x) + 0, 2: o = b; + 1: o = c; + default: begin + o = a; + if (y == 0) o = d; + if (y == 1) o = e; + end + endcase + end +endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index afdacdf30..579dad8d3 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -1,5 +1,6 @@ read_verilog muxpack.v design -save read + hierarchy -top mux_if_unbal_4_1 prep design -save gold @@ -29,20 +30,21 @@ 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 +# TODO: Currently ExclusiveDatabase only analyses $eq cells +#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 @@ -156,8 +158,8 @@ design -save gold muxpack opt stat -select -assert-count 2 t:$mux -select -assert-count 1 t:$pmux +select -assert-count 4 t:$mux +select -assert-count 0 t:$pmux design -stash gate design -import gold -as gold design -import gate -as gate @@ -171,25 +173,40 @@ design -save gold muxpack opt stat -select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux +select -assert-count 3 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 +#design -load read +#hierarchy -top cliffordwolf_freduce +#prep +#design -save gold +#proc; opt; freduce; opt +#show +#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 cliffordwolf_freduce +hierarchy -top case_nonexclusive_select prep design -save gold -proc; opt; freduce; opt -write_verilog -noexpr -norename muxpack opt stat select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux +select -assert-count 2 t:$pmux design -stash gate design -import gold -as gold design -import gate -as gate From f705f6a0b5d19d38cf41ba5f782847de54110463 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:39:12 -0700 Subject: [PATCH 419/927] Comment O(N) -> O(N^2) --- passes/opt/muxpack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 4b02df394..f01d5474d 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -62,7 +62,7 @@ struct ExclusiveDatabase bool query(const SigSpec& sig1, const SigSpec& sig2) const { - // FIXME: O(N) + // FIXME: O(N^2) for (auto bit1 : sig1.bits()) { auto it = sig_cmp_prev.find(bit1); if (it == sig_cmp_prev.end()) From 2b350401c4577d54c0d460240e2d2847d2eeadc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:44:57 -0700 Subject: [PATCH 420/927] Fix spacing from spaces to tabs --- frontends/aiger/aigerparse.cc | 634 +++++++++++++++++----------------- 1 file changed, 317 insertions(+), 317 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 32be4cf6c..68552fd06 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -34,389 +34,389 @@ YOSYS_NAMESPACE_BEGIN AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name) - : design(design), f(f), clk_name(clk_name) + : design(design), f(f), clk_name(clk_name) { - module = new RTLIL::Module; - module->name = module_name; - if (design->module(module->name)) - log_error("Duplicate definition of module %s!\n", log_id(module->name)); + module = new RTLIL::Module; + module->name = module_name; + if (design->module(module->name)) + log_error("Duplicate definition of module %s!\n", log_id(module->name)); } void AigerReader::parse_aiger() { - std::string header; - f >> header; - if (header != "aag" && header != "aig") - log_error("Unsupported AIGER file!\n"); + 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"); + // Parse rest of header + if (!(f >> M >> I >> L >> O >> A)) + log_error("Invalid AIGER header\n"); - // Optional values - B = C = J = F = 0; - if (f.peek() != ' ') goto end_of_header; - if (!(f >> B)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> C)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> J)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> F)) log_error("Invalid AIGER header\n"); + // Optional values + B = C = J = F = 0; + if (f.peek() != ' ') goto end_of_header; + if (!(f >> B)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> C)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> J)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> F)) log_error("Invalid AIGER header\n"); end_of_header: - 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 + 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 B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); + 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; + line_count = 1; - if (header == "aag") - parse_aiger_ascii(); - else if (header == "aig") - parse_aiger_binary(); - else - log_abort(); + if (header == "aag") + parse_aiger_ascii(); + else if (header == "aig") + parse_aiger_binary(); + else + log_abort(); - RTLIL::Wire* n0 = module->wire("\\n0"); - if (n0) - module->connect(n0, RTLIL::S0); + RTLIL::Wire* n0 = module->wire("\\n0"); + 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; - } - } + 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; - for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { - f.ignore(1); - if (!(f >> l1 >> s)) - log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); + // Parse footer (symbol table, comments, etc.) + unsigned l1; + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { + 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); + 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 if (c == 'b') wire = bad_properties[l1]; - else log_abort(); + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else if (c == 'b') wire = bad_properties[l1]; + else log_abort(); - module->rename(wire, stringf("\\%s", s.c_str())); - } - else if (c == 'j' || c == 'f') { - // TODO - } - else if (c == 'c') { - f.ignore(1); - if (f.peek() == '\n') - break; - // Else constraint (TODO) - } - 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 - } + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + } + 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 + } - module->fixup_ports(); - design->add(module); + module->fixup_ports(); + 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); - } + 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? + 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; + return wire; } void AigerReader::parse_aiger_ascii() { - std::string line; - std::stringstream ss; + std::string line; + std::stringstream ss; - unsigned l1, l2, l3; + unsigned l1, l2, l3; - // Parse inputs - 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_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_input = true; - inputs.push_back(wire); - } + // Parse inputs + 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_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_input = true; + inputs.push_back(wire); + } - // Parse latches - RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - clk_wire = module->wire(clk_name); - log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); - clk_wire = module->addWire(clk_name); - clk_wire->port_input = true; - } - 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_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? - RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + // Parse latches + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + clk_wire = module->wire(clk_name); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); + clk_wire->port_input = true; + } + 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_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); + module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); - // Reset logic is optional in AIGER 1.9 - if (f.peek() == ' ') { - if (!(f >> l3)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0) - q_wire->attributes["\\init"] = RTLIL::S0; - else if (l3 == 1) - q_wire->attributes["\\init"] = RTLIL::S1; - else if (l3 == l1) { - //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); - } - else - log_error("Line %u has invalid reset literal for latch!\n", line_count); - } - else { - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::S0; - } - latches.push_back(q_wire); - } + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::S0; + } + latches.push_back(q_wire); + } - // Parse outputs - for (unsigned i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as an output!\n", line_count); + // Parse outputs + for (unsigned i = 0; i < O; ++i, ++line_count) { + 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); - wire->port_output = true; - outputs.push_back(wire); - } + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } - // Parse bad properties - for (unsigned i = 0; i < B; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + 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); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - bad_properties.push_back(wire); - } + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } - // TODO: Parse invariant constraints - for (unsigned i = 0; i < C; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse justice properties - for (unsigned i = 0; i < J; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse fairness constraints - for (unsigned i = 0; i < F; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // Parse AND - for (unsigned i = 0; i < A; ++i) { - if (!(f >> l1 >> l2 >> l3)) - log_error("Line %u cannot be interpreted as an AND!\n", line_count); + // Parse AND + for (unsigned i = 0; i < A; ++i) { + 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_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); - module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); - } - std::getline(f, line); // Ignore up to start of next line + 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); + module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); + } + std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) { - unsigned x = 0, i = 0; - unsigned char ch; - while ((ch = f.get()) & 0x80) - x |= (ch & 0x7f) << (7 * i++); - return ref - (x | (ch << (7 * i))); + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = f.get()) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return ref - (x | (ch << (7 * i))); } void AigerReader::parse_aiger_binary() { - unsigned l1, l2, l3; - std::string line; + unsigned l1, l2, l3; + std::string line; - // Parse inputs - for (unsigned i = 1; i <= I; ++i) { - RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); - wire->port_input = true; - inputs.push_back(wire); - } + // Parse inputs + for (unsigned i = 1; i <= I; ++i) { + RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); + wire->port_input = true; + inputs.push_back(wire); + } - // Parse latches - RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - clk_wire = module->wire(clk_name); - log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); - clk_wire = module->addWire(clk_name); - clk_wire->port_input = true; - } - l1 = (I+1) * 2; - for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { - if (!(f >> l2)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); - log_debug("%d %d is a latch\n", l1, l2); - RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + // Parse latches + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + clk_wire = module->wire(clk_name); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); + clk_wire->port_input = true; + } + l1 = (I+1) * 2; + for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { + if (!(f >> l2)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + log_debug("%d %d is a latch\n", l1, l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); - // Reset logic is optional in AIGER 1.9 - if (f.peek() == ' ') { - if (!(f >> l3)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0) - q_wire->attributes["\\init"] = RTLIL::S0; - else if (l3 == 1) - q_wire->attributes["\\init"] = RTLIL::S1; - else if (l3 == l1) { - //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); - } - else - log_error("Line %u has invalid reset literal for latch!\n", line_count); - } - else { - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::S0; - } - latches.push_back(q_wire); - } + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::S0; + } + latches.push_back(q_wire); + } - // Parse outputs - for (unsigned i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as an output!\n", line_count); + // Parse outputs + for (unsigned i = 0; i < O; ++i, ++line_count) { + 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); - wire->port_output = true; - outputs.push_back(wire); - } - std::getline(f, line); // Ignore up to start of next line + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } + std::getline(f, line); // Ignore up to start of next line - // Parse bad properties - for (unsigned i = 0; i < B; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + 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); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - bad_properties.push_back(wire); - } - if (B > 0) - std::getline(f, line); // Ignore up to start of next line + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse invariant constraints - for (unsigned i = 0; i < C; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse justice properties - for (unsigned i = 0; i < J; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse fairness constraints - for (unsigned i = 0; i < F; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // Parse AND - l1 = (I+L+1) << 1; - for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { - l2 = parse_next_delta_literal(f, l1); - l3 = parse_next_delta_literal(f, l2); + // Parse AND + l1 = (I+L+1) << 1; + for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { + 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_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); + 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); - 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); + } } struct AigerFrontend : public Frontend { - AigerFrontend() : Frontend("aiger", "read AIGER file") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_aiger [options] [filename]\n"); - log("\n"); - 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: )" + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + 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 + "top" // FIXME #else - "" + "" #endif - ")\n"); - log("\n"); - 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"); - } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing AIGER frontend.\n"); + ")\n"); + log("\n"); + 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"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); - RTLIL::IdString clk_name = "\\clk"; - RTLIL::IdString module_name; + RTLIL::IdString clk_name = "\\clk"; + RTLIL::IdString module_name; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -433,19 +433,19 @@ struct AigerFrontend : public Frontend { } extra_args(f, filename, args, argidx); - if (module_name.empty()) { + if (module_name.empty()) { #ifdef _WIN32 - module_name = "top"; // FIXME: basename equivalent on Win32? + module_name = "top"; // FIXME: basename equivalent on Win32? #else - char* bn = strdup(filename.c_str()); - module_name = RTLIL::escape_id(bn); - free(bn); + char* bn = strdup(filename.c_str()); + module_name = RTLIL::escape_id(bn); + free(bn); #endif - } + } - AigerReader reader(design, *f, module_name, clk_name); + AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); - } + } } AigerFrontend; YOSYS_NAMESPACE_END From 5a46a0b38584014c3644cc434458638874bd4d75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 16:57:32 -0700 Subject: [PATCH 421/927] 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 422/927] 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 423/927] 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 abf90b040331f9fd48c9e4bdb4bbb952db4c2d04 Mon Sep 17 00:00:00 2001 From: Simon Schubert <2@0x2c.org> Date: Mon, 10 Jun 2019 11:49:08 +0200 Subject: [PATCH 424/927] ice40/cells_sim.v: Add support for RGB_DRV/LED_DRV_CUR for u4k --- techlibs/ice40/cells_sim.v | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index e89405b22..f9945b2b5 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -973,6 +973,30 @@ parameter RGB1_CURRENT = "0b000000"; parameter RGB2_CURRENT = "0b000000"; endmodule +(* blackbox *) +module SB_LED_DRV_CUR( + input EN, + output LEDPU +); +endmodule + +(* blackbox *) +module SB_RGB_DRV( + input RGBLEDEN, + input RGB0PWM, + input RGB1PWM, + input RGB2PWM, + input RGBPU, + output RGB0, + output RGB1, + output RGB2 +); +parameter CURRENT_MODE = "0b0"; +parameter RGB0_CURRENT = "0b000000"; +parameter RGB1_CURRENT = "0b000000"; +parameter RGB2_CURRENT = "0b000000"; +endmodule + (* blackbox *) module SB_I2C( input SBCLKI, From a91ea6612a73568782c80bd12ce2875353e2b5c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 10:27:55 -0700 Subject: [PATCH 425/927] Add some more comments --- tests/aiger/run-test.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index e56d0fa80..f52eb4ac1 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -2,9 +2,14 @@ set -e +# NB: *.aag and *.aig must contain a symbol table naming the primary +# inputs and outputs, otherwise ABC and Yosys will name them +# arbitrarily (and inconsistently with each other). + for aag in *.aag; do # Since ABC cannot read *.aag, read the *.aig instead - # (which would have been created by the reference aig2aig utility) + # (which would have been created by the reference aig2aig utility, + # available from http://fmv.jku.at/aiger/) ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" ../../yosys -p " read_verilog ${aag%.*}_ref.v From 5b999ae68decef5646ef0ccac53463f22fe18d8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 10:32:19 -0700 Subject: [PATCH 426/927] Elaborate muxpack doc --- passes/opt/muxpack.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index f01d5474d..b6f3313bf 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -302,8 +302,12 @@ struct MuxpackPass : public Pass { 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("constructs) and $mux cells (e.g. those created by if-else constructs) into\n"); + log("$pmux cells.\n"); + log("\n"); + log("This optimisation is conservative --- it will only pack $mux or $pmux cells with\n"); + log("other such cells if it can be certain that the select lines are mutually\n"); + log("exclusive.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From d097f423d1b30a3936388bb93a0a88fd3527ad49 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Mon, 10 Jun 2019 21:42:35 +0200 Subject: [PATCH 427/927] Refactor driver map generation - Implement iterators over the driver map that enumerate signals and cells within the cones of the signal --- kernel/satgen_algo.h | 158 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 kernel/satgen_algo.h diff --git a/kernel/satgen_algo.h b/kernel/satgen_algo.h new file mode 100644 index 000000000..483dfad5c --- /dev/null +++ b/kernel/satgen_algo.h @@ -0,0 +1,158 @@ +/* -*- c++ -*- + * 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. + * + */ + +#ifndef SATGEN_ALGO_H +#define SATGEN_ALGO_H + +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/sigtools.h" +#include + +YOSYS_NAMESPACE_BEGIN + +struct DriverMap : public std::map>> { + RTLIL::Module *module; + SigMap sigmap; + + using map_t = std::map>>; + + struct DriverMapConeWireIterator : public std::iterator { + using set_iter_t = std::set::iterator; + + DriverMap *drvmap; + const RTLIL::SigBit *sig; + std::stack> dfs; + + DriverMapConeWireIterator(DriverMap *drvmap) : DriverMapConeWireIterator(drvmap, NULL) {} + + DriverMapConeWireIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} + + inline const RTLIL::SigBit &operator*() const { return *sig; }; + inline bool operator!=(const DriverMapConeWireIterator &other) const { return sig != other.sig; } + inline bool operator==(const DriverMapConeWireIterator &other) const { return sig == other.sig; } + inline void operator++() + { + if (drvmap->count(*sig)) { + std::pair> &drv = drvmap->at(*sig); + dfs.push(std::make_pair(drv.second.begin(), drv.second.end())); + sig = &(*dfs.top().first); + } else { + while (1) { + auto &inputs_iter = dfs.top(); + + inputs_iter.first++; + if (inputs_iter.first != inputs_iter.second) { + sig = &(*inputs_iter.first); + return; + } else { + dfs.pop(); + if (dfs.empty()) { + sig = NULL; + return; + } + } + } + } + } + }; + + struct DriverMapConeWireIterable { + DriverMap *drvmap; + const RTLIL::SigBit *sig; + + DriverMapConeWireIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} + + inline DriverMapConeWireIterator begin() { return DriverMapConeWireIterator(drvmap, sig); } + inline DriverMapConeWireIterator end() { return DriverMapConeWireIterator(drvmap); } + }; + + struct DriverMapConeCellIterator : public std::iterator { + DriverMap *drvmap; + const RTLIL::SigBit *sig; + + DriverMapConeWireIterator sig_iter; + + DriverMapConeCellIterator(DriverMap *drvmap) : DriverMapConeCellIterator(drvmap, NULL) {} + + DriverMapConeCellIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig), sig_iter(drvmap, sig) + { + if ((sig != NULL) && (!drvmap->count(*sig_iter))) { + ++(*this); + } + } + + inline RTLIL::Cell *operator*() const + { + std::pair> &drv = drvmap->at(*sig); + return drv.first; + }; + inline bool operator!=(const DriverMapConeCellIterator &other) const { return sig_iter != other.sig_iter; } + inline bool operator==(const DriverMapConeCellIterator &other) const { return sig_iter == other.sig_iter; } + inline void operator++() + { + do { + ++sig_iter; + if (sig_iter.sig == NULL) { + return; + } + } while (!drvmap->count(*sig_iter)); + } + }; + + struct DriverMapConeCellIterable { + DriverMap *drvmap; + const RTLIL::SigBit *sig; + + DriverMapConeCellIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} + + inline DriverMapConeCellIterator begin() { return DriverMapConeCellIterator(drvmap, sig); } + inline DriverMapConeCellIterator end() { return DriverMapConeCellIterator(drvmap); } + }; + + DriverMap(RTLIL::Module *module) : module(module), sigmap(module) + { + CellTypes ct; + ct.setup_internals(); + ct.setup_stdcells(); + + for (auto &it : module->cells_) { + if (ct.cell_known(it.second->type)) { + std::set inputs, outputs; + for (auto &port : it.second->connections()) { + std::vector bits = sigmap(port.second).to_sigbit_vector(); + if (ct.cell_output(it.second->type, port.first)) + outputs.insert(bits.begin(), bits.end()); + else + inputs.insert(bits.begin(), bits.end()); + } + std::pair> drv(it.second, inputs); + for (auto &bit : outputs) + (*this)[bit] = drv; + } + } + } + + DriverMapConeWireIterable cone(const RTLIL::SigBit &sig) { return DriverMapConeWireIterable(this, &sig); } + DriverMapConeCellIterable cell_cone(const RTLIL::SigBit &sig) { return DriverMapConeCellIterable(this, &sig); } +}; + +YOSYS_NAMESPACE_END + +#endif From 9d8563178e930fe30bf4dd35b4a0306a1bd85d92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 14:34:12 -0700 Subject: [PATCH 428/927] 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 429/927] 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 430/927] 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 431/927] 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 432/927] 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 433/927] 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 434/927] 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 c314ca3c51579a9c5305cbf9a69635e123db0423 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 16:16:26 -0700 Subject: [PATCH 435/927] Add test --- tests/various/shregmap.v | 22 ++++++++++++++++++++++ tests/various/shregmap.ys | 31 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/various/shregmap.v create mode 100644 tests/various/shregmap.ys diff --git a/tests/various/shregmap.v b/tests/various/shregmap.v new file mode 100644 index 000000000..56e05c2c0 --- /dev/null +++ b/tests/various/shregmap.v @@ -0,0 +1,22 @@ +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 new file mode 100644 index 000000000..ca7f47015 --- /dev/null +++ b/tests/various/shregmap.ys @@ -0,0 +1,31 @@ +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 f19aa8d989df9e443d26cf6beaf389c2f3d6a424 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 16:16:40 -0700 Subject: [PATCH 436/927] If d_bit already in sigbit_chain_next, create extra wire --- passes/techmap/shregmap.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 21dfe9619..46f6a79fb 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -293,10 +293,13 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { - if (sigbit_chain_next.count(d_bit)) { + auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); + if (!r.second) { sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; + 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; From 4b56f6646dbf819da9fa1fdd47bb4bbdf943be7f Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 11 Jun 2019 02:52:06 +0300 Subject: [PATCH 437/927] Fixed brojen $error()/$info/$warning() on non-generate blocks (within always/initial blocks) --- frontends/verilog/verilog_lexer.l | 2 +- frontends/verilog/verilog_parser.y | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 3c612472d..d3fd91473 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -313,7 +313,7 @@ supply1 { return TOK_SUPPLY1; } "$"(info|warning|error|fatal) { frontend_verilog_yylval.string = new std::string(yytext); - return TOK_ELAB_TASK; + return TOK_MSG_TASKS; } "$signed" { return TOK_TO_SIGNED; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a034f9601..ea8e457e8 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -133,7 +133,7 @@ struct specify_rise_fall { } %token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE -%token TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_ELAB_TASK +%token TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM @@ -1881,6 +1881,16 @@ behavioral_stmt: } opt_arg_list ';'{ ast_stack.pop_back(); } | + TOK_MSG_TASKS attr { + AstNode *node = new AstNode(AST_TCALL); + node->str = *$1; + delete $1; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + append_attr(node, $2); + } opt_arg_list ';'{ + ast_stack.pop_back(); + } | attr TOK_BEGIN opt_label { AstNode *node = new AstNode(AST_BLOCK); ast_stack.back()->children.push_back(node); @@ -2177,7 +2187,7 @@ gen_stmt: delete $6; ast_stack.pop_back(); } | - TOK_ELAB_TASK { + TOK_MSG_TASKS { AstNode *node = new AstNode(AST_TECALL); node->str = *$1; delete $1; From 9892df17efadd0eafe5217e812fb4cec2bfdf6e5 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 11 Jun 2019 11:47:13 +0200 Subject: [PATCH 438/927] Generate satgen instance instead of calling sat pass --- kernel/satgen_algo.h | 45 ++++++++++++++++- passes/opt/opt_rmdff.cc | 106 +++++++++++++++++++++++++++++++--------- 2 files changed, 128 insertions(+), 23 deletions(-) diff --git a/kernel/satgen_algo.h b/kernel/satgen_algo.h index 483dfad5c..d475d7d64 100644 --- a/kernel/satgen_algo.h +++ b/kernel/satgen_algo.h @@ -100,7 +100,7 @@ struct DriverMap : public std::map> &drv = drvmap->at(*sig); + std::pair> &drv = drvmap->at(*sig_iter); return drv.first; }; inline bool operator!=(const DriverMapConeCellIterator &other) const { return sig_iter != other.sig_iter; } @@ -126,6 +126,48 @@ struct DriverMap : public std::map { + DriverMap *drvmap; + const RTLIL::SigBit *sig; + + DriverMapConeWireIterator sig_iter; + + DriverMapConeInputsIterator(DriverMap *drvmap) : DriverMapConeInputsIterator(drvmap, NULL) {} + + DriverMapConeInputsIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig), sig_iter(drvmap, sig) + { + if ((sig != NULL) && (drvmap->count(*sig_iter))) { + ++(*this); + } + } + + inline const RTLIL::SigBit& operator*() const + { + return *sig_iter; + }; + inline bool operator!=(const DriverMapConeInputsIterator &other) const { return sig_iter != other.sig_iter; } + inline bool operator==(const DriverMapConeInputsIterator &other) const { return sig_iter == other.sig_iter; } + inline void operator++() + { + do { + ++sig_iter; + if (sig_iter.sig == NULL) { + return; + } + } while (drvmap->count(*sig_iter)); + } + }; + + struct DriverMapConeInputsIterable { + DriverMap *drvmap; + const RTLIL::SigBit *sig; + + DriverMapConeInputsIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} + + inline DriverMapConeInputsIterator begin() { return DriverMapConeInputsIterator(drvmap, sig); } + inline DriverMapConeInputsIterator end() { return DriverMapConeInputsIterator(drvmap); } + }; + DriverMap(RTLIL::Module *module) : module(module), sigmap(module) { CellTypes ct; @@ -150,6 +192,7 @@ struct DriverMap : public std::map +#include "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/satgen.h" +#include "kernel/satgen_algo.h" +#include "kernel/sigtools.h" #include +#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -456,36 +459,95 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) if (sat && has_init) { std::vector removed_sigbits; + DriverMap drvmap(mod); + // for (auto &sigbit : sig_q.bits()) { - for (int position =0; position < GetSize(sig_d); position += 1) { + for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; - RTLIL::Const sigbit_init_val = val_init.extract(position); if ((!q_sigbit.wire) || (!d_sigbit.wire)) { continue; } + std::map sat_pi; + + ezSatPtr ez; + SatGen satgen(ez.get(), &drvmap.sigmap); + std::set ez_cells; + std::vector modelExpressions; + std::vector modelValues; + + log("Optimizing: %s\n", log_id(q_sigbit.wire)); + log(" Cells:"); + for (const auto &cell : drvmap.cell_cone(d_sigbit)) { + if (ez_cells.count(cell) == 0) { + log(" %s\n", log_id(cell)); + if (!satgen.importCell(cell)) + log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), + RTLIL::id2cstr(cell->type)); + ez_cells.insert(cell); + } + } + + RTLIL::Const sigbit_init_val = val_init.extract(position); + int reg_init = satgen.importSigSpec(sigbit_init_val).front(); + + int output_a = satgen.importSigSpec(d_sigbit).front(); + modelExpressions.push_back(output_a); + + log(" Wires:"); + for (const auto &sig : drvmap.cone_inputs(d_sigbit)) { + if (sat_pi.count(sig) == 0) { + sat_pi[sig] = satgen.importSigSpec(sig).front(); + modelExpressions.push_back(sat_pi[sig]); + + if (sig == q_sigbit) { + ez->assume(ez->IFF(sat_pi[sig], reg_init)); + } + + if (sig.wire) { + log(" %s\n", log_id(sig.wire)); + } + } + } + + bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, reg_init)); + // bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, ez->NOT(reg_init))); + if (ez->getSolverTimoutStatus()) + log("Timeout\n"); + + log("Success: %d\n", success); + + // satgen.signals_eq(big_lhs, big_rhs, timestep); + + // auto iterable = drvmap.cone(d_sigbit); + + // // for (const auto &sig : drvmap.cone(d_sigbit)) + // for(auto begin=iterable.begin(); begin != iterable.end(); ++begin) + // { + // if (drvmap.count(*begin)) { + // if (drvmap.at(*begin).first) + // log("Running: %s\n", log_id(drvmap.at(*begin).first)); + // } + + // if ((*begin).wire) { + // log("Running: %s\n", log_id((*begin).wire)); + // } + // } + + char str[1024]; - sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", - log_id(d_sigbit.wire), - d_sigbit.offset, - sigbit_init_val.as_string().c_str(), - log_id(q_sigbit.wire), - q_sigbit.offset, - sigbit_init_val.as_string().c_str() - ); - log("Running: %s\n", str); + // sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", log_id(d_sigbit.wire), d_sigbit.offset, + // sigbit_init_val.as_string().c_str(), log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); + // log("Running: %s\n", str); - log_flush(); + // log_flush(); - pass->call(mod->design, str); - if (mod->design->scratchpad_get_bool("sat.success", false)) { - sprintf(str, "connect -set %s[%d] %s", - log_id(q_sigbit.wire), - q_sigbit.offset, - sigbit_init_val.as_string().c_str() - ); + // pass->call(mod->design, str); + // if (mod->design->scratchpad_get_bool("sat.success", false)) { + if (success) { + sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); log("Running: %s\n", str); log_flush(); pass->call(mod->design, str); From 8a708d1fdb662f86a46720200fa15acafde30333 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 12:02:31 -0700 Subject: [PATCH 439/927] 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 440/927] 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 2f427acc9ed23c77e89386f4fbf53ac580bf0f0b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 15:48:20 -0700 Subject: [PATCH 441/927] Try way that doesn't involve creating a new wire --- passes/techmap/shregmap.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 46f6a79fb..3adcd8968 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -294,12 +294,8 @@ 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; @@ -319,14 +315,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; - if (sigbit_chain_prev.count(it.first) != 0) + c1 = sigbit_chain_prev.at(it.first, nullptr); + if (c1 != nullptr) { - Cell *c1 = sigbit_chain_prev.at(it.first); - Cell *c2 = it.second; - if (c1->type != c2->type) goto start_cell; @@ -336,6 +332,15 @@ 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(); @@ -352,7 +357,7 @@ struct ShregmapWorker } start_cell: - chain_start_cells.insert(it.second); + chain_start_cells.insert(c2); } } From d26646051c4ae9740decd5d76eec6a3afd63844a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 16:05:27 -0700 Subject: [PATCH 442/927] 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 6cdea93724b69695938ca021fd3841f644b478bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 16:05:42 -0700 Subject: [PATCH 443/927] Revert "Try way that doesn't involve creating a new wire" This reverts commit 2f427acc9ed23c77e89386f4fbf53ac580bf0f0b. --- 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 444/927] 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 45c2a5f87694a83e0cf96477ede02567a93b32a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:34:06 -0700 Subject: [PATCH 445/927] Add shregmap -tech xilinx test --- tests/various/shregmap.v | 28 +++++++++++++++++++++++++++- tests/various/shregmap.ys | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/tests/various/shregmap.v b/tests/various/shregmap.v index 56e05c2c0..604c2c976 100644 --- a/tests/various/shregmap.v +++ b/tests/various/shregmap.v @@ -1,4 +1,4 @@ -module shregmap_test(input i, clk, output [1:0] q); +module shregmap_static_test(input i, clk, output [1:0] q); reg head = 1'b0; reg [3:0] shift1 = 4'b0000; reg [3:0] shift2 = 4'b0000; @@ -20,3 +20,29 @@ always @(posedge C) r <= { r[DEPTH-2:0], D }; assign Q = r[DEPTH-1]; endmodule + +module shregmap_variable_test(input i, clk, input [1:0] l1, l2, 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[l2], shift1[l1]}; +endmodule + +module $__XILINX_SHREG_(input C, D, input [1:0] L, output Q); +parameter CLKPOL = 1; +parameter ENPOL = 1; +parameter DEPTH = 1; +parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; +reg [DEPTH-1:0] r = INIT; +wire clk = C ^ CLKPOL; +always @(posedge C) + r <= { r[DEPTH-2:0], D }; +assign Q = r[L]; +endmodule diff --git a/tests/various/shregmap.ys b/tests/various/shregmap.ys index ca7f47015..d644a88aa 100644 --- a/tests/various/shregmap.ys +++ b/tests/various/shregmap.ys @@ -1,6 +1,8 @@ read_verilog shregmap.v +design -save read + design -copy-to model $__SHREG_DFF_P_ -hierarchy -top shregmap_test +hierarchy -top shregmap_static_test prep design -save gold @@ -29,3 +31,36 @@ stat design -load gate stat + +########## + +design -load read +design -copy-to model $__XILINX_SHREG_ +hierarchy -top shregmap_variable_test +prep +design -save gold + +simplemap t:$dff t:$dffe +shregmap -tech xilinx + +stat +# show -width +write_verilog -noexpr -norename +select -assert-count 1 t:$_DFF_P_ +select -assert-count 2 t:$__XILINX_SHREG_ + +design -stash gate + +design -import gold -as gold +design -import gate -as gate +design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_ +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 4c9fde87d170fc8d4b729581b055407553951e4c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:48:45 -0700 Subject: [PATCH 446/927] 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 447/927] 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 448/927] 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 449/927] 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 450/927] 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 451/927] 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 452/927] 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 453/927] 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 454/927] 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 455/927] 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 456/927] 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 457/927] 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 458/927] 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 459/927] 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 d69989b8d27eea16d793600b1779661f31161c6c Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Wed, 12 Jun 2019 19:35:05 +0200 Subject: [PATCH 460/927] Rename satgen_algo.h -> algo.h, code cleanup and refactoring --- kernel/algo.h | 239 ++++++++++++++++++++++++++++++++++++++++ kernel/celltypes.h | 9 +- kernel/satgen_algo.h | 201 --------------------------------- passes/opt/opt_rmdff.cc | 93 ++++------------ 4 files changed, 264 insertions(+), 278 deletions(-) create mode 100644 kernel/algo.h delete mode 100644 kernel/satgen_algo.h diff --git a/kernel/algo.h b/kernel/algo.h new file mode 100644 index 000000000..6ab96a875 --- /dev/null +++ b/kernel/algo.h @@ -0,0 +1,239 @@ +/* -*- c++ -*- + * 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. + * + */ + +#ifndef SATGEN_ALGO_H +#define SATGEN_ALGO_H + +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/sigtools.h" +#include + +YOSYS_NAMESPACE_BEGIN + +CellTypes comb_cells_filt() +{ + CellTypes ct; + + ct.setup_internals(); + ct.setup_stdcells(); + + return ct; +} + +struct Netlist { + RTLIL::Module *module; + SigMap sigmap; + dict sigbit_driver_map; + dict> cell_inputs_map; + + Netlist(RTLIL::Module *module) : module(module), sigmap(module) + { + CellTypes ct(module->design); + setup_netlist(module, ct); + } + + Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module) { setup_netlist(module, ct); } + + void setup_netlist(RTLIL::Module *module, const CellTypes &ct) + { + for (auto cell : module->cells()) { + if (ct.cell_known(cell->type)) { + std::set inputs, outputs; + for (auto &port : cell->connections()) { + std::vector bits = sigmap(port.second).to_sigbit_vector(); + if (ct.cell_output(cell->type, port.first)) + outputs.insert(bits.begin(), bits.end()); + else + inputs.insert(bits.begin(), bits.end()); + } + cell_inputs_map[cell] = inputs; + for (auto &bit : outputs) { + sigbit_driver_map[bit] = cell; + }; + } + } + } +}; + +namespace detail +{ +struct NetlistConeWireIter : public std::iterator { + using set_iter_t = std::set::iterator; + + const Netlist &net; + const RTLIL::SigBit *p_sig; + std::stack> dfs_path_stack; + std::set cells_visited; + + NetlistConeWireIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig) {} + + const RTLIL::SigBit &operator*() const { return *p_sig; }; + bool operator!=(const NetlistConeWireIter &other) const { return p_sig != other.p_sig; } + bool operator==(const NetlistConeWireIter &other) const { return p_sig == other.p_sig; } + + void next_sig_in_dag() + { + while (1) { + if (dfs_path_stack.empty()) { + p_sig = NULL; + return; + } + + auto &cell_inputs_iter = dfs_path_stack.top().first; + auto &cell_inputs_iter_guard = dfs_path_stack.top().second; + + cell_inputs_iter++; + if (cell_inputs_iter != cell_inputs_iter_guard) { + p_sig = &(*cell_inputs_iter); + return; + } else { + dfs_path_stack.pop(); + } + } + } + + NetlistConeWireIter &operator++() + { + if (net.sigbit_driver_map.count(*p_sig)) { + auto drv = net.sigbit_driver_map.at(*p_sig); + + if (!cells_visited.count(drv)) { + auto &inputs = net.cell_inputs_map.at(drv); + dfs_path_stack.push(std::make_pair(inputs.begin(), inputs.end())); + cells_visited.insert(drv); + p_sig = &(*dfs_path_stack.top().first); + } else { + next_sig_in_dag(); + } + } else { + next_sig_in_dag(); + } + return *this; + } +}; + +struct NetlistConeWireIterable { + const Netlist &net; + const RTLIL::SigBit *p_sig; + + NetlistConeWireIterable(const Netlist &net, const RTLIL::SigBit *p_sig) : net(net), p_sig(p_sig) {} + + NetlistConeWireIter begin() { return NetlistConeWireIter(net, p_sig); } + NetlistConeWireIter end() { return NetlistConeWireIter(net); } +}; + +struct NetlistConeCellIter : public std::iterator { + const Netlist &net; + const RTLIL::SigBit *p_sig; + + NetlistConeWireIter sig_iter; + + NetlistConeCellIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig), sig_iter(net, p_sig) + { + if ((p_sig != NULL) && (!has_driver_cell(*sig_iter))) { + ++(*this); + } + } + + bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } + + RTLIL::Cell *operator*() const { return net.sigbit_driver_map.at(*sig_iter); }; + + bool operator!=(const NetlistConeCellIter &other) const { return sig_iter != other.sig_iter; } + bool operator==(const NetlistConeCellIter &other) const { return sig_iter == other.sig_iter; } + NetlistConeCellIter &operator++() + { + while (true) { + ++sig_iter; + if (sig_iter.p_sig == NULL) { + return *this; + } + + if (has_driver_cell(*sig_iter)) { + auto cell = net.sigbit_driver_map.at(*sig_iter); + + if (!sig_iter.cells_visited.count(cell)) { + return *this; + } + } + }; + } +}; + +struct NetlistConeCellIterable { + const Netlist &net; + const RTLIL::SigBit *p_sig; + + NetlistConeCellIterable(const Netlist &net, const RTLIL::SigBit *p_sig) : net(net), p_sig(p_sig) {} + + NetlistConeCellIter begin() { return NetlistConeCellIter(net, p_sig); } + NetlistConeCellIter end() { return NetlistConeCellIter(net); } +}; + +struct NetlistConeInputsIter : public std::iterator { + const Netlist &net; + const RTLIL::SigBit *p_sig; + + NetlistConeWireIter sig_iter; + + bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } + + NetlistConeInputsIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig), sig_iter(net, p_sig) + { + if ((p_sig != NULL) && (has_driver_cell(*sig_iter))) { + ++(*this); + } + } + + const RTLIL::SigBit &operator*() const { return *sig_iter; }; + bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } + bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } + NetlistConeInputsIter &operator++() + { + do { + ++sig_iter; + if (sig_iter.p_sig == NULL) { + return *this; + } + } while (has_driver_cell(*sig_iter)); + + return *this; + } +}; + +struct NetlistConeInputsIterable { + const Netlist &net; + const RTLIL::SigBit *p_sig; + + NetlistConeInputsIterable(const Netlist &net, const RTLIL::SigBit *p_sig) : net(net), p_sig(p_sig) {} + + NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, p_sig); } + NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } +}; +} // namespace detail + +detail::NetlistConeWireIterable cone(const Netlist &net, const RTLIL::SigBit &sig) { return detail::NetlistConeWireIterable(net, &sig); } + +// detail::NetlistConeInputsIterable cone_inputs(const RTLIL::SigBit &sig) { return NetlistConeInputsIterable(this, &sig); } +detail::NetlistConeCellIterable cell_cone(const Netlist &net, const RTLIL::SigBit &sig) { return detail::NetlistConeCellIterable(net, &sig); } + +YOSYS_NAMESPACE_END + +#endif diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 4e91eddda..758661c02 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -246,24 +246,24 @@ struct CellTypes cell_types.clear(); } - bool cell_known(RTLIL::IdString type) + bool cell_known(RTLIL::IdString type) const { return cell_types.count(type) != 0; } - bool cell_output(RTLIL::IdString type, RTLIL::IdString port) + bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const { auto it = cell_types.find(type); return it != cell_types.end() && it->second.outputs.count(port) != 0; } - bool cell_input(RTLIL::IdString type, RTLIL::IdString port) + bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const { auto it = cell_types.find(type); return it != cell_types.end() && it->second.inputs.count(port) != 0; } - bool cell_evaluable(RTLIL::IdString type) + bool cell_evaluable(RTLIL::IdString type) const { auto it = cell_types.find(type); return it != cell_types.end() && it->second.is_evaluable; @@ -482,4 +482,3 @@ extern CellTypes yosys_celltypes; YOSYS_NAMESPACE_END #endif - diff --git a/kernel/satgen_algo.h b/kernel/satgen_algo.h deleted file mode 100644 index d475d7d64..000000000 --- a/kernel/satgen_algo.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- c++ -*- - * 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. - * - */ - -#ifndef SATGEN_ALGO_H -#define SATGEN_ALGO_H - -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/sigtools.h" -#include - -YOSYS_NAMESPACE_BEGIN - -struct DriverMap : public std::map>> { - RTLIL::Module *module; - SigMap sigmap; - - using map_t = std::map>>; - - struct DriverMapConeWireIterator : public std::iterator { - using set_iter_t = std::set::iterator; - - DriverMap *drvmap; - const RTLIL::SigBit *sig; - std::stack> dfs; - - DriverMapConeWireIterator(DriverMap *drvmap) : DriverMapConeWireIterator(drvmap, NULL) {} - - DriverMapConeWireIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} - - inline const RTLIL::SigBit &operator*() const { return *sig; }; - inline bool operator!=(const DriverMapConeWireIterator &other) const { return sig != other.sig; } - inline bool operator==(const DriverMapConeWireIterator &other) const { return sig == other.sig; } - inline void operator++() - { - if (drvmap->count(*sig)) { - std::pair> &drv = drvmap->at(*sig); - dfs.push(std::make_pair(drv.second.begin(), drv.second.end())); - sig = &(*dfs.top().first); - } else { - while (1) { - auto &inputs_iter = dfs.top(); - - inputs_iter.first++; - if (inputs_iter.first != inputs_iter.second) { - sig = &(*inputs_iter.first); - return; - } else { - dfs.pop(); - if (dfs.empty()) { - sig = NULL; - return; - } - } - } - } - } - }; - - struct DriverMapConeWireIterable { - DriverMap *drvmap; - const RTLIL::SigBit *sig; - - DriverMapConeWireIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} - - inline DriverMapConeWireIterator begin() { return DriverMapConeWireIterator(drvmap, sig); } - inline DriverMapConeWireIterator end() { return DriverMapConeWireIterator(drvmap); } - }; - - struct DriverMapConeCellIterator : public std::iterator { - DriverMap *drvmap; - const RTLIL::SigBit *sig; - - DriverMapConeWireIterator sig_iter; - - DriverMapConeCellIterator(DriverMap *drvmap) : DriverMapConeCellIterator(drvmap, NULL) {} - - DriverMapConeCellIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig), sig_iter(drvmap, sig) - { - if ((sig != NULL) && (!drvmap->count(*sig_iter))) { - ++(*this); - } - } - - inline RTLIL::Cell *operator*() const - { - std::pair> &drv = drvmap->at(*sig_iter); - return drv.first; - }; - inline bool operator!=(const DriverMapConeCellIterator &other) const { return sig_iter != other.sig_iter; } - inline bool operator==(const DriverMapConeCellIterator &other) const { return sig_iter == other.sig_iter; } - inline void operator++() - { - do { - ++sig_iter; - if (sig_iter.sig == NULL) { - return; - } - } while (!drvmap->count(*sig_iter)); - } - }; - - struct DriverMapConeCellIterable { - DriverMap *drvmap; - const RTLIL::SigBit *sig; - - DriverMapConeCellIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} - - inline DriverMapConeCellIterator begin() { return DriverMapConeCellIterator(drvmap, sig); } - inline DriverMapConeCellIterator end() { return DriverMapConeCellIterator(drvmap); } - }; - - struct DriverMapConeInputsIterator : public std::iterator { - DriverMap *drvmap; - const RTLIL::SigBit *sig; - - DriverMapConeWireIterator sig_iter; - - DriverMapConeInputsIterator(DriverMap *drvmap) : DriverMapConeInputsIterator(drvmap, NULL) {} - - DriverMapConeInputsIterator(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig), sig_iter(drvmap, sig) - { - if ((sig != NULL) && (drvmap->count(*sig_iter))) { - ++(*this); - } - } - - inline const RTLIL::SigBit& operator*() const - { - return *sig_iter; - }; - inline bool operator!=(const DriverMapConeInputsIterator &other) const { return sig_iter != other.sig_iter; } - inline bool operator==(const DriverMapConeInputsIterator &other) const { return sig_iter == other.sig_iter; } - inline void operator++() - { - do { - ++sig_iter; - if (sig_iter.sig == NULL) { - return; - } - } while (drvmap->count(*sig_iter)); - } - }; - - struct DriverMapConeInputsIterable { - DriverMap *drvmap; - const RTLIL::SigBit *sig; - - DriverMapConeInputsIterable(DriverMap *drvmap, const RTLIL::SigBit *sig) : drvmap(drvmap), sig(sig) {} - - inline DriverMapConeInputsIterator begin() { return DriverMapConeInputsIterator(drvmap, sig); } - inline DriverMapConeInputsIterator end() { return DriverMapConeInputsIterator(drvmap); } - }; - - DriverMap(RTLIL::Module *module) : module(module), sigmap(module) - { - CellTypes ct; - ct.setup_internals(); - ct.setup_stdcells(); - - for (auto &it : module->cells_) { - if (ct.cell_known(it.second->type)) { - std::set inputs, outputs; - for (auto &port : it.second->connections()) { - std::vector bits = sigmap(port.second).to_sigbit_vector(); - if (ct.cell_output(it.second->type, port.first)) - outputs.insert(bits.begin(), bits.end()); - else - inputs.insert(bits.begin(), bits.end()); - } - std::pair> drv(it.second, inputs); - for (auto &bit : outputs) - (*this)[bit] = drv; - } - } - } - - DriverMapConeWireIterable cone(const RTLIL::SigBit &sig) { return DriverMapConeWireIterable(this, &sig); } - DriverMapConeInputsIterable cone_inputs(const RTLIL::SigBit &sig) { return DriverMapConeInputsIterable(this, &sig); } - DriverMapConeCellIterable cell_cone(const RTLIL::SigBit &sig) { return DriverMapConeCellIterable(this, &sig); } -}; - -YOSYS_NAMESPACE_END - -#endif diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 4b9fe5823..b5a5735e7 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -21,7 +21,7 @@ #include "kernel/register.h" #include "kernel/rtlil.h" #include "kernel/satgen.h" -#include "kernel/satgen_algo.h" +#include "kernel/algo.h" #include "kernel/sigtools.h" #include #include @@ -32,6 +32,7 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; +std::map netlists; bool keepdc; bool sat; @@ -459,9 +460,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) if (sat && has_init) { std::vector removed_sigbits; - DriverMap drvmap(mod); + if (!netlists.count(mod)) { + netlists.emplace(mod, Netlist(mod, comb_cells_filt())); + } + + Netlist &net = netlists.at(mod); - // for (auto &sigbit : sig_q.bits()) { for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; @@ -470,83 +474,27 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) continue; } - std::map sat_pi; - ezSatPtr ez; - SatGen satgen(ez.get(), &drvmap.sigmap); - std::set ez_cells; - std::vector modelExpressions; - std::vector modelValues; + SatGen satgen(ez.get(), &net.sigmap); - log("Optimizing: %s\n", log_id(q_sigbit.wire)); - log(" Cells:"); - for (const auto &cell : drvmap.cell_cone(d_sigbit)) { - if (ez_cells.count(cell) == 0) { - log(" %s\n", log_id(cell)); - if (!satgen.importCell(cell)) - log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), - RTLIL::id2cstr(cell->type)); - ez_cells.insert(cell); - } + for (const auto &cell : cell_cone(net, d_sigbit)) { + if (!satgen.importCell(cell)) + log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), + RTLIL::id2cstr(cell->type)); } RTLIL::Const sigbit_init_val = val_init.extract(position); - int reg_init = satgen.importSigSpec(sigbit_init_val).front(); + int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); - int output_a = satgen.importSigSpec(d_sigbit).front(); - modelExpressions.push_back(output_a); + int q_sat_pi = satgen.importSigBit(q_sigbit); + int d_sat_pi = satgen.importSigBit(d_sigbit); - log(" Wires:"); - for (const auto &sig : drvmap.cone_inputs(d_sigbit)) { - if (sat_pi.count(sig) == 0) { - sat_pi[sig] = satgen.importSigSpec(sig).front(); - modelExpressions.push_back(sat_pi[sig]); - - if (sig == q_sigbit) { - ez->assume(ez->IFF(sat_pi[sig], reg_init)); - } - - if (sig.wire) { - log(" %s\n", log_id(sig.wire)); - } - } - } - - bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, reg_init)); - // bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, ez->NOT(reg_init))); - if (ez->getSolverTimoutStatus()) - log("Timeout\n"); - - log("Success: %d\n", success); - - // satgen.signals_eq(big_lhs, big_rhs, timestep); - - // auto iterable = drvmap.cone(d_sigbit); - - // // for (const auto &sig : drvmap.cone(d_sigbit)) - // for(auto begin=iterable.begin(); begin != iterable.end(); ++begin) - // { - // if (drvmap.count(*begin)) { - // if (drvmap.at(*begin).first) - // log("Running: %s\n", log_id(drvmap.at(*begin).first)); - // } - - // if ((*begin).wire) { - // log("Running: %s\n", log_id((*begin).wire)); - // } - // } + // log("DFF: %s", log_id(net.sigbit_driver_map[q_sigbit])); + bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); char str[1024]; - // sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", log_id(d_sigbit.wire), d_sigbit.offset, - // sigbit_init_val.as_string().c_str(), log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); - // log("Running: %s\n", str); - - // log_flush(); - - // pass->call(mod->design, str); - // if (mod->design->scratchpad_get_bool("sat.success", false)) { - if (success) { + if (!counter_example_found) { sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); log("Running: %s\n", str); log_flush(); @@ -561,6 +509,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) } } + return false; delete_dff: @@ -603,9 +552,9 @@ struct OptRmdffPass : public Pass { break; } extra_args(args, argidx, design); + netlists.clear(); - for (auto module : design->selected_modules()) - { + for (auto module : design->selected_modules()) { pool driven_bits; dict init_bits; From 2e7b3eee400a4d845398be8e15ca023672f05270 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:43:43 -0700 Subject: [PATCH 461/927] 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 462/927] 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 463/927] 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 464/927] 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 465/927] 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 466/927] 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 467/927] 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 468/927] 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 469/927] 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 470/927] 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 471/927] 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 472/927] 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 473/927] 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 4912567cbff3c24e9cddea0b59287ec53321af7a Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 13 Jun 2019 15:42:45 +0200 Subject: [PATCH 474/927] Pass SigBit by value to Netlist algorithms --- kernel/algo.h | 133 ++++++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/kernel/algo.h b/kernel/algo.h index 6ab96a875..05467c60a 100644 --- a/kernel/algo.h +++ b/kernel/algo.h @@ -74,25 +74,43 @@ struct Netlist { namespace detail { -struct NetlistConeWireIter : public std::iterator { +struct NetlistConeWireIter : public std::iterator { using set_iter_t = std::set::iterator; const Netlist &net; - const RTLIL::SigBit *p_sig; + RTLIL::SigBit sig; + bool sentinel; + std::stack> dfs_path_stack; std::set cells_visited; - NetlistConeWireIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig) {} + NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true) {} - const RTLIL::SigBit &operator*() const { return *p_sig; }; - bool operator!=(const NetlistConeWireIter &other) const { return p_sig != other.p_sig; } - bool operator==(const NetlistConeWireIter &other) const { return p_sig == other.p_sig; } + NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig), sentinel(false) {} + + const RTLIL::SigBit &operator*() const { return sig; }; + bool operator!=(const NetlistConeWireIter &other) const + { + if (sentinel || other.sentinel) { + return sentinel != other.sentinel; + } else { + return sig != other.sig; + } + } + + bool operator==(const NetlistConeWireIter &other) const { + if (sentinel || other.sentinel) { + return sentinel == other.sentinel; + } else { + return sig == other.sig; + } + } void next_sig_in_dag() { while (1) { if (dfs_path_stack.empty()) { - p_sig = NULL; + sentinel = true; return; } @@ -101,7 +119,7 @@ struct NetlistConeWireIter : public std::iterator { +struct NetlistConeCellIter : public std::iterator { const Netlist &net; - const RTLIL::SigBit *p_sig; NetlistConeWireIter sig_iter; - NetlistConeCellIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig), sig_iter(net, p_sig) + NetlistConeCellIter(const Netlist &net) : net(net), sig_iter(net) {} + + NetlistConeCellIter(const Netlist &net, RTLIL::SigBit sig) : net(net), sig_iter(net, sig) { - if ((p_sig != NULL) && (!has_driver_cell(*sig_iter))) { + if ((!sig_iter.sentinel) && (!has_driver_cell(*sig_iter))) { ++(*this); } } @@ -162,7 +181,7 @@ struct NetlistConeCellIter : public std::iterator { - const Netlist &net; - const RTLIL::SigBit *p_sig; +// struct NetlistConeInputsIter : public std::iterator { +// const Netlist &net; +// RTLIL::SigBit sig; - NetlistConeWireIter sig_iter; +// NetlistConeWireIter sig_iter; - bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } +// bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } - NetlistConeInputsIter(const Netlist &net, const RTLIL::SigBit *p_sig = NULL) : net(net), p_sig(p_sig), sig_iter(net, p_sig) - { - if ((p_sig != NULL) && (has_driver_cell(*sig_iter))) { - ++(*this); - } - } +// NetlistConeInputsIter(const Netlist &net, RTLIL::SigBit sig = NULL) : net(net), sig(sig), sig_iter(net, sig) +// { +// if ((sig != NULL) && (has_driver_cell(sig_iter))) { +// ++(*this); +// } +// } - const RTLIL::SigBit &operator*() const { return *sig_iter; }; - bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } - bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } - NetlistConeInputsIter &operator++() - { - do { - ++sig_iter; - if (sig_iter.p_sig == NULL) { - return *this; - } - } while (has_driver_cell(*sig_iter)); +// const RTLIL::SigBit &operator*() const { return sig_iter; }; +// bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } +// bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } +// NetlistConeInputsIter &operator++() +// { +// do { +// ++sig_iter; +// if (sig_iter->empty()) { +// return *this; +// } +// } while (has_driver_cell(sig_iter)); - return *this; - } -}; +// return *this; +// } +// }; -struct NetlistConeInputsIterable { - const Netlist &net; - const RTLIL::SigBit *p_sig; +// struct NetlistConeInputsIterable { +// const Netlist &net; +// RTLIL::SigBit sig; - NetlistConeInputsIterable(const Netlist &net, const RTLIL::SigBit *p_sig) : net(net), p_sig(p_sig) {} +// NetlistConeInputsIterable(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig) {} - NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, p_sig); } - NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } -}; +// NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, sig); } +// NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } +// }; } // namespace detail -detail::NetlistConeWireIterable cone(const Netlist &net, const RTLIL::SigBit &sig) { return detail::NetlistConeWireIterable(net, &sig); } +detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig) { return detail::NetlistConeWireIterable(net, net.sigmap(sig)); } -// detail::NetlistConeInputsIterable cone_inputs(const RTLIL::SigBit &sig) { return NetlistConeInputsIterable(this, &sig); } -detail::NetlistConeCellIterable cell_cone(const Netlist &net, const RTLIL::SigBit &sig) { return detail::NetlistConeCellIterable(net, &sig); } +// detail::NetlistConeInputsIterable cone_inputs(RTLIL::SigBit sig) { return NetlistConeInputsIterable(this, &sig); } +detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig) { return detail::NetlistConeCellIterable(net, net.sigmap(sig)); } YOSYS_NAMESPACE_END From 9d34cea65af5b34ce0930fb892fca6742db898ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 08:22:22 -0700 Subject: [PATCH 475/927] 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 476/927] 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 477/927] 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 8665f48879526f8f3ed79629f28a8686ed78a8ad Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 13 Jun 2019 19:35:37 +0200 Subject: [PATCH 478/927] Implement disconnection of constant register bits --- kernel/algo.h | 115 +++++++++++++++++++++++++++++----------- passes/opt/opt_rmdff.cc | 36 ++++++++----- 2 files changed, 108 insertions(+), 43 deletions(-) diff --git a/kernel/algo.h b/kernel/algo.h index 05467c60a..9626c780e 100644 --- a/kernel/algo.h +++ b/kernel/algo.h @@ -40,16 +40,39 @@ CellTypes comb_cells_filt() struct Netlist { RTLIL::Module *module; SigMap sigmap; + CellTypes ct; dict sigbit_driver_map; dict> cell_inputs_map; - Netlist(RTLIL::Module *module) : module(module), sigmap(module) + Netlist(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) { setup_netlist(module, ct); } + + Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module), ct(ct) { setup_netlist(module, ct); } + + RTLIL::Cell *driver_cell(RTLIL::SigBit sig) const { - CellTypes ct(module->design); - setup_netlist(module, ct); + sig = sigmap(sig); + if (!sigbit_driver_map.count(sig)) { + return NULL; + } + + return sigbit_driver_map.at(sig); } - Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module) { setup_netlist(module, ct); } + RTLIL::SigBit& driver_port(RTLIL::SigBit sig) + { + RTLIL::Cell *cell = driver_cell(sig); + + for (auto &port : cell->connections_) { + if (ct.cell_output(cell->type, port.first)) { + RTLIL::SigSpec port_sig = sigmap(port.second); + for (int i = 0; i < GetSize(port_sig); i++) { + if (port_sig[i] == sig) { + return port.second[i]; + } + } + } + } + } void setup_netlist(RTLIL::Module *module, const CellTypes &ct) { @@ -80,13 +103,17 @@ struct NetlistConeWireIter : public std::iterator> dfs_path_stack; std::set cells_visited; - NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true) {} + NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true), cell_filter(NULL) {} - NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig), sentinel(false) {} + NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) + : net(net), sig(sig), sentinel(false), cell_filter(cell_filter) + { + } const RTLIL::SigBit &operator*() const { return sig; }; bool operator!=(const NetlistConeWireIter &other) const @@ -98,7 +125,8 @@ struct NetlistConeWireIter : public std::iteratorcell_known(cell->type))) { + next_sig_in_dag(); + return *this; + } + + auto &inputs = net.cell_inputs_map.at(cell); + dfs_path_stack.push(std::make_pair(inputs.begin(), inputs.end())); + cells_visited.insert(cell); + sig = (*dfs_path_stack.top().first); return *this; } }; @@ -150,10 +185,13 @@ struct NetlistConeWireIter : public std::iteratorcell_known(cell->type))) { + continue; + } + + if (!sig_iter.cells_visited.count(cell)) { + return *this; + } + } } }; struct NetlistConeCellIterable { const Netlist &net; RTLIL::SigBit sig; + CellTypes *cell_filter; - NetlistConeCellIterable(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig) {} + NetlistConeCellIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) + { + } - NetlistConeCellIter begin() { return NetlistConeCellIter(net, sig); } + NetlistConeCellIter begin() { return NetlistConeCellIter(net, sig, cell_filter); } NetlistConeCellIter end() { return NetlistConeCellIter(net); } }; @@ -248,10 +295,16 @@ struct NetlistConeCellIterable { // }; } // namespace detail -detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig) { return detail::NetlistConeWireIterable(net, net.sigmap(sig)); } +detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) +{ + return detail::NetlistConeWireIterable(net, net.sigmap(sig), cell_filter = cell_filter); +} // detail::NetlistConeInputsIterable cone_inputs(RTLIL::SigBit sig) { return NetlistConeInputsIterable(this, &sig); } -detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig) { return detail::NetlistConeCellIterable(net, net.sigmap(sig)); } +detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) +{ + return detail::NetlistConeCellIterable(net, net.sigmap(sig), cell_filter); +} YOSYS_NAMESPACE_END diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index b5a5735e7..c5db344e8 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -33,6 +33,8 @@ SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; std::map netlists; +std::map comb_filters; + bool keepdc; bool sat; @@ -263,7 +265,7 @@ delete_dlatch: return true; } -bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) +bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) { RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::Const val_cp, val_rp, val_rv, val_ep; @@ -461,7 +463,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) std::vector removed_sigbits; if (!netlists.count(mod)) { - netlists.emplace(mod, Netlist(mod, comb_cells_filt())); + netlists.emplace(mod, Netlist(mod)); + comb_filters.emplace(mod, comb_cells_filt()); } Netlist &net = netlists.at(mod); @@ -477,7 +480,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) ezSatPtr ez; SatGen satgen(ez.get(), &net.sigmap); - for (const auto &cell : cell_cone(net, d_sigbit)) { + for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { if (!satgen.importCell(cell)) log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); @@ -489,17 +492,25 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); - // log("DFF: %s", log_id(net.sigbit_driver_map[q_sigbit])); - bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); - char str[1024]; + if (position == 14) { + counter_example_found = false; + } + if (!counter_example_found) { - sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); - log("Running: %s\n", str); - log_flush(); - pass->call(mod->design, str); - // mod->connect(q_sigbit, sigbit_init_val); + + RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); + RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); + + for (auto &conn : mod->connections_) + net.sigmap(conn.first).replace(driver_port, dummy_wire, &conn.first); + + remove_init_attr(driver_port); + driver_port = dummy_wire; + + mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); + removed_sigbits.push_back(position); } } @@ -553,6 +564,7 @@ struct OptRmdffPass : public Pass { } extra_args(args, argidx, design); netlists.clear(); + comb_filters.clear(); for (auto module : design->selected_modules()) { pool driven_bits; @@ -631,7 +643,7 @@ struct OptRmdffPass : public Pass { for (auto &id : dff_list) { if (module->cell(id) != nullptr && - handle_dff(module, module->cells_[id], this)) + handle_dff(module, module->cells_[id])) total_count++; } From d39a5a77a9ec58ea97af91c961b02b5a55deaaa7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Jun 2019 13:13:48 -0700 Subject: [PATCH 479/927] 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 480/927] 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 481/927] 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 482/927] 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 483/927] 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 291b36afeb1075b7c6329d1e57594ed3e6b71581 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 11:35:45 +0200 Subject: [PATCH 484/927] Some cleanup, revert sat.cc --- passes/opt/opt_rmdff.cc | 17 ++++++++++------- passes/sat/sat.cc | 7 +------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index c5db344e8..41bbdcd57 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -460,15 +460,19 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) } if (sat && has_init) { - std::vector removed_sigbits; + bool removed_sigbits = false; + // Create netlist for the module if not already available if (!netlists.count(mod)) { netlists.emplace(mod, Netlist(mod)); comb_filters.emplace(mod, comb_cells_filt()); } + // Load netlist for the module from the pool Netlist &net = netlists.at(mod); + + // For each register bit, try to prove that it cannot change from the initial value. If so, remove it for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; @@ -480,6 +484,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) ezSatPtr ez; SatGen satgen(ez.get(), &net.sigmap); + // Create SAT instance only for the cells that influence the register bit combinatorially for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { if (!satgen.importCell(cell)) log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), @@ -492,12 +497,10 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); + // Try to find out whether the register bit can change under some circumstances bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); - if (position == 14) { - counter_example_found = false; - } - + // If the register bit cannot change, we can replace it with a constant if (!counter_example_found) { RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); @@ -511,11 +514,11 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); - removed_sigbits.push_back(position); + removed_sigbits = true; } } - if (!removed_sigbits.empty()) { + if (removed_sigbits) { return true; } } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 4492fc2b7..cbba738f0 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1548,20 +1548,17 @@ struct SatPass : public Pass { print_proof_failed(); tip_failed: - design->scratchpad_set_bool("sat.success", false); if (verify) { log("\n"); log_error("Called with -verify and proof did fail!\n"); } - if (0) { + if (0) tip_success: - design->scratchpad_set_bool("sat.success", true); if (falsify) { log("\n"); log_error("Called with -falsify and proof did succeed!\n"); } - } } else { @@ -1631,7 +1628,6 @@ struct SatPass : public Pass { if (sathelper.solve()) { - design->scratchpad_set_bool("sat.success", false); if (max_undef) { log("SAT model found. maximizing number of undefs.\n"); sathelper.maximize_undefs(); @@ -1671,7 +1667,6 @@ struct SatPass : public Pass { } else { - design->scratchpad_set_bool("sat.success", true); if (sathelper.gotTimeout) goto timeout; if (rerun_counter) From 53695e6729e8ae603be7e7cd9bc8b29758d61a11 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 11:39:24 +0200 Subject: [PATCH 485/927] Prepare for situation when port of the signal cannot be found --- kernel/algo.h | 8 +++++++- passes/opt/opt_rmdff.cc | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/algo.h b/kernel/algo.h index 9626c780e..f029ad6ab 100644 --- a/kernel/algo.h +++ b/kernel/algo.h @@ -58,10 +58,14 @@ struct Netlist { return sigbit_driver_map.at(sig); } - RTLIL::SigBit& driver_port(RTLIL::SigBit sig) + RTLIL::SigSpec driver_port(RTLIL::SigBit sig) { RTLIL::Cell *cell = driver_cell(sig); + if (!cell) { + return RTLIL::SigSpec(); + } + for (auto &port : cell->connections_) { if (ct.cell_output(cell->type, port.first)) { RTLIL::SigSpec port_sig = sigmap(port.second); @@ -72,6 +76,8 @@ struct Netlist { } } } + + return RTLIL::SigSpec(); } void setup_netlist(RTLIL::Module *module, const CellTypes &ct) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 41bbdcd57..cf89ac096 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -503,7 +503,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If the register bit cannot change, we can replace it with a constant if (!counter_example_found) { - RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); + RTLIL::SigSpec driver_port = net.driver_port(q_sigbit); RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); for (auto &conn : mod->connections_) From 8451cbea896d2b441b5c78eb2813790616d10b84 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 12:14:02 +0200 Subject: [PATCH 486/927] Move netlist helper module to passes/opt for the time being --- kernel/algo.h => passes/opt/netlist.h | 0 passes/opt/opt_rmdff.cc | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename kernel/algo.h => passes/opt/netlist.h (100%) diff --git a/kernel/algo.h b/passes/opt/netlist.h similarity index 100% rename from kernel/algo.h rename to passes/opt/netlist.h diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index f44e6e58c..0ab91ca9e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -21,8 +21,8 @@ #include "kernel/register.h" #include "kernel/rtlil.h" #include "kernel/satgen.h" -#include "kernel/algo.h" #include "kernel/sigtools.h" +#include "netlist.h" #include #include From 95665730540c0fd7c76690f28d0fd6b5f13f2223 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 14 Jun 2019 12:02:12 +0100 Subject: [PATCH 487/927] 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 488/927] 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 489/927] 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 490/927] 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 491/927] 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 492/927] 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 493/927] 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 494/927] 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 495/927] 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 496/927] 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 497/927] 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 498/927] 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 499/927] 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 500/927] 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 501/927] 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 502/927] 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 503/927] 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 504/927] 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 b63b2a0bd4552a7dbe0d2c4a15d4e3a1b0e2022d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:50:24 -0700 Subject: [PATCH 505/927] Revert "Remove wide mux inference" This reverts commit 738fdfe8f55e18ac7f315cd68c117eae370004ca. --- 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, 195 insertions(+), 3 deletions(-) create mode 100644 techlibs/xilinx/mux_map.v diff --git a/CHANGELOG b/CHANGELOG index 44e32c6a8..e74af6b65 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - "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 1a652eb27..59fd61cf0 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_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index b5114758c..f139dc5d5 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -154,3 +154,123 @@ 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 new file mode 100644 index 000000000..0fa8db736 --- /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_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 a11648873..63ede275f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -72,6 +72,9 @@ 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"); @@ -93,7 +96,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, abc, arch; - bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; + bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl, nomux; void clear_flags() YS_OVERRIDE { @@ -108,6 +111,7 @@ struct SynthXilinxPass : public ScriptPass nobram = false; nodram = false; nosrl = false; + nomux = false; arch = "xc7"; } @@ -171,6 +175,10 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } + if (args[argidx] == "-nomux") { + nomux = true; + continue; + } if (args[argidx] == "-abc9") { abc = "abc9"; continue; @@ -219,11 +227,15 @@ 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 - if (!nosrl || help_mode) - run("pmux2shiftx", "(skip if '-nosrl')"); + // 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 @@ -261,6 +273,10 @@ 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) { @@ -275,6 +291,8 @@ 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 13e2e8df11b4af9ce5512508caad793c659b9479 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:50:30 -0700 Subject: [PATCH 506/927] Update CHANGELOG --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e74af6b65..13cfb812b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,12 +17,13 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "rename -src" - Added "equiv_opt" pass - Added "read_aiger" frontend + - Added "shregmap -tech xilinx" - 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" - - "synth_xilinx" to now infer wide multiplexers + - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) + - "synth_xilinx" to now infer wide multiplexers (-nomux to disable) Yosys 0.7 .. Yosys 0.8 From 2d85725604271c658382e8fdd8ff28275fb94b03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:07:56 -0700 Subject: [PATCH 507/927] 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 508/927] 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 509/927] 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 4d7516f45956c6dd3647dc235e3a29c0c7ecc816 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: [PATCH 510/927] 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 9b55e69755a00a46c97104f344c0ee7065a8f13c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: [PATCH 511/927] 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 512/927] 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 513/927] 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 514/927] 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 515/927] 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 1ec450d6bf34a7aec9b0469b6f295847eb658160 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 12:08:03 -0700 Subject: [PATCH 516/927] 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 63ede275f..7b20a7132 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 c23bbc429103ca84cb8a9cfb674aacf7d14109c6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 16 Jun 2019 23:12:03 +0200 Subject: [PATCH 517/927] Add timescale and generated-by header to yosys-smtbmc MkVcd Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ab20a4af2..cea0fc56c 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1023,6 +1023,8 @@ class MkVcd: assert t >= self.t if t != self.t: if self.t == -1: + print("$version Generated by Yosys-SMTBMC $end", file=self.f) + print("$timescale 1ns $end", file=self.f) print("$var integer 32 t smt_step $end", file=self.f) print("$var event 1 ! smt_clock $end", file=self.f) From 7250c57c5a05139ca03544a31fe40b52e4e73486 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 10:28:51 -0700 Subject: [PATCH 518/927] 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 519/927] 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 520/927] 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 521/927] 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 522/927] &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 523/927] 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 524/927] 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 525/927] 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 526/927] 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 527/927] 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 528/927] 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 529/927] 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 530/927] 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 6a4025b5eef3ea96a8a7cdb0046cb2193cfa08e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 12:37:46 -0700 Subject: [PATCH 531/927] Remove unncessary header --- frontends/aiger/aigerparse.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3b53b0086..b98b36319 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 7324a4c2cd0132f792f4fade1a77aeceae46bd85 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 12:47:12 -0700 Subject: [PATCH 532/927] Remove iterator based Module::remove as per @cliffordwolf --- kernel/rtlil.cc | 13 +++---------- kernel/rtlil.h | 1 - passes/techmap/abc9.cc | 13 ++++++------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f732b56b0..3990ec283 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1565,21 +1565,14 @@ 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); + auto it = cells_.find(cell->name); + log_assert(it != cells_.end()); log_assert(refcount_cells_ == 0); - it = cells_.erase(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 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); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2f670dba2..7b13239f2 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -510,16 +510,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } vector boxes; - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { + RTLIL::Cell *cell = it->second; if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { - it = module->remove(it); + 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; + boxes.emplace_back(cell); } std::map cell_stats; @@ -620,8 +619,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto cell : boxes) - module->remove(cell); + for (auto cell : boxes) + module->remove(cell); // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { From 468c41d997477aa6c67a8b97bc4d9dcff185b815 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 17 Jun 2019 14:45:11 -0700 Subject: [PATCH 533/927] Support ~ for home directory This is tested on Linux only v2: Wrap functioanlity in ifndef _WIN32 (eddiehung) Find '~/' instead of '~' (cliffordwolf) Signed-off-by: Ben Widawsky --- kernel/yosys.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 377572fc2..94d6d675f 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -651,6 +651,10 @@ void rewrite_filename(std::string &filename) filename = filename.substr(1, GetSize(filename)-2); if (filename.substr(0, 2) == "+/") filename = proc_share_dirname() + filename.substr(2); +#ifndef _WIN32 + if (filename.substr(0, 2) == "~/") + filename = filename.replace(0, 1, getenv("HOME")); +#endif } #ifdef YOSYS_ENABLE_TCL From 4a18e19fb86f5729ca764d5b0ee338f558f90a43 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 17 Jun 2019 14:45:48 -0700 Subject: [PATCH 534/927] Support filename rewrite in backends Signed-off-by: Ben Widawsky --- backends/aiger/aiger.cc | 1 + backends/ilang/ilang_backend.cc | 1 + backends/json/json.cc | 1 + backends/protobuf/protobuf.cc | 1 + 4 files changed, 4 insertions(+) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index dfe506c66..d685c5638 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -776,6 +776,7 @@ struct AigerBackend : public Backend { writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { + rewrite_filename(filename); std::ofstream mapf; mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 04d1ee311..b4ba2b03f 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -483,6 +483,7 @@ struct DumpPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc); if (ff->fail()) { diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..5022d5da1 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -525,6 +525,7 @@ struct JsonPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), std::ofstream::trunc); if (ff->fail()) { diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index 549fc73ae..fff110bb0 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -336,6 +336,7 @@ struct ProtobufPass : public Pass { std::stringstream buf; if (!filename.empty()) { + rewrite_filename(filename); std::ofstream *ff = new std::ofstream; ff->open(filename.c_str(), std::ofstream::trunc); if (ff->fail()) { From df6576edc83817b692d2096e806bd822f3fda430 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 19 Jun 2019 05:22:13 +0000 Subject: [PATCH 535/927] In RTLIL::Module::check(), check process invariants. --- kernel/rtlil.cc | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 790ba52a3..a09f4a0d1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1381,7 +1381,34 @@ void RTLIL::Module::check() for (auto &it : processes) { log_assert(it.first == it.second->name); log_assert(!it.first.empty()); - // FIXME: More checks here.. + log_assert(it.second->root_case.compare.empty()); + std::vector all_cases = {&it.second->root_case}; + for (size_t i = 0; i < all_cases.size(); i++) { + for (auto &switch_it : all_cases[i]->switches) { + for (auto &case_it : switch_it->cases) { + for (auto &compare_it : case_it->compare) { + log_assert(switch_it->signal.size() == compare_it.size()); + } + all_cases.push_back(case_it); + } + } + } + for (auto &sync_it : it.second->syncs) { + switch (sync_it->type) { + case SyncType::ST0: + case SyncType::ST1: + case SyncType::STp: + case SyncType::STn: + case SyncType::STe: + log_assert(!sync_it->signal.empty()); + break; + case SyncType::STa: + case SyncType::STg: + case SyncType::STi: + log_assert(sync_it->signal.empty()); + break; + } + } } for (auto &it : connections_) { From addf01d45dd795b4fe711012facbe43dd7c2eae7 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 19 Jun 2019 05:22:40 +0000 Subject: [PATCH 536/927] Explain exact semantics of switch and case rules in the manual. --- manual/CHAPTER_Overview.tex | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 2feb0f1cb..1a25c477f 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -350,6 +350,18 @@ and this bit is a one (the second ``1'').} for {\tt \textbackslash{}reset == 1} sets {\tt \$0\textbackslash{}q[0:0]} to the value of {\tt \textbackslash{}d} if {\tt \textbackslash{}enable} is active (lines $6 \dots 11$). +A case can specify zero or more compare values that will determine whether it matches. Each of the compare values +must be the exact same width as the control signal. When more than one compare value is specified, the case matches +if any of them matches the control signal; when zero compare values are specified, the case always matches (i.e. +it is the default case). + +A switch prioritizes cases from first to last: multiple cases can match, but only the first matched case becomes +active. This normally synthesizes to a priority encoder. The {\tt parallel\_case} attribute allows passes to assume +that no more than one case will match, and {\tt full\_case} attribute allows passes to assume that exactly one +case will match; if these invariants are ever dynamically violated, the behavior is undefined. These attributes +are useful when an invariant invisible to the synthesizer causes the control signal to never take certain +bit patterns. + The lines $13 \dots 16$ then cause {\tt \textbackslash{}q} to be updated whenever there is a positive clock edge on {\tt \textbackslash{}clock} or {\tt \textbackslash{}reset}. From 6d64e242ba8214f7bceb35f688b544f56d49cea1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 11:25:11 +0200 Subject: [PATCH 537/927] Fix handling of "logic" variables with initial value Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ea8e457e8..5f3d713d3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -345,7 +345,7 @@ module_arg_opt_assignment: if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) { AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; - if (ast_stack.back()->children.back()->is_reg) + if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); else ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); @@ -1360,7 +1360,7 @@ wire_name_and_opt_assign: wire_name '=' expr { AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; - if (astbuf1->is_reg) + if (astbuf1->is_reg || astbuf1->is_logic) ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3)))); else ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3)); From 8d0cd529c936b1c0a38d7a71a4457bd84c8b3efe Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 11:37:11 +0200 Subject: [PATCH 538/927] Add defaultvalue attribute Signed-off-by: Clifford Wolf --- README.md | 4 ++++ frontends/verilog/verilog_parser.y | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/README.md b/README.md index 94ea9538f..637703a7f 100644 --- a/README.md +++ b/README.md @@ -350,6 +350,10 @@ Verilog Attributes and non-standard features through the synthesis. When entities are combined, a new |-separated string is created that contains all the string from the original entities. +- The ``defaultvalue`` attribute is used to store default values for + module inputs. The attribute is attached to the input wire by the HDL + front-end when the input is declared with a default value. + - In addition to the ``(* ... *)`` attribute syntax, Yosys supports the non-standard ``{* ... *}`` attribute syntax to set default attributes for everything that comes after the ``{* ... *}`` statement. (Reset diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5f3d713d3..ebb4369c3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -345,6 +345,12 @@ module_arg_opt_assignment: if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) { AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; + if (ast_stack.back()->children.back()->is_input) { + AstNode *n = ast_stack.back()->children.back(); + if (n->attributes.count("\\defaultvalue")) + delete n->attributes.at("\\defaultvalue"); + n->attributes["\\defaultvalue"] = $2; + } else if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic) ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2)))); else @@ -1360,6 +1366,11 @@ wire_name_and_opt_assign: wire_name '=' expr { AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; + if (astbuf1->is_input) { + if (astbuf1->attributes.count("\\defaultvalue")) + delete astbuf1->attributes.at("\\defaultvalue"); + astbuf1->attributes["\\defaultvalue"] = $3; + } else if (astbuf1->is_reg || astbuf1->is_logic) ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3)))); else From 3da5288ce096befb844476907a2c6020aae62b8b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 11:49:20 +0200 Subject: [PATCH 539/927] Use input default values in hierarchy pass Signed-off-by: Clifford Wolf --- passes/hierarchy/hierarchy.cc | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 24e64a9b2..213437c01 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -591,6 +591,9 @@ struct HierarchyPass : public Pass { log(" module instances when the width does not match the module port. This\n"); log(" option disables this behavior.\n"); log("\n"); + log(" -nodefaults\n"); + log(" do not resolve input port default values\n"); + log("\n"); log(" -nokeep_asserts\n"); log(" per default this pass sets the \"keep\" attribute on all modules\n"); log(" that directly or indirectly contain one or more formal properties.\n"); @@ -645,6 +648,7 @@ struct HierarchyPass : public Pass { bool generate_mode = false; bool keep_positionals = false; bool keep_portwidths = false; + bool nodefaults = false; bool nokeep_asserts = false; std::vector generate_cells; std::vector generate_ports; @@ -712,6 +716,10 @@ struct HierarchyPass : public Pass { keep_portwidths = true; continue; } + if (args[argidx] == "-nodefaults") { + nodefaults = true; + continue; + } if (args[argidx] == "-nokeep_asserts") { nokeep_asserts = true; continue; @@ -940,6 +948,36 @@ struct HierarchyPass : public Pass { } } + if (!nodefaults) + { + dict> defaults_db; + + for (auto module : design->modules()) + for (auto wire : module->wires()) + if (wire->port_input && wire->attributes.count("\\defaultvalue")) + defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); + + for (auto module : design->modules()) + for (auto cell : module->cells()) + { + if (defaults_db.count(cell->type) == 0) + continue; + + if (keep_positionals) { + bool found_positionals = false; + for (auto &conn : cell->connections()) + if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') + found_positionals = true; + if (found_positionals) + continue; + } + + for (auto &it : defaults_db.at(cell->type)) + if (!cell->hasPort(it.first)) + cell->setPort(it.first, it.second); + } + } + std::set blackbox_derivatives; std::vector design_modules = design->modules(); From fa5fc3f6afd9eb27c1f52244b60cbeb77aa2e26c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 12:12:08 +0200 Subject: [PATCH 540/927] Add defvalue test, minor autotest fixes for .sv files Signed-off-by: Clifford Wolf --- tests/simple/defvalue.sv | 22 ++++++++++++++++++++++ tests/tools/autotest.sh | 29 +++++++++++++++-------------- 2 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 tests/simple/defvalue.sv diff --git a/tests/simple/defvalue.sv b/tests/simple/defvalue.sv new file mode 100644 index 000000000..b0a087ecb --- /dev/null +++ b/tests/simple/defvalue.sv @@ -0,0 +1,22 @@ +module top(input clock, input [3:0] delta, output [3:0] cnt1, cnt2); + cnt #(1) foo (.clock, .cnt(cnt1), .delta); + cnt #(2) bar (.clock, .cnt(cnt2)); +endmodule + +module cnt #( + parameter integer initval = 0 +) ( + input clock, + output logic [3:0] cnt = initval, +`ifdef __ICARUS__ + input [3:0] delta +`else + input [3:0] delta = 10 +`endif +); +`ifdef __ICARUS__ + assign (weak0, weak1) delta = 10; +`endif + always @(posedge clock) + cnt <= cnt + delta; +endmodule diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 23964a751..96d9cdda9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -89,8 +89,7 @@ done compile_and_run() { exe="$1"; output="$2"; shift 2 - ext=${1##*.} - if [ "$ext" == "sv" ]; then + if [ "${2##*.}" == "sv" ]; then language_gen="-g2012" else language_gen="-g2005" @@ -142,23 +141,25 @@ do cd ${bn}.out fn=$(basename $fn) bn=$(basename $bn) + refext=v rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then - "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v" + "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" else - cp ../${fn} ${bn}_ref.${ext} + refext=$ext + cp ../${fn} ${bn}_ref.${refext} fi if [ ! -f ../${bn}_tb.v ]; then - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v + "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} else cp ../${bn}_tb.v ${bn}_tb.v fi if $genvcd; then sed -i 's,// \$dump,$dump,g' ${bn}_tb.v; fi - compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs \ + compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.${refext} $libs \ "$toolsdir"/../../techlibs/common/simlib.v \ "$toolsdir"/../../techlibs/common/simcells.v if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi @@ -175,25 +176,25 @@ do test_count=$(( test_count + 1 )) } - if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.v; then + if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.${refext}; then touch ../${bn}.skip return fi if [ -n "$scriptfiles" ]; then - test_passes -f "$frontend $include_opts" ${bn}_ref.v $scriptfiles + test_passes -f "$frontend $include_opts" ${bn}_ref.${refext} $scriptfiles elif [ -n "$scriptopt" ]; then - test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.v + test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.${refext} elif [ "$frontend" = "verific" ]; then - test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -all; opt; memory;;" + test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -all; opt; memory;;" elif [ "$frontend" = "verific_gates" ]; then - test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -gates -all; opt; memory;;" + test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -gates -all; opt; memory;;" 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; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${refext} + test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext} 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 + "$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.${refext} $firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v fi From c330379870a48209534807d1c021ce2a20ccf880 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 12:20:35 +0200 Subject: [PATCH 541/927] Make tests/aiger less chatty Signed-off-by: Clifford Wolf --- tests/aiger/run-test.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index f52eb4ac1..5246c1b48 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -10,8 +10,9 @@ for aag in *.aag; do # Since ABC cannot read *.aag, read the *.aig instead # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) - ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" - ../../yosys -p " + echo "Checking $aag." + ../../yosys-abc -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + ../../yosys -qp " read_verilog ${aag%.*}_ref.v prep design -stash gold @@ -26,8 +27,9 @@ sat -verify -prove-asserts -show-ports -seq 16 miter done for aig in *.aig; do - ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" - ../../yosys -p " + echo "Checking $aig." + ../../yosys-abc -q "read -c $aig; write ${aig%.*}_ref.v" + ../../yosys -qp " read_verilog ${aig%.*}_ref.v prep design -stash gold From 8b8af10f5e612eb1a39320e20b2d1d6f1e7d45df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20W=C3=B6lfel?= Date: Wed, 19 Jun 2019 12:47:48 +0200 Subject: [PATCH 542/927] Unpacked array declaration using size Allows fixed-sized array dimension specified by a single number. This commit is based on the work from PeterCrozier https://github.com/YosysHQ/yosys/pull/560. But is split out of the original work. --- frontends/verilog/verilog_parser.y | 8 +++++++- tests/various/unpacked_arrays.sv | 4 ++++ tests/various/unpacked_arrays.ys | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/various/unpacked_arrays.sv create mode 100644 tests/various/unpacked_arrays.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a034f9601..f77321f09 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1385,7 +1385,13 @@ wire_name: node->children.push_back(rng); } node->type = AST_MEMORY; - node->children.push_back($2); + auto *rangeNode = $2; + if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { + // SV array size [n], rewrite as [n-1:0] + rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); + rangeNode->children.push_back(AstNode::mkconst_int(0, false)); + } + node->children.push_back(rangeNode); } if (current_function_or_task == NULL) { if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) { diff --git a/tests/various/unpacked_arrays.sv b/tests/various/unpacked_arrays.sv new file mode 100644 index 000000000..2f4ed0d3f --- /dev/null +++ b/tests/various/unpacked_arrays.sv @@ -0,0 +1,4 @@ +module unpacked_arrays; + reg array_range [0:7]; + reg array_size [8]; +endmodule diff --git a/tests/various/unpacked_arrays.ys b/tests/various/unpacked_arrays.ys new file mode 100644 index 000000000..419152d9c --- /dev/null +++ b/tests/various/unpacked_arrays.ys @@ -0,0 +1,2 @@ +read_verilog -sv unpacked_arrays.sv +stat From ec4565009ae69409eb01f1b595f5f59fcc969ce2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 14:38:50 +0200 Subject: [PATCH 543/927] Add "read_verilog -pwires" feature, closes #1106 Signed-off-by: Clifford Wolf --- README.md | 4 ++++ frontends/ast/ast.cc | 8 ++++++-- frontends/ast/ast.h | 6 +++--- frontends/ast/genrtlil.cc | 21 ++++++++++++++++++++- frontends/verilog/verilog_frontend.cc | 10 +++++++++- frontends/verilog/verilog_parser.y | 8 ++++++-- 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 637703a7f..42f972c8e 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,10 @@ Verilog Attributes and non-standard features module inputs. The attribute is attached to the input wire by the HDL front-end when the input is declared with a default value. +- The ``parameter`` and ``localparam`` attributes are used to mark wires + that represent module parameters or localparams (when the HDL front-end + is run in -pwires mode). + - In addition to the ``(* ... *)`` attribute syntax, Yosys supports the non-standard ``{* ... *}`` attribute syntax to set default attributes for everything that comes after the ``{* ... *}`` statement. (Reset diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index b5b968e9e..3d066af53 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -46,7 +46,7 @@ namespace AST { // instantiate global variables (private API) namespace AST_INTERNAL { bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; - bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire; + bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map current_scope; const dict *genRTLIL_subst_ptr = NULL; @@ -1112,6 +1112,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast current_module->nowb = flag_nowb; current_module->noopt = flag_noopt; current_module->icells = flag_icells; + current_module->pwires = flag_pwires; current_module->autowire = flag_autowire; current_module->fixup_ports(); @@ -1126,7 +1127,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast // create AstModule instances for all modules in the AST tree and add them to 'design' void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, - bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) + bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; @@ -1144,6 +1145,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump flag_nowb = nowb; flag_noopt = noopt; flag_icells = icells; + flag_pwires = pwires; flag_autowire = autowire; log_assert(current_ast->type == AST_DESIGN); @@ -1480,6 +1482,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dictlib = lib; new_mod->noopt = noopt; new_mod->icells = icells; + new_mod->pwires = pwires; new_mod->autowire = autowire; return new_mod; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index b8cde060e..54b2fb319 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -286,13 +286,13 @@ namespace AST // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, - bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); + bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire); // parametric modules are supported directly by the AST library // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions struct AstModule : RTLIL::Module { AstNode *ast; - bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire; + bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) YS_OVERRIDE; @@ -325,7 +325,7 @@ namespace AST_INTERNAL { // internal state variables extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit; - extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; + extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, flag_autowire; extern AST::AstNode *current_ast, *current_ast_mod; extern std::map current_scope; extern const dict *genRTLIL_subst_ptr; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 32ed401eb..079fc11e5 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,7 +853,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_FUNCTION: case AST_DPI_FUNCTION: case AST_AUTOWIRE: - case AST_LOCALPARAM: case AST_DEFPARAM: case AST_GENVAR: case AST_GENFOR: @@ -895,6 +894,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // remember the parameter, needed for example in techmap case AST_PARAMETER: current_module->avail_parameters.insert(str); + /* fall through */ + case AST_LOCALPARAM: + if (flag_pwires) + { + if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT) + log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str()); + + RTLIL::Const val = children[0]->bitsAsConst(); + RTLIL::Wire *wire = current_module->addWire(str, GetSize(val)); + current_module->connect(wire, val); + + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1; + + for (auto &attr : attributes) { + if (attr.second->type != AST_CONSTANT) + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + wire->attributes[attr.first] = attr.second->asAttrConst(); + } + } break; // create an RTLIL::Wire for an AST_WIRE node diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 01e589efb..0e2bead6f 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -168,6 +168,9 @@ struct VerilogFrontend : public Frontend { log(" -icells\n"); log(" interpret cell types starting with '$' as internal cell types\n"); log("\n"); + log(" -pwires\n"); + log(" add a wire for each module parameter\n"); + log("\n"); log(" -nooverwrite\n"); log(" ignore re-definitions of modules. (the default behavior is to\n"); log(" create an error message if the existing module is not a black box\n"); @@ -228,6 +231,7 @@ struct VerilogFrontend : public Frontend { bool flag_nodpi = false; bool flag_noopt = false; bool flag_icells = false; + bool flag_pwires = false; bool flag_nooverwrite = false; bool flag_overwrite = false; bool flag_defer = false; @@ -368,6 +372,10 @@ struct VerilogFrontend : public Frontend { flag_icells = true; continue; } + if (arg == "-pwires") { + flag_pwires = true; + continue; + } if (arg == "-ignore_redef" || arg == "-nooverwrite") { flag_nooverwrite = true; flag_overwrite = false; @@ -458,7 +466,7 @@ struct VerilogFrontend : public Frontend { error_on_dpi_function(current_ast); AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, - flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); + flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); if (!flag_nopp) delete lexin; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ebb4369c3..8234479cc 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -319,15 +319,17 @@ module_para_list: single_module_para: /* empty */ | - TOK_PARAMETER { + attr TOK_PARAMETER { if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + append_attr(astbuf1, $1); } param_signed param_integer param_range single_param_decl | - TOK_LOCALPARAM { + attr TOK_LOCALPARAM { if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + append_attr(astbuf1, $1); } param_signed param_integer param_range single_param_decl | single_param_decl; @@ -1217,6 +1219,7 @@ param_decl: attr TOK_PARAMETER { astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + append_attr(astbuf1, $1); } param_signed param_integer param_real param_range param_decl_list ';' { delete astbuf1; }; @@ -1225,6 +1228,7 @@ localparam_decl: attr TOK_LOCALPARAM { astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + append_attr(astbuf1, $1); } param_signed param_integer param_real param_range param_decl_list ';' { delete astbuf1; }; From 96ade549932ca48d0e1d3b99389129cdc37524a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 19 Jun 2019 09:51:11 -0700 Subject: [PATCH 544/927] Fix bug in #1078, add entry to CHANGELOG --- CHANGELOG | 1 + passes/techmap/muxcover.cc | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 839fefcf1..4c38f6e6e 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 + - Extended "muxcover -mux{4,8,16}=" - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 32102436d..8e44be148 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -610,7 +610,7 @@ struct MuxcoverPass : public Pass { use_mux4 = true; if (arg.size() > 5) { if (arg[5] != '=') break; - cost_mux4 = atoi(arg.substr(5).c_str()); + cost_mux4 = atoi(arg.substr(6).c_str()); } continue; } @@ -618,7 +618,7 @@ struct MuxcoverPass : public Pass { use_mux8 = true; if (arg.size() > 5) { if (arg[5] != '=') break; - cost_mux8 = atoi(arg.substr(5).c_str()); + cost_mux8 = atoi(arg.substr(6).c_str()); } continue; } @@ -626,7 +626,7 @@ struct MuxcoverPass : public Pass { use_mux16 = true; if (arg.size() > 6) { if (arg[6] != '=') break; - cost_mux16 = atoi(arg.substr(6).c_str()); + cost_mux16 = atoi(arg.substr(7).c_str()); } continue; } From 0d888ee7edada1349b76360f85124a81d0766cd2 Mon Sep 17 00:00:00 2001 From: acw1251 Date: Wed, 19 Jun 2019 15:27:04 -0400 Subject: [PATCH 545/927] Fixed the help summary line for a few commands --- passes/cmds/blackbox.cc | 2 +- passes/sat/assertpmux.cc | 6 +++--- passes/sat/cutpoint.cc | 2 +- techlibs/ice40/ice40_unlut.cc | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc index 6094f8f16..d09ed872e 100644 --- a/passes/cmds/blackbox.cc +++ b/passes/cmds/blackbox.cc @@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct BlackboxPass : public Pass { - BlackboxPass() : Pass("blackbox", "change type of cells in the design") { } + BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index 509cb0ba9..3b432c461 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -180,7 +180,7 @@ struct AssertpmuxWorker }; struct AssertpmuxPass : public Pass { - AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { } + AssertpmuxPass() : Pass("assertpmux", "adds asserts for parallel muxes") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -195,8 +195,8 @@ struct AssertpmuxPass : public Pass { log("\n"); log(" -always\n"); log(" usually the $pmux condition is only checked when the $pmux output\n"); - log(" is used be the mux tree it drives. this option will deactivate this\n"); - log(" additional constrained and check the $pmux condition always.\n"); + log(" is used by the mux tree it drives. this option will deactivate this\n"); + log(" additional constraint and check the $pmux condition always.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 048aec7f3..b4549bc39 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct CutpointPass : public Pass { - CutpointPass() : Pass("cutpoint", "add hi/lo cover cells for each wire bit") { } + CutpointPass() : Pass("cutpoint", "adds formal cut points to the design") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc index 2428a8e78..bec3c4c96 100644 --- a/techlibs/ice40/ice40_unlut.cc +++ b/techlibs/ice40/ice40_unlut.cc @@ -74,7 +74,7 @@ static void run_ice40_unlut(Module *module) } struct Ice40UnlutPass : public Pass { - Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { } + Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SBLUT4 cells to $lut cells") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| From ce29ede801e4cbfa430c56833f3f0bf98b18063f Mon Sep 17 00:00:00 2001 From: acw1251 Date: Wed, 19 Jun 2019 16:39:46 -0400 Subject: [PATCH 546/927] Fixed small typo in ice40_unlut help summary --- techlibs/ice40/ice40_unlut.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc index bec3c4c96..d16e6e6a3 100644 --- a/techlibs/ice40/ice40_unlut.cc +++ b/techlibs/ice40/ice40_unlut.cc @@ -74,7 +74,7 @@ static void run_ice40_unlut(Module *module) } struct Ice40UnlutPass : public Pass { - Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SBLUT4 cells to $lut cells") { } + Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SB_LUT4 cells to $lut cells") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| From 6a6dd5e0575950174e3abde7a13a3e3be73e5299 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 12:06:07 +0200 Subject: [PATCH 547/927] Add proper test for SV-style arrays Signed-off-by: Clifford Wolf --- tests/simple/arrays02.sv | 16 ++++++++++++++++ tests/various/unpacked_arrays.sv | 4 ---- tests/various/unpacked_arrays.ys | 2 -- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 tests/simple/arrays02.sv delete mode 100644 tests/various/unpacked_arrays.sv delete mode 100644 tests/various/unpacked_arrays.ys diff --git a/tests/simple/arrays02.sv b/tests/simple/arrays02.sv new file mode 100644 index 000000000..76c2a7388 --- /dev/null +++ b/tests/simple/arrays02.sv @@ -0,0 +1,16 @@ +module uut_arrays02(clock, we, addr, wr_data, rd_data); + +input clock, we; +input [3:0] addr, wr_data; +output [3:0] rd_data; +reg [3:0] rd_data; + +reg [3:0] memory [16]; + +always @(posedge clock) begin + if (we) + memory[addr] <= wr_data; + rd_data <= memory[addr]; +end + +endmodule diff --git a/tests/various/unpacked_arrays.sv b/tests/various/unpacked_arrays.sv deleted file mode 100644 index 2f4ed0d3f..000000000 --- a/tests/various/unpacked_arrays.sv +++ /dev/null @@ -1,4 +0,0 @@ -module unpacked_arrays; - reg array_range [0:7]; - reg array_size [8]; -endmodule diff --git a/tests/various/unpacked_arrays.ys b/tests/various/unpacked_arrays.ys deleted file mode 100644 index 419152d9c..000000000 --- a/tests/various/unpacked_arrays.ys +++ /dev/null @@ -1,2 +0,0 @@ -read_verilog -sv unpacked_arrays.sv -stat From 11ec7b2aecddc72747ccdc30d2674583062d58d3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 12:23:07 +0200 Subject: [PATCH 548/927] Fix typo Signed-off-by: Clifford Wolf --- passes/cmds/stat.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index d22685b62..27c5fb60c 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -285,8 +285,8 @@ struct StatPass : public Pass { log(" use cell area information from the provided liberty file\n"); log("\n"); log(" -tech \n"); - log(" print area estemate for the specified technology. Corrently supported\n"); - log(" calues for : xilinx\n"); + log(" print area estemate for the specified technology. Currently supported\n"); + log(" values for : xilinx\n"); log("\n"); log(" -width\n"); log(" annotate internal cell types with their word width.\n"); From 2454ad99bf49afe752d6fd1c1567f59ee9e26736 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 13:44:21 +0200 Subject: [PATCH 549/927] Refactor "opt_rmdff -sat" Signed-off-by: Clifford Wolf --- passes/opt/netlist.h | 317 ---------------------------------------- passes/opt/opt_rmdff.cc | 86 +++++------ tests/opt/opt_ff_sat.v | 25 ++-- tests/opt/opt_ff_sat.ys | 1 + 4 files changed, 57 insertions(+), 372 deletions(-) delete mode 100644 passes/opt/netlist.h diff --git a/passes/opt/netlist.h b/passes/opt/netlist.h deleted file mode 100644 index f029ad6ab..000000000 --- a/passes/opt/netlist.h +++ /dev/null @@ -1,317 +0,0 @@ -/* -*- c++ -*- - * 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. - * - */ - -#ifndef SATGEN_ALGO_H -#define SATGEN_ALGO_H - -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/sigtools.h" -#include - -YOSYS_NAMESPACE_BEGIN - -CellTypes comb_cells_filt() -{ - CellTypes ct; - - ct.setup_internals(); - ct.setup_stdcells(); - - return ct; -} - -struct Netlist { - RTLIL::Module *module; - SigMap sigmap; - CellTypes ct; - dict sigbit_driver_map; - dict> cell_inputs_map; - - Netlist(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) { setup_netlist(module, ct); } - - Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module), ct(ct) { setup_netlist(module, ct); } - - RTLIL::Cell *driver_cell(RTLIL::SigBit sig) const - { - sig = sigmap(sig); - if (!sigbit_driver_map.count(sig)) { - return NULL; - } - - return sigbit_driver_map.at(sig); - } - - RTLIL::SigSpec driver_port(RTLIL::SigBit sig) - { - RTLIL::Cell *cell = driver_cell(sig); - - if (!cell) { - return RTLIL::SigSpec(); - } - - for (auto &port : cell->connections_) { - if (ct.cell_output(cell->type, port.first)) { - RTLIL::SigSpec port_sig = sigmap(port.second); - for (int i = 0; i < GetSize(port_sig); i++) { - if (port_sig[i] == sig) { - return port.second[i]; - } - } - } - } - - return RTLIL::SigSpec(); - } - - void setup_netlist(RTLIL::Module *module, const CellTypes &ct) - { - for (auto cell : module->cells()) { - if (ct.cell_known(cell->type)) { - std::set inputs, outputs; - for (auto &port : cell->connections()) { - std::vector bits = sigmap(port.second).to_sigbit_vector(); - if (ct.cell_output(cell->type, port.first)) - outputs.insert(bits.begin(), bits.end()); - else - inputs.insert(bits.begin(), bits.end()); - } - cell_inputs_map[cell] = inputs; - for (auto &bit : outputs) { - sigbit_driver_map[bit] = cell; - }; - } - } - } -}; - -namespace detail -{ -struct NetlistConeWireIter : public std::iterator { - using set_iter_t = std::set::iterator; - - const Netlist &net; - RTLIL::SigBit sig; - bool sentinel; - CellTypes *cell_filter; - - std::stack> dfs_path_stack; - std::set cells_visited; - - NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true), cell_filter(NULL) {} - - NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) - : net(net), sig(sig), sentinel(false), cell_filter(cell_filter) - { - } - - const RTLIL::SigBit &operator*() const { return sig; }; - bool operator!=(const NetlistConeWireIter &other) const - { - if (sentinel || other.sentinel) { - return sentinel != other.sentinel; - } else { - return sig != other.sig; - } - } - - bool operator==(const NetlistConeWireIter &other) const - { - if (sentinel || other.sentinel) { - return sentinel == other.sentinel; - } else { - return sig == other.sig; - } - } - - void next_sig_in_dag() - { - while (1) { - if (dfs_path_stack.empty()) { - sentinel = true; - return; - } - - auto &cell_inputs_iter = dfs_path_stack.top().first; - auto &cell_inputs_iter_guard = dfs_path_stack.top().second; - - cell_inputs_iter++; - if (cell_inputs_iter != cell_inputs_iter_guard) { - sig = *cell_inputs_iter; - return; - } else { - dfs_path_stack.pop(); - } - } - } - - NetlistConeWireIter &operator++() - { - RTLIL::Cell *cell = net.driver_cell(sig); - - if (!cell) { - next_sig_in_dag(); - return *this; - } - - if (cells_visited.count(cell)) { - next_sig_in_dag(); - return *this; - } - - if ((cell_filter) && (!cell_filter->cell_known(cell->type))) { - next_sig_in_dag(); - return *this; - } - - auto &inputs = net.cell_inputs_map.at(cell); - dfs_path_stack.push(std::make_pair(inputs.begin(), inputs.end())); - cells_visited.insert(cell); - sig = (*dfs_path_stack.top().first); - return *this; - } -}; - -struct NetlistConeWireIterable { - const Netlist &net; - RTLIL::SigBit sig; - CellTypes *cell_filter; - - NetlistConeWireIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) - { - } - - NetlistConeWireIter begin() { return NetlistConeWireIter(net, sig, cell_filter); } - NetlistConeWireIter end() { return NetlistConeWireIter(net); } -}; - -struct NetlistConeCellIter : public std::iterator { - const Netlist &net; - - NetlistConeWireIter sig_iter; - - NetlistConeCellIter(const Netlist &net) : net(net), sig_iter(net) {} - - NetlistConeCellIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig_iter(net, sig, cell_filter) - { - if ((!sig_iter.sentinel) && (!has_driver_cell(*sig_iter))) { - ++(*this); - } - } - - bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } - - RTLIL::Cell *operator*() const { return net.sigbit_driver_map.at(*sig_iter); }; - - bool operator!=(const NetlistConeCellIter &other) const { return sig_iter != other.sig_iter; } - bool operator==(const NetlistConeCellIter &other) const { return sig_iter == other.sig_iter; } - NetlistConeCellIter &operator++() - { - while (true) { - ++sig_iter; - if (sig_iter.sentinel) { - return *this; - } - - RTLIL::Cell* cell = net.driver_cell(*sig_iter); - - if (!cell) { - continue; - } - - if ((sig_iter.cell_filter) && (!sig_iter.cell_filter->cell_known(cell->type))) { - continue; - } - - if (!sig_iter.cells_visited.count(cell)) { - return *this; - } - } - } -}; - -struct NetlistConeCellIterable { - const Netlist &net; - RTLIL::SigBit sig; - CellTypes *cell_filter; - - NetlistConeCellIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) - { - } - - NetlistConeCellIter begin() { return NetlistConeCellIter(net, sig, cell_filter); } - NetlistConeCellIter end() { return NetlistConeCellIter(net); } -}; - -// struct NetlistConeInputsIter : public std::iterator { -// const Netlist &net; -// RTLIL::SigBit sig; - -// NetlistConeWireIter sig_iter; - -// bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } - -// NetlistConeInputsIter(const Netlist &net, RTLIL::SigBit sig = NULL) : net(net), sig(sig), sig_iter(net, sig) -// { -// if ((sig != NULL) && (has_driver_cell(sig_iter))) { -// ++(*this); -// } -// } - -// const RTLIL::SigBit &operator*() const { return sig_iter; }; -// bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } -// bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } -// NetlistConeInputsIter &operator++() -// { -// do { -// ++sig_iter; -// if (sig_iter->empty()) { -// return *this; -// } -// } while (has_driver_cell(sig_iter)); - -// return *this; -// } -// }; - -// struct NetlistConeInputsIterable { -// const Netlist &net; -// RTLIL::SigBit sig; - -// NetlistConeInputsIterable(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig) {} - -// NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, sig); } -// NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } -// }; -} // namespace detail - -detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) -{ - return detail::NetlistConeWireIterable(net, net.sigmap(sig), cell_filter = cell_filter); -} - -// detail::NetlistConeInputsIterable cone_inputs(RTLIL::SigBit sig) { return NetlistConeInputsIterable(this, &sig); } -detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) -{ - return detail::NetlistConeCellIterable(net, net.sigmap(sig), cell_filter); -} - -YOSYS_NAMESPACE_END - -#endif diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 0ab91ca9e..5fc28ae92 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -22,7 +22,6 @@ #include "kernel/rtlil.h" #include "kernel/satgen.h" #include "kernel/sigtools.h" -#include "netlist.h" #include #include @@ -31,9 +30,8 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map, dff_init_map; SigSet mux_drivers; +dict bit2driver; dict> init_attributes; -std::map netlists; -std::map comb_filters; bool keepdc; bool sat; @@ -459,41 +457,46 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\E"); } - if (sat && has_init) { + if (sat && has_init && (!sig_r.size() || val_init == val_rv)) + { bool removed_sigbits = false; - // Create netlist for the module if not already available - if (!netlists.count(mod)) { - netlists.emplace(mod, Netlist(mod)); - comb_filters.emplace(mod, comb_cells_filt()); - } - - // Load netlist for the module from the pool - Netlist &net = netlists.at(mod); + ezSatPtr ez; + SatGen satgen(ez.get(), &assign_map); + pool sat_cells; + std::function sat_import_cell = [&](Cell *c) { + if (!sat_cells.insert(c).second) + return; + if (!satgen.importCell(c)) + return; + for (auto &conn : c->connections()) { + if (!c->input(conn.first)) + continue; + for (auto bit : assign_map(conn.second)) + if (bit2driver.count(bit)) + sat_import_cell(bit2driver.at(bit)); + } + }; // For each register bit, try to prove that it cannot change from the initial value. If so, remove it for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; - if ((!q_sigbit.wire) || (!d_sigbit.wire)) { + if ((!q_sigbit.wire) || (!d_sigbit.wire)) continue; - } - ezSatPtr ez; - SatGen satgen(ez.get(), &net.sigmap); + if (!bit2driver.count(d_sigbit)) + continue; - // Create SAT instance only for the cells that influence the register bit combinatorially - for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { - if (!satgen.importCell(cell)) - log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), - RTLIL::id2cstr(cell->type)); - } + sat_import_cell(bit2driver.at(d_sigbit)); + + RTLIL::State sigbit_init_val = val_init[position]; + if (sigbit_init_val != State::S0 && sigbit_init_val != State::S1) + continue; - RTLIL::Const sigbit_init_val = val_init.extract(position); int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); - int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); @@ -501,24 +504,21 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); // If the register bit cannot change, we can replace it with a constant - if (!counter_example_found) { + if (!counter_example_found) + { + log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, + position, log_id(dff), log_id(dff->type), log_id(mod)); - RTLIL::SigSpec driver_port = net.driver_port(q_sigbit); - RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); - - for (auto &conn : mod->connections_) - net.sigmap(conn.first).replace(driver_port, dummy_wire, &conn.first); - - remove_init_attr(driver_port); - driver_port = dummy_wire; - - mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); + SigSpec tmp = dff->getPort("\\D"); + tmp[position] = sigbit_init_val; + dff->setPort("\\D", tmp); removed_sigbits = true; } } if (removed_sigbits) { + handle_dff(mod, dff); return true; } } @@ -566,8 +566,6 @@ struct OptRmdffPass : public Pass { break; } extra_args(args, argidx, design); - netlists.clear(); - comb_filters.clear(); for (auto module : design->selected_modules()) { pool driven_bits; @@ -576,6 +574,7 @@ struct OptRmdffPass : public Pass { assign_map.set(module); dff_init_map.set(module); mux_drivers.clear(); + bit2driver.clear(); init_attributes.clear(); for (auto wire : module->wires()) @@ -600,17 +599,21 @@ struct OptRmdffPass : public Pass { driven_bits.insert(bit); } } - mux_drivers.clear(); std::vector dff_list; std::vector dffsr_list; std::vector dlatch_list; for (auto cell : module->cells()) { - for (auto &conn : cell->connections()) - if (cell->output(conn.first) || !cell->known()) - for (auto bit : assign_map(conn.second)) + for (auto &conn : cell->connections()) { + bool is_output = cell->output(conn.first); + if (is_output || !cell->known()) + for (auto bit : assign_map(conn.second)) { + if (is_output) + bit2driver[bit] = cell; driven_bits.insert(bit); + } + } if (cell->type == "$mux" || cell->type == "$pmux") { if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) @@ -682,6 +685,7 @@ struct OptRmdffPass : public Pass { assign_map.clear(); mux_drivers.clear(); + bit2driver.clear(); init_attributes.clear(); if (total_count || total_initdrv) diff --git a/tests/opt/opt_ff_sat.v b/tests/opt/opt_ff_sat.v index fc1e61980..5a0a6fe37 100644 --- a/tests/opt/opt_ff_sat.v +++ b/tests/opt/opt_ff_sat.v @@ -1,15 +1,12 @@ -module top( - input clk, - input a, - output b - ); - reg b_reg; - initial begin - b_reg <= 0; - end - - assign b = b_reg; - always @(posedge clk) begin - b_reg <= a && b_reg; - end +module top ( + input clk, + output reg [7:0] cnt +); + initial cnt = 0; + always @(posedge clk) begin + if (cnt < 20) + cnt <= cnt + 1; + else + cnt <= 0; + end endmodule diff --git a/tests/opt/opt_ff_sat.ys b/tests/opt/opt_ff_sat.ys index 13e4ad29b..4e7cc6ca4 100644 --- a/tests/opt/opt_ff_sat.ys +++ b/tests/opt/opt_ff_sat.ys @@ -2,3 +2,4 @@ read_verilog opt_ff_sat.v prep -flatten opt_rmdff -sat synth +select -assert-count 5 t:$_DFF_P_ From a8c85d1b4b810e2ea31770e37e1414b7f1a15283 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 14:27:57 +0200 Subject: [PATCH 550/927] Update some .gitignore files Signed-off-by: Clifford Wolf --- tests/aiger/.gitignore | 3 +-- tests/various/.gitignore | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/aiger/.gitignore b/tests/aiger/.gitignore index 073f46157..9a26bb8f4 100644 --- a/tests/aiger/.gitignore +++ b/tests/aiger/.gitignore @@ -1,2 +1 @@ -*.log -*.out +/*_ref.v diff --git a/tests/various/.gitignore b/tests/various/.gitignore index 397b4a762..7b3e8c68e 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -1 +1,2 @@ -*.log +/*.log +/*.out From 06eb87bcb795b44dc0c9e42c0b2a495c05d23881 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 15:23:55 +0200 Subject: [PATCH 551/927] Improve shregmap help message, fixes #1113 Signed-off-by: Clifford Wolf --- passes/techmap/shregmap.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 21dfe9619..18e60fa6b 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -605,9 +605,11 @@ struct ShregmapPass : public Pass { log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); + log(" this option also implies -clkpol pos -zinit\n"); log("\n"); log(" -tech xilinx\n"); log(" map to xilinx dynamic-length shift registers.\n"); + log(" this option also implies -params -init\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From 477e566e8d203ec7754c90fc845d7f3f759f2974 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 15:34:52 +0200 Subject: [PATCH 552/927] Fix typo, fixes #1095 Signed-off-by: Clifford Wolf --- passes/cmds/write_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 9613b462b..64a762d7c 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -62,7 +62,7 @@ struct WriteFileFrontend : public Frontend { if (argidx < args.size() && args[argidx].rfind("-", 0) != 0) output_filename = args[argidx++]; else - log_cmd_error("Missing putput filename.\n"); + log_cmd_error("Missing output filename.\n"); extra_args(f, filename, args, argidx); From 0221f3e1c5b427678c5679027ee47ec7c0b8321d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:04:42 -0700 Subject: [PATCH 553/927] Fix sign extension when sign is 1'bx --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a09f4a0d1..95a24c93f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3437,7 +3437,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) if (width_ < width) { RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::Sx; - if (!is_signed) + if (padding != RTLIL::State::Sx && !is_signed) padding = RTLIL::State::S0; while (width_ < width) append(padding); From b98276fa61be7a1c589d6dac661d31982cfab16b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:10:43 -0700 Subject: [PATCH 554/927] Add test --- tests/various/signext.ys | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/various/signext.ys diff --git a/tests/various/signext.ys b/tests/various/signext.ys new file mode 100644 index 000000000..26dab13a6 --- /dev/null +++ b/tests/various/signext.ys @@ -0,0 +1,24 @@ + +read_verilog -formal < Date: Thu, 20 Jun 2019 10:15:04 -0700 Subject: [PATCH 555/927] Remove leftover comment --- tests/various/signext.ys | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/various/signext.ys b/tests/various/signext.ys index 26dab13a6..ae44a0e06 100644 --- a/tests/various/signext.ys +++ b/tests/various/signext.ys @@ -5,9 +5,6 @@ assign o = 1'bx; endmodule EOT - -## Example usage for "pmuxtree" and "muxcover" - proc ## Equivalence checking From efdb057c6ad5ba0fe05a597ba5f080067f061aad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: [PATCH 556/927] 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 f54edf1e78fbcbd8a11c2ffcbdf62a50b93ce909 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:22:14 -0700 Subject: [PATCH 557/927] 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 7b13239f2..f652cdf12 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 8767ec3fbdc0986854107de9cf178953ef09f1db Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 20 Jun 2019 10:27:59 -0700 Subject: [PATCH 558/927] Add a few more filename rewrites This now allows a full pipeline to work, something such as: yosys -p "synth_ecp5 -json ~/work/fpga/prjtrellis/examples/ecp5_evn/blinky.v" Otherwise, you will get something along the lines of: ERROR: Can't open output file `~/work/fpga/prjtrellis/examples/ecp5_evn/blinky.v' for writing: No such file or directory Signed-off-by: Ben Widawsky --- kernel/register.cc | 1 + passes/sat/sat.cc | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/kernel/register.cc b/kernel/register.cc index 71eb6b187..26da96b95 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -545,6 +545,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vectoropen(filename.c_str(), std::ofstream::trunc); yosys_output_files.insert(filename); diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index cbba738f0..e4654d835 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -659,6 +659,7 @@ struct SatHelper void dump_model_to_vcd(std::string vcd_file_name) { + rewrite_filename(vcd_file_name); FILE *f = fopen(vcd_file_name.c_str(), "w"); if (!f) log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name.c_str(), strerror(errno)); @@ -761,6 +762,7 @@ struct SatHelper void dump_model_to_json(std::string json_file_name) { + rewrite_filename(json_file_name); FILE *f = fopen(json_file_name.c_str(), "w"); if (!f) log_cmd_error("Can't open output file `%s' for writing: %s\n", json_file_name.c_str(), strerror(errno)); @@ -1505,6 +1507,7 @@ struct SatPass : public Pass { { if (!cnf_file_name.empty()) { + rewrite_filename(cnf_file_name); FILE *f = fopen(cnf_file_name.c_str(), "w"); if (!f) log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno)); @@ -1608,6 +1611,7 @@ struct SatPass : public Pass { if (!cnf_file_name.empty()) { + rewrite_filename(cnf_file_name); FILE *f = fopen(cnf_file_name.c_str(), "w"); if (!f) log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno)); From 0e3e647596db296e662348625c28b76215b55bcf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:47:20 -0700 Subject: [PATCH 559/927] 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 e33cbb0dde72b292002a9fc7158857b19803effe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 12:40:05 -0700 Subject: [PATCH 560/927] Revert "Fix sign extension when sign is 1'bx" This reverts commit 0221f3e1c5b427678c5679027ee47ec7c0b8321d. --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 95a24c93f..a09f4a0d1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3437,7 +3437,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) if (width_ < width) { RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::Sx; - if (padding != RTLIL::State::Sx && !is_signed) + if (!is_signed) padding = RTLIL::State::S0; while (width_ < width) append(padding); From 20119ee50e0cefbcd89275101c8710febd5afd32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 12:43:39 -0700 Subject: [PATCH 561/927] Maintain "is_unsized" state of constants --- frontends/verilog/const2ast.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 57d366dbf..3a3634d34 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -204,7 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn { std::vector data; bool is_signed = false; - bool is_unsized = false; + bool is_unsized = len_in_bits < 0; if (*(endptr+1) == 's') { is_signed = true; endptr++; @@ -213,25 +213,25 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn { case 'b': case 'B': - my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false); + my_strtobin(data, endptr+2, len_in_bits, 2, case_type, is_unsized); break; case 'o': case 'O': - my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false); + my_strtobin(data, endptr+2, len_in_bits, 8, case_type, is_unsized); break; case 'd': case 'D': - my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false); + my_strtobin(data, endptr+2, len_in_bits, 10, case_type, is_unsized); break; case 'h': case 'H': - my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false); + my_strtobin(data, endptr+2, len_in_bits, 16, case_type, is_unsized); break; default: char next_char = char(tolower(*(endptr+1))); if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') { - my_strtobin(data, endptr+1, 1, 2, case_type, true); is_unsized = true; + my_strtobin(data, endptr+1, 1, 2, case_type, is_unsized); } else { return NULL; } From d0bbf9e4d4a508179b55a0cc7793d984f3318f7c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 12:43:59 -0700 Subject: [PATCH 562/927] Extend sign extension tests --- tests/various/signext.ys | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/various/signext.ys b/tests/various/signext.ys index ae44a0e06..0c8d671e7 100644 --- a/tests/various/signext.ys +++ b/tests/various/signext.ys @@ -1,7 +1,13 @@ read_verilog -formal < Date: Thu, 20 Jun 2019 12:45:40 -0700 Subject: [PATCH 563/927] Add CHANGELOG entry --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 4c38f6e6e..496a521be 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "read_aiger" frontend - Extended "muxcover -mux{4,8,16}=" - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" + - Fixed sign extension of unsized constants with 'bx and 'bz MSB Yosys 0.7 .. Yosys 0.8 @@ -32,7 +33,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 c27ab609faeeb3ae9372ea4cf85e5ac6ba029646 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:04:12 -0700 Subject: [PATCH 564/927] Make genvar a signed type --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4895d0302..d89b2dc88 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -517,6 +517,7 @@ wire_type_token: TOK_GENVAR { astbuf3->type = AST_GENVAR; astbuf3->is_reg = true; + astbuf3->is_signed = true; astbuf3->range_left = 31; astbuf3->range_right = 0; } | From c20adc52638b0f3ba3b1c39e5286ae92e901005d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:07:22 -0700 Subject: [PATCH 565/927] Add test --- tests/simple/generate.v | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/simple/generate.v b/tests/simple/generate.v index 3c55682cb..0e353ad9b 100644 --- a/tests/simple/generate.v +++ b/tests/simple/generate.v @@ -148,3 +148,14 @@ generate endgenerate assign out = steps[WIDTH].outer[0].val; endmodule + +// ------------------------------------------ + +module gen_test6(output [3:0] o); +generate + genvar i; + for (i = 3; i >= 0; i = i-1) begin + assign o[i] = 1'b0; + end +endgenerate +endmodule From 9faab38e8de1a78b0ce364a1bdefd2a9ee9c2ec6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:45:04 -0700 Subject: [PATCH 566/927] mux_map to drop sign bit, and eliminate 'bx-es --- techlibs/xilinx/mux_map.v | 60 ++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 0fa8db736..6ad83a488 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -29,24 +29,58 @@ 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 - \$__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)); + genvar i; + wire [A_WIDTH-1:0] A_forward; + assign A_forward[A_WIDTH-1] = A[A_WIDTH-1]; + for (i = A_WIDTH-2; i >= 0; i = i - 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_forward[i] = A_forward[i+1]; 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)); + assign A_forward[i] = A[i]; + + wire [A_WIDTH-1:0] A_without_x; + assign A_without_x[0] = A_forward[0]; + for (i = 1; i < A_WIDTH; i = i + 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_without_x[i] = A_without_x[i-1]; + else + assign A_without_x[i] = A[i]; + + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + // Since negative indices are out of the range of A + // and hence return 'bx, drop the sign bit + \$__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_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); + end + else begin + if (B_WIDTH < 3 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + \$__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_without_x), .B(B), .Y(Y) + ); end endgenerate endmodule From d1dadfcec8e5fffb1d27f067a86a606591b9c686 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:45:09 -0700 Subject: [PATCH 567/927] 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 7b20a7132..f1e887df8 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -299,6 +299,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 9c61fb0e0c23f00bacf316f7efd358c66f2f6397 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:57:54 -0700 Subject: [PATCH 568/927] Add comment as per @cliffordwolf --- passes/techmap/shregmap.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 46f6a79fb..8881ba468 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -295,7 +295,18 @@ struct ShregmapWorker { auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); if (!r.second) { + // Insertion not successful means that d_bit is already + // connected to another register, thus mark it as a + // non chain user ... sigbit_with_non_chain_users.insert(d_bit); + // ... and clone d_bit into another wire, and use that + // wire as a different key in the d_bit-to-cell dictionary + // so that it can be identified as another chain + // (omitting this common flop) + // Link: https://github.com/YosysHQ/yosys/pull/1085 + // NB: This relies on us not updating sigmap with this + // alias otherwise it would think they are the same + // wire Wire *wire = module->addWire(NEW_ID); module->connect(wire, d_bit); sigbit_chain_next.insert(std::make_pair(wire, cell)); From e63324f5ef2ebb14fa0cc88544f577406f95b223 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 17:03:05 -0700 Subject: [PATCH 569/927] Actually, there might not be any harm in updating sigmap... --- passes/techmap/shregmap.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 8881ba468..d9d1e257b 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -304,11 +304,9 @@ struct ShregmapWorker // so that it can be identified as another chain // (omitting this common flop) // Link: https://github.com/YosysHQ/yosys/pull/1085 - // NB: This relies on us not updating sigmap with this - // alias otherwise it would think they are the same - // wire Wire *wire = module->addWire(NEW_ID); module->connect(wire, d_bit); + sigmap.add(wire, d_bit); sigbit_chain_next.insert(std::make_pair(wire, cell)); } From 7dca8def52fdd3a0e450d3f554c328904636798d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 17:29:45 -0700 Subject: [PATCH 570/927] 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 b98b36319..1235af142 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -944,11 +944,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 f2d541962e92fedce0fbb34d4cf5c1985c7cda40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: [PATCH 571/927] 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 572/927] 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 573/927] 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 574/927] 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 575/927] 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 a0566b03ecfb13fba693d35e8af16913b45444c7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:06:51 -0700 Subject: [PATCH 576/927] 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 c421d48d6d5519b24b4596d695c3cf7c43b468f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:27:00 -0700 Subject: [PATCH 577/927] 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 1235af142..d50a38b7a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -836,6 +836,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 @@ -945,12 +949,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 494610911ae2a5b2b73d0f5e030f237df56d3fb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:31:22 -0700 Subject: [PATCH 578/927] 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 242b72d4e11b815d0ca4fa80eee2e112333608d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:37:03 -0700 Subject: [PATCH 579/927] 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 f652cdf12..3f7efa800 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 b810bf26ab9e40e8d7e5a5001ac3a1708309a30b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:40:17 -0700 Subject: [PATCH 580/927] 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 eb09ea6d54738b82924e33c26f47fe35fbdd24cd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:06:51 -0700 Subject: [PATCH 581/927] 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 582/927] 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 583/927] 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 584/927] 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 585/927] 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 40188457d1af9bd4d905c83b29a3bf696b8666f0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 19 Jun 2019 13:15:54 +0200 Subject: [PATCH 586/927] Add support for partial matches to muxcover, fixes #1091 Signed-off-by: Clifford Wolf --- passes/techmap/muxcover.cc | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 8e44be148..78272b0c4 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -57,6 +57,7 @@ struct MuxcoverWorker bool use_mux8; bool use_mux16; bool nodecode; + bool nopartial; int cost_mux2; int cost_mux4; @@ -69,6 +70,7 @@ struct MuxcoverWorker use_mux8 = false; use_mux16 = false; nodecode = false; + nopartial = false; cost_mux2 = COST_MUX2; cost_mux4 = COST_MUX4; cost_mux8 = COST_MUX8; @@ -133,13 +135,20 @@ struct MuxcoverWorker log(" Finished treeification: Found %d trees.\n", GetSize(tree_list)); } - bool follow_muxtree(SigBit &ret_bit, tree_t &tree, SigBit bit, const char *path) + bool follow_muxtree(SigBit &ret_bit, tree_t &tree, SigBit bit, const char *path, bool first_layer = true) { if (*path) { - if (tree.muxes.count(bit) == 0) - return false; + if (tree.muxes.count(bit) == 0) { + if (first_layer || nopartial) + return false; + if (path[0] == 'S') + ret_bit = State::Sx; + else + ret_bit = bit; + return true; + } char port_name[3] = {'\\', *path, 0}; - return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1); + return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false); } else { ret_bit = bit; return true; @@ -148,7 +157,7 @@ struct MuxcoverWorker int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit) { - if (A == B) + if (A == B || sel == State::Sx) return 0; tuple key(A, B, sel); @@ -166,6 +175,9 @@ struct MuxcoverWorker if (std::get<2>(entry)) return 0; + if (A == State::Sx || B == State::Sx) + return 0; + return cost_mux2 / GetSize(std::get<1>(entry)); } @@ -183,9 +195,15 @@ struct MuxcoverWorker implement_decode_mux(std::get<0>(key)); implement_decode_mux(std::get<1>(key)); - module->addMuxGate(NEW_ID, std::get<0>(key), std::get<1>(key), std::get<2>(key), ctrl_bit); + if (std::get<0>(key) == State::Sx) { + module->addBufGate(NEW_ID, std::get<1>(key), ctrl_bit); + } else if (std::get<1>(key) == State::Sx) { + module->addBufGate(NEW_ID, std::get<0>(key), ctrl_bit); + } else { + module->addMuxGate(NEW_ID, std::get<0>(key), std::get<1>(key), std::get<2>(key), ctrl_bit); + decode_mux_counter++; + } std::get<2>(entry) = true; - decode_mux_counter++; } int find_best_cover(tree_t &tree, SigBit bit) @@ -598,6 +616,7 @@ struct MuxcoverPass : public Pass { bool use_mux8 = false; bool use_mux16 = false; bool nodecode = false; + bool nopartial = false; int cost_mux4 = COST_MUX4; int cost_mux8 = COST_MUX8; int cost_mux16 = COST_MUX16; @@ -634,6 +653,10 @@ struct MuxcoverPass : public Pass { nodecode = true; continue; } + if (arg == "-nopartial") { + nopartial = true; + continue; + } break; } extra_args(args, argidx, design); @@ -654,6 +677,7 @@ struct MuxcoverPass : public Pass { worker.cost_mux8 = cost_mux8; worker.cost_mux16 = cost_mux16; worker.nodecode = nodecode; + worker.nopartial = nopartial; worker.run(); } } From 75375a3fbce622b5c4cb6f4464379bb0e66a1107 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 19 Jun 2019 10:07:34 -0700 Subject: [PATCH 587/927] Add test --- tests/various/muxcover.ys | 137 +++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 7ac460f13..d55a35b8c 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -13,7 +13,7 @@ read_verilog -formal < Date: Wed, 19 Jun 2019 10:15:41 -0700 Subject: [PATCH 588/927] Missing a `clean` and `opt_expr -mux_bool` in test --- tests/various/muxcover.ys | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index d55a35b8c..8ef619b46 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -115,6 +115,8 @@ design -save gold techmap muxcover -mux4=150 -mux8=200 +clean +opt_expr -mux_bool select -assert-count 0 t:$_MUX_ select -assert-count 0 t:$_MUX4_ select -assert-count 1 t:$_MUX8_ @@ -171,6 +173,8 @@ design -save gold techmap muxcover -mux4=150 -mux8=200 -mux16=250 +clean +opt_expr -mux_bool select -assert-count 0 t:$_MUX_ select -assert-count 0 t:$_MUX4_ select -assert-count 0 t:$_MUX8_ From 891ea6512e5254803b36a2a22121bc2733ac8b9e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 11:30:27 +0200 Subject: [PATCH 589/927] Improvements in muxcover - Slightly under-estimate cost of decoder muxes - Prefer larger muxes at tree root at same cost - Don't double-count input cost for partial muxes - Add debug log output --- passes/techmap/muxcover.cc | 95 ++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 78272b0c4..e952b04b6 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -178,7 +178,7 @@ struct MuxcoverWorker if (A == State::Sx || B == State::Sx) return 0; - return cost_mux2 / GetSize(std::get<1>(entry)); + return std::max((cost_mux2 / GetSize(std::get<1>(entry))) - 1, 1); } void implement_decode_mux(SigBit ctrl_bit) @@ -206,6 +206,23 @@ struct MuxcoverWorker std::get<2>(entry) = true; } + void find_best_covers(tree_t &tree, const vector &bits) + { + for (auto bit : bits) + find_best_cover(tree, bit); + } + + int sum_best_covers(tree_t &tree, const vector &bits) + { + int sum = 0; + for (auto bit : pool(bits.begin(), bits.end())) { + int cost = tree.newmuxes.at(bit).cost; + log_debug(" Best cost for %s: %d\n", log_signal(bit), cost); + sum += cost; + } + return sum; + } + int find_best_cover(tree_t &tree, SigBit bit) { if (tree.newmuxes.count(bit)) { @@ -236,9 +253,13 @@ struct MuxcoverWorker mux.inputs.push_back(B); mux.selects.push_back(S1); + find_best_covers(tree, mux.inputs); + log_debug(" Decode cost for mux2 at %s: %d\n", log_signal(bit), mux.cost); + mux.cost += cost_mux2; - mux.cost += find_best_cover(tree, A); - mux.cost += find_best_cover(tree, B); + mux.cost += sum_best_covers(tree, mux.inputs); + + log_debug(" Cost of mux2 at %s: %d\n", log_signal(bit), mux.cost); best_mux = mux; } @@ -274,13 +295,15 @@ struct MuxcoverWorker mux.selects.push_back(S1); mux.selects.push_back(T1); - 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); - mux.cost += find_best_cover(tree, D); + find_best_covers(tree, mux.inputs); + log_debug(" Decode cost for mux4 at %s: %d\n", log_signal(bit), mux.cost); - if (best_mux.cost > mux.cost) + mux.cost += cost_mux4; + mux.cost += sum_best_covers(tree, mux.inputs); + + log_debug(" Cost of mux4 at %s: %d\n", log_signal(bit), mux.cost); + + if (best_mux.cost >= mux.cost) best_mux = mux; } } @@ -337,17 +360,15 @@ struct MuxcoverWorker mux.selects.push_back(T1); mux.selects.push_back(U1); - 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); - mux.cost += find_best_cover(tree, D); - mux.cost += find_best_cover(tree, E); - mux.cost += find_best_cover(tree, F); - mux.cost += find_best_cover(tree, G); - mux.cost += find_best_cover(tree, H); + find_best_covers(tree, mux.inputs); + log_debug(" Decode cost for mux8 at %s: %d\n", log_signal(bit), mux.cost); - if (best_mux.cost > mux.cost) + mux.cost += cost_mux8; + mux.cost += sum_best_covers(tree, mux.inputs); + + log_debug(" Cost of mux8 at %s: %d\n", log_signal(bit), mux.cost); + + if (best_mux.cost >= mux.cost) best_mux = mux; } } @@ -441,25 +462,15 @@ struct MuxcoverWorker mux.selects.push_back(U1); mux.selects.push_back(V1); - 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); - mux.cost += find_best_cover(tree, D); - mux.cost += find_best_cover(tree, E); - mux.cost += find_best_cover(tree, F); - mux.cost += find_best_cover(tree, G); - mux.cost += find_best_cover(tree, H); - mux.cost += find_best_cover(tree, I); - mux.cost += find_best_cover(tree, J); - mux.cost += find_best_cover(tree, K); - mux.cost += find_best_cover(tree, L); - mux.cost += find_best_cover(tree, M); - mux.cost += find_best_cover(tree, N); - mux.cost += find_best_cover(tree, O); - mux.cost += find_best_cover(tree, P); + find_best_covers(tree, mux.inputs); + log_debug(" Decode cost for mux16 at %s: %d\n", log_signal(bit), mux.cost); - if (best_mux.cost > mux.cost) + mux.cost += cost_mux16; + mux.cost += sum_best_covers(tree, mux.inputs); + + log_debug(" Cost of mux16 at %s: %d\n", log_signal(bit), mux.cost); + + if (best_mux.cost >= mux.cost) best_mux = mux; } } @@ -555,6 +566,7 @@ struct MuxcoverWorker void treecover(tree_t &tree) { int count_muxes_by_type[4] = {0, 0, 0, 0}; + log_debug(" Searching for best cover for tree at %s.\n", log_signal(tree.root)); find_best_cover(tree, tree.root); implement_best_cover(tree, tree.root, count_muxes_by_type); log(" Replaced tree at %s: %d MUX2, %d MUX4, %d MUX8, %d MUX16\n", log_signal(tree.root), @@ -571,12 +583,13 @@ struct MuxcoverWorker log(" Covering trees:\n"); - // pre-fill cache of decoder muxes - if (!nodecode) + if (!nodecode) { + log_debug(" Populating cache of decoder muxes.\n"); for (auto &tree : tree_list) { find_best_cover(tree, tree.root); tree.newmuxes.clear(); } + } for (auto &tree : tree_list) treecover(tree); @@ -607,6 +620,10 @@ struct MuxcoverPass : public Pass { log(" substitutions, but guarantees that the resulting circuit is not\n"); log(" less efficient than the original circuit.\n"); log("\n"); + log(" -nopartial\n"); + log(" Do not consider mappings that use $_MUX_ to select from less\n"); + log(" than different signals.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From 06bf2ea5621ba5f18aea0fbcb788a041309e0148 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:53:27 -0700 Subject: [PATCH 590/927] 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 3f7efa800..b904b66c1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -522,7 +522,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) { @@ -576,7 +576,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 d2076aa6595b5448bc151a22710822a6fb314c55 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:55:08 -0700 Subject: [PATCH 591/927] 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 eb13663698aa52593e53fae58bd1dfa01136fe08 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: [PATCH 592/927] 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 c4ea6fff65d6b2e69a31649af7e10b129c6ae0f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: [PATCH 593/927] 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 d685c5638..6863b40fa 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 a9ce9193a19352e63197984df00c3cf31a4974e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:09:13 -0700 Subject: [PATCH 594/927] 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 54f3237720709f7c59f4e440ebfdbc61a63c926a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:53:27 -0700 Subject: [PATCH 595/927] 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 596/927] 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 597/927] 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 598/927] 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 6f6a7428f2358a4dc94120ebe740dacb67ce06b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:28:55 -0700 Subject: [PATCH 599/927] 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 531d36336d1fd669ff89159ac5c4519c27761138 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:29:40 -0700 Subject: [PATCH 600/927] 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 cbbd96aae9d847279628191d73d5307f3d832097 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:28:55 -0700 Subject: [PATCH 601/927] 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 602/927] 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 9286b6f013db06b473d009dfabb5e7c1526387b1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 21 Jun 2019 10:02:10 +0200 Subject: [PATCH 603/927] Add "muxcover -freedecode" Signed-off-by: Clifford Wolf --- passes/techmap/muxcover.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index e952b04b6..7fa89bbe3 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -57,6 +57,7 @@ struct MuxcoverWorker bool use_mux8; bool use_mux16; bool nodecode; + bool freedecode; bool nopartial; int cost_mux2; @@ -70,6 +71,7 @@ struct MuxcoverWorker use_mux8 = false; use_mux16 = false; nodecode = false; + freedecode = false; nopartial = false; cost_mux2 = COST_MUX2; cost_mux4 = COST_MUX4; @@ -178,6 +180,9 @@ struct MuxcoverWorker if (A == State::Sx || B == State::Sx) return 0; + if (freedecode) + return 0; + return std::max((cost_mux2 / GetSize(std::get<1>(entry))) - 1, 1); } @@ -620,6 +625,9 @@ struct MuxcoverPass : public Pass { log(" substitutions, but guarantees that the resulting circuit is not\n"); log(" less efficient than the original circuit.\n"); log("\n"); + log(" -freedecode\n"); + log(" Do not count cost for generated decode logic\n"); + log("\n"); log(" -nopartial\n"); log(" Do not consider mappings that use $_MUX_ to select from less\n"); log(" than different signals.\n"); @@ -633,6 +641,7 @@ struct MuxcoverPass : public Pass { bool use_mux8 = false; bool use_mux16 = false; bool nodecode = false; + bool freedecode = false; bool nopartial = false; int cost_mux4 = COST_MUX4; int cost_mux8 = COST_MUX8; @@ -670,6 +679,10 @@ struct MuxcoverPass : public Pass { nodecode = true; continue; } + if (arg == "-freedecode") { + freedecode = true; + continue; + } if (arg == "-nopartial") { nopartial = true; continue; @@ -694,6 +707,7 @@ struct MuxcoverPass : public Pass { worker.cost_mux8 = cost_mux8; worker.cost_mux16 = cost_mux16; worker.nodecode = nodecode; + worker.freedecode = freedecode; worker.nopartial = nopartial; worker.run(); } From a0d3d2bb41cd11b5b33620e16cb67c6568b16847 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 21 Jun 2019 09:44:13 +0100 Subject: [PATCH 604/927] ecp5: Improve mapping of $alu when BI is used Signed-off-by: David Shah --- techlibs/ecp5/arith_map.v | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v index eb7947601..17bde0497 100644 --- a/techlibs/ecp5/arith_map.v +++ b/techlibs/ecp5/arith_map.v @@ -50,20 +50,21 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); wire [Y_WIDTH2-1:0] AA = A_buf; wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf; + wire [Y_WIDTH2-1:0] BX = B_buf; wire [Y_WIDTH2-1:0] C = {CO, CI}; wire [Y_WIDTH2-1:0] FCO, Y1; genvar i; generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice CCU2C #( - .INIT0(16'b0110011010101010), - .INIT1(16'b0110011010101010), + .INIT0(16'b1001011010101010), + .INIT1(16'b1001011010101010), .INJECT1_0("NO"), .INJECT1_1("NO") ) ccu2c_i ( .CIN(C[i]), - .A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1), - .A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1), + .A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1), + .A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1), .S0(Y[i]), .S1(Y1[i]), .COUT(FCO[i]) ); From f15def325c7f2621cf8299ca61b5eeb3ddd3667e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 21 Jun 2019 15:22:17 +0200 Subject: [PATCH 605/927] Added JSON upto and offset Signed-off-by: Clifford Wolf --- backends/json/json.cc | 4 ++++ frontends/json/jsonparse.cc | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/backends/json/json.cc b/backends/json/json.cc index 5022d5da1..1781a28cd 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -189,6 +189,10 @@ struct JsonWriter 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()); + if (w->start_offset) + f << stringf(" \"offset\": %d,\n", w->start_offset); + if (w->upto) + f << stringf(" \"upto\": 1,\n"); f << stringf(" \"attributes\": {"); write_parameters(w->attributes); f << stringf("\n }\n"); diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 82361ea9b..344b8c2c8 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -372,6 +372,18 @@ void json_import(Design *design, string &modname, JsonNode *node) if (wire == nullptr) wire = module->addWire(net_name, GetSize(bits_node->data_array)); + if (net_node->data_dict.count("upto") != 0) { + JsonNode *val = net_node->data_dict.at("offset"); + if (val->type == 'N') + wire->upto = val->data_number != 0; + } + + if (net_node->data_dict.count("offset") != 0) { + JsonNode *val = net_node->data_dict.at("offset"); + if (val->type == 'N') + wire->start_offset = val->data_number; + } + for (int i = 0; i < GetSize(bits_node->data_array); i++) { JsonNode *bitval_node = bits_node->data_array.at(i); From 3775763f51ffb16ecf750833d30192a493ca2ade Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 19:09:34 +0200 Subject: [PATCH 606/927] Fix typo --- frontends/json/jsonparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 344b8c2c8..b74d41dd2 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -373,7 +373,7 @@ void json_import(Design *design, string &modname, JsonNode *node) wire = module->addWire(net_name, GetSize(bits_node->data_array)); if (net_node->data_dict.count("upto") != 0) { - JsonNode *val = net_node->data_dict.at("offset"); + JsonNode *val = net_node->data_dict.at("upto"); if (val->type == 'N') wire->upto = val->data_number != 0; } From ec979475e7f6bce65a4b6768cc3488a3ab02826d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 21 Jun 2019 19:24:41 +0200 Subject: [PATCH 607/927] Replace "muxcover -freedecode" with "muxcover -dmux=cost" Signed-off-by: Clifford Wolf --- passes/techmap/muxcover.cc | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 7fa89bbe3..b0722134e 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -23,6 +23,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +#define COST_DMUX 90 #define COST_MUX2 100 #define COST_MUX4 220 #define COST_MUX8 460 @@ -57,9 +58,9 @@ struct MuxcoverWorker bool use_mux8; bool use_mux16; bool nodecode; - bool freedecode; bool nopartial; + int cost_dmux; int cost_mux2; int cost_mux4; int cost_mux8; @@ -71,8 +72,8 @@ struct MuxcoverWorker use_mux8 = false; use_mux16 = false; nodecode = false; - freedecode = false; nopartial = false; + cost_dmux = COST_DMUX; cost_mux2 = COST_MUX2; cost_mux4 = COST_MUX4; cost_mux8 = COST_MUX8; @@ -180,10 +181,7 @@ struct MuxcoverWorker if (A == State::Sx || B == State::Sx) return 0; - if (freedecode) - return 0; - - return std::max((cost_mux2 / GetSize(std::get<1>(entry))) - 1, 1); + return cost_dmux / GetSize(std::get<1>(entry)); } void implement_decode_mux(SigBit ctrl_bit) @@ -620,14 +618,15 @@ struct MuxcoverPass : public Pass { 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(" -dmux=cost\n"); + log(" Use the specified cost for $_MUX_ cells used in decoders.\n"); + log(" Default cost: %d\n", COST_DMUX); + log("\n"); log(" -nodecode\n"); log(" Do not insert decoder logic. This reduces the number of possible\n"); log(" substitutions, but guarantees that the resulting circuit is not\n"); log(" less efficient than the original circuit.\n"); log("\n"); - log(" -freedecode\n"); - log(" Do not count cost for generated decode logic\n"); - log("\n"); log(" -nopartial\n"); log(" Do not consider mappings that use $_MUX_ to select from less\n"); log(" than different signals.\n"); @@ -641,8 +640,8 @@ struct MuxcoverPass : public Pass { bool use_mux8 = false; bool use_mux16 = false; bool nodecode = false; - bool freedecode = false; bool nopartial = false; + int cost_dmux = COST_DMUX; int cost_mux4 = COST_MUX4; int cost_mux8 = COST_MUX8; int cost_mux16 = COST_MUX16; @@ -675,12 +674,12 @@ struct MuxcoverPass : public Pass { } continue; } - if (arg == "-nodecode") { - nodecode = true; + if (arg.size() >= 6 && arg.substr(0,6) == "-dmux=") { + cost_dmux = atoi(arg.substr(6).c_str()); continue; } - if (arg == "-freedecode") { - freedecode = true; + if (arg == "-nodecode") { + nodecode = true; continue; } if (arg == "-nopartial") { @@ -703,11 +702,11 @@ struct MuxcoverPass : public Pass { worker.use_mux4 = use_mux4; worker.use_mux8 = use_mux8; worker.use_mux16 = use_mux16; + worker.cost_dmux = cost_dmux; worker.cost_mux4 = cost_mux4; worker.cost_mux8 = cost_mux8; worker.cost_mux16 = cost_mux16; worker.nodecode = nodecode; - worker.freedecode = freedecode; worker.nopartial = nopartial; worker.run(); } From 21fa8972f3d04f717d0d4afbfa252e842c807619 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 10:40:18 -0700 Subject: [PATCH 608/927] autotest.sh to cat *.err on error --- tests/tools/autotest.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 96d9cdda9..d90abf848 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -226,6 +226,7 @@ do if $warn_iverilog_git; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi + cat ${bn}.err $keeprunning || exit 1 fi done From 50e72210772f3a1c34f5fe80b19c65f6d304b71a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 19:47:25 +0200 Subject: [PATCH 609/927] Add upto and offset to JSON ports --- backends/json/json.cc | 4 ++++ frontends/json/jsonparse.cc | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/backends/json/json.cc b/backends/json/json.cc index 1781a28cd..eb59e5eba 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -127,6 +127,10 @@ struct JsonWriter f << stringf(" %s: {\n", get_name(n).c_str()); f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output"); f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); + if (w->start_offset) + f << stringf(" \"offset\": %d,\n", w->start_offset); + if (w->upto) + f << stringf(" \"upto\": 1,\n"); f << stringf(" }"); first = false; } diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index b74d41dd2..f5ae8eb72 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -292,6 +292,18 @@ void json_import(Design *design, string &modname, JsonNode *node) if (port_wire == nullptr) port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array)); + if (port_node->data_dict.count("upto") != 0) { + JsonNode *val = port_node->data_dict.at("upto"); + if (val->type == 'N') + port_wire->upto = val->data_number != 0; + } + + if (port_node->data_dict.count("offset") != 0) { + JsonNode *val = port_node->data_dict.at("offset"); + if (val->type == 'N') + port_wire->start_offset = val->data_number; + } + if (port_direction_node->data_string == "input") { port_wire->port_input = true; } else From fde90f7f8eb4150c7f806ab4baa53057a56bc160 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 20:01:40 +0200 Subject: [PATCH 610/927] Fix json formatting --- backends/json/json.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/json/json.cc b/backends/json/json.cc index eb59e5eba..dda4dfedd 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -126,11 +126,11 @@ struct JsonWriter f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(n).c_str()); f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output"); - f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); if (w->start_offset) f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); + f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); f << stringf(" }"); first = false; } From dd22edcd28f2ef9411dde9a941f1fefe05d7bff1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:12:32 -0700 Subject: [PATCH 611/927] Expand synth -coarse without wreduce, move muxcover --- techlibs/xilinx/synth_xilinx.cc | 36 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f1e887df8..ede2bda10 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -218,15 +218,25 @@ struct SynthXilinxPass : public ScriptPass run(stringf("hierarchy -check %s", top_opt.c_str())); } - if (check_label("flatten", "(with '-flatten' only)")) { - if (flatten || help_mode) { - run("proc"); - run("flatten"); - } - } - if (check_label("coarse")) { - run("synth -run coarse"); + run("proc"); + if (flatten || help_mode) + run("flatten", "(with -flatten only)"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt"); + // FIXME + //run("wreduce"); + run("peepopt"); + run("opt_clean"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); //if (!nomux || help_mode) // run("muxpack", "(skip if '-nomux')"); @@ -259,16 +269,20 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + run("opt -fast"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); + if (!nomux || help_mode) { + run("simplemap t:$mux", " (skip if -nomux)"); + run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); + } run("opt -full"); if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here - run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); + 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')"); } @@ -292,8 +306,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 c6b4653ebe83fc5bacaeb92fe7c63a8d52bd523e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:13:01 -0700 Subject: [PATCH 612/927] Since muxcover uses MUX4s, blast them back to gates here --- techlibs/xilinx/mux_map.v | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 6ad83a488..b7ff6ca90 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -84,3 +84,10 @@ module \$shiftx (A, B, Y); end endgenerate endmodule + +module \$_MUX4_ (A, B, C, D, S, T, Y); +input A, B, C, D, S, T; +output Y; +assign Y = T ? (S ? D : C) : + (S ? B : A); +endmodule From f433a523742350b4bb9291ad65299015e2c81f05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:15:23 -0700 Subject: [PATCH 613/927] Add FIXME about need for -mux4 --- Makefile | 4 ++-- techlibs/xilinx/synth_xilinx.cc | 2 ++ 2 files changed, 4 insertions(+), 2 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/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ede2bda10..db3f5b7e4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -275,6 +275,8 @@ struct SynthXilinxPass : public ScriptPass run("dff2dffe"); if (!nomux || help_mode) { run("simplemap t:$mux", " (skip if -nomux)"); + // FIXME: Must specify mux4, even if we don't need it, + // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } run("opt -full"); From 641b86d25f5baa898bf5fca3d1a8f2fd4f5954e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:45:31 -0700 Subject: [PATCH 614/927] Fix up ExclusiveDatabase with @cliffordwolf's help --- passes/opt/muxpack.cc | 65 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index b6f3313bf..ae4f7ba9c 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,54 +29,53 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict sig_cmp_prev; - dict> sig_exclusive; + dict> sig_cmp_prev; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) { - SigSpec a_port, b_port, y_port; + SigSpec const_sig, nonconst_sig, y_port; for (auto cell : module->cells()) { if (cell->type == "$eq") { - a_port = sigmap(cell->getPort("\\A")); - b_port = sigmap(cell->getPort("\\B")); - if (!b_port.is_fully_const()) { - if (!a_port.is_fully_const()) + nonconst_sig = sigmap(cell->getPort("\\A")); + const_sig = sigmap(cell->getPort("\\B")); + if (!const_sig.is_fully_const()) { + if (!nonconst_sig.is_fully_const()) continue; - std::swap(a_port, b_port); + std::swap(nonconst_sig, const_sig); } y_port = sigmap(cell->getPort("\\Y")); } else if (cell->type == "$logic_not") { - a_port = sigmap(cell->getPort("\\A")); - b_port = Const(RTLIL::S0, GetSize(a_port)); + nonconst_sig = sigmap(cell->getPort("\\A")); + const_sig = Const(RTLIL::S0, GetSize(nonconst_sig)); y_port = sigmap(cell->getPort("\\Y")); } else continue; - auto r = sig_exclusive[a_port].insert(b_port.as_const()); - if (!r.second) - continue; - sig_cmp_prev[y_port] = a_port; - } - } + log_assert(!nonconst_sig.empty()); + log_assert(!const_sig.empty()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + } + } - bool query(const SigSpec& sig1, const SigSpec& sig2) const - { - // FIXME: O(N^2) - for (auto bit1 : sig1.bits()) { - auto it = sig_cmp_prev.find(bit1); - if (it == sig_cmp_prev.end()) - return false; + bool query(const SigSpec &sig) const + { + SigSpec nonconst_sig; + pool const_values; - for (auto bit2 : sig2.bits()) { - auto jt = sig_cmp_prev.find(bit2); - if (jt == sig_cmp_prev.end()) - return false; + for (auto bit : sig.bits()) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) + return false; - if (it->second != jt->second) - return false; - } - } + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) + return false; + + if (!const_values.insert(it->second.second).second) + return false; + } return true; } @@ -178,8 +177,8 @@ struct MuxpackWorker Cell *prev_cell = sig_chain_prev.at(a_sig); log_assert(prev_cell); SigSpec s_sig = sigmap(cell->getPort("\\S")); - SigSpec next_s_sig = sigmap(prev_cell->getPort("\\S")); - if (!excl_db.query(s_sig, next_s_sig)) + s_sig.append(sigmap(prev_cell->getPort("\\S"))); + if (!excl_db.query(s_sig)) goto start_cell; } From 6ec816098153c733b97410ebc6aef166db8affd8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:45:53 -0700 Subject: [PATCH 615/927] Add more muxpack tests, with overlapping entries --- tests/various/muxpack.v | 55 +++++++++++++++++++++++++++++++++++++++- tests/various/muxpack.ys | 30 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index 3a1086dbf..7a658d754 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -187,7 +187,9 @@ module case_nonexclusive_select ( ); always @* begin case (x) - 0, 2: o = b; + //0, 2: o = b; + 0: o = b; + 2: o = b; 1: o = c; default: begin o = a; @@ -197,3 +199,54 @@ module case_nonexclusive_select ( endcase end endmodule + +module case_nonoverlap ( + input wire [2:0] x, + input wire a, b, c, d, e, f, g, + output reg o +); + always @* begin + case (x) + //0, 2: o = b; // Creates $reduce_or + //0: o = b; 2: o = b; // Creates $reduce_or + 0: o = b; + 2: o = f; + 1: o = c; + default: + case (x) + //3, 4: o = d; // Creates $reduce_or + //3: o = d; 4: o = d; // Creates $reduce_or + 3: o = d; + 4: o = g; + 5: o = e; + default: o = 1'b0; + endcase + endcase + end +endmodule + +module case_overlap ( + input wire [2:0] x, + input wire a, b, c, d, e, f, g, + output reg o +); + always @* begin + case (x) + //0, 2: o = b; // Creates $reduce_or + //0: o = b; 2: o = b; // Creates $reduce_or + 0: o = b; + 2: o = f; + 1: o = c; + default: + case (x) + //3, 4: o = d; // Creates $reduce_or + //3: o = d; 4: o = d; // Creates $reduce_or + 2: o = 1'b1; // Overlaps with previous $pmux + 3: o = d; + 4: o = g; + 5: o = e; + default: o = 1'b0; + endcase + endcase + end +endmodule diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index 579dad8d3..ef8a6dab9 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -212,3 +212,33 @@ 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 case_nonoverlap +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 case_overlap +prep +design -save gold +muxpack +#opt # Do not opt otherwise $pmux's overlapping entry will get removed +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 d89d663c92853fcd7f9d75b392ec4133ba2f1d89 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:52:28 -0700 Subject: [PATCH 616/927] Add doc --- passes/opt/muxpack.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ae4f7ba9c..c8b226c78 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -304,9 +304,9 @@ struct MuxpackPass : public Pass { log("constructs) and $mux cells (e.g. those created by if-else constructs) into\n"); log("$pmux cells.\n"); log("\n"); - log("This optimisation is conservative --- it will only pack $mux or $pmux cells with\n"); - log("other such cells if it can be certain that the select lines are mutually\n"); - log("exclusive.\n"); + log("This optimisation is conservative --- it will only pack $mux or $pmux cells\n"); + log("whose select lines are driven by '$eq' cells with other such cells if it can be\n"); + log("certain that their select inputs are mutually exclusive.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From 15535112b7b4caa1da75274397c5a3ba885a7349 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:52:51 -0700 Subject: [PATCH 617/927] Fix spacing --- passes/opt/muxpack.cc | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index c8b226c78..4468e8734 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -52,30 +52,30 @@ struct ExclusiveDatabase } else continue; - log_assert(!nonconst_sig.empty()); - log_assert(!const_sig.empty()); - sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); - } - } + log_assert(!nonconst_sig.empty()); + log_assert(!const_sig.empty()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + } + } - bool query(const SigSpec &sig) const - { - SigSpec nonconst_sig; - pool const_values; + bool query(const SigSpec &sig) const + { + SigSpec nonconst_sig; + pool const_values; - for (auto bit : sig.bits()) { - auto it = sig_cmp_prev.find(bit); - if (it == sig_cmp_prev.end()) - return false; + for (auto bit : sig.bits()) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) + return false; - if (nonconst_sig.empty()) - nonconst_sig = it->second.first; - else if (nonconst_sig != it->second.first) - return false; + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) + return false; - if (!const_values.insert(it->second.second).second) - return false; - } + if (!const_values.insert(it->second.second).second) + return false; + } return true; } From ae8305ffcc0c812488163bcc35365d473ce1345d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:13:00 -0700 Subject: [PATCH 618/927] Fix testcase --- tests/various/muxpack.ys | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index ef8a6dab9..de5eec87f 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -230,13 +230,14 @@ sat -verify -prove-asserts -show-ports miter design -load read hierarchy -top case_overlap -prep +#prep # Do not prep otherwise $pmux's overlapping entry will get removed +proc design -save gold muxpack -#opt # Do not opt otherwise $pmux's overlapping entry will get removed +opt stat select -assert-count 0 t:$mux -select -assert-count 1 t:$pmux +select -assert-count 2 t:$pmux design -stash gate design -import gold -as gold design -import gate -as gate From 32f637ffdb0c0641b51227fad92bc80e284740d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:31:04 -0700 Subject: [PATCH 619/927] Add more tests --- tests/various/muxpack.v | 47 +++++++++++++++++++++++----------------- tests/various/muxpack.ys | 25 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v index 7a658d754..33ece1f16 100644 --- a/tests/various/muxpack.v +++ b/tests/various/muxpack.v @@ -187,7 +187,6 @@ module case_nonexclusive_select ( ); always @* begin case (x) - //0, 2: o = b; 0: o = b; 2: o = b; 1: o = c; @@ -202,22 +201,16 @@ endmodule module case_nonoverlap ( input wire [2:0] x, - input wire a, b, c, d, e, f, g, + input wire a, b, c, d, e, output reg o ); always @* begin case (x) - //0, 2: o = b; // Creates $reduce_or - //0: o = b; 2: o = b; // Creates $reduce_or - 0: o = b; - 2: o = f; + 0, 2: o = b; // Creates $reduce_or 1: o = c; default: case (x) - //3, 4: o = d; // Creates $reduce_or - //3: o = d; 4: o = d; // Creates $reduce_or - 3: o = d; - 4: o = g; + 3: o = d; 4: o = d; // Creates $reduce_or 5: o = e; default: o = 1'b0; endcase @@ -227,23 +220,37 @@ endmodule module case_overlap ( input wire [2:0] x, - input wire a, b, c, d, e, f, g, + input wire a, b, c, d, e, output reg o ); always @* begin case (x) - //0, 2: o = b; // Creates $reduce_or - //0: o = b; 2: o = b; // Creates $reduce_or - 0: o = b; - 2: o = f; + 0, 2: o = b; // Creates $reduce_or 1: o = c; default: case (x) - //3, 4: o = d; // Creates $reduce_or - //3: o = d; 4: o = d; // Creates $reduce_or - 2: o = 1'b1; // Overlaps with previous $pmux - 3: o = d; - 4: o = g; + 0: o = 1'b1; // OVERLAP! + 3, 4: o = d; // Creates $reduce_or + 5: o = e; + default: o = 1'b0; + endcase + endcase + end +endmodule + +module case_overlap2 ( + input wire [2:0] x, + input wire a, b, c, d, e, + output reg o +); + always @* begin + case (x) + 0: o = b; 2: o = b; // Creates $reduce_or + 1: o = c; + default: + case (x) + 0: o = d; 2: o = d; // Creates $reduce_or + 3: o = d; 4: o = d; // Creates $reduce_or 5: o = e; default: o = 1'b0; endcase diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys index de5eec87f..af23fcec8 100644 --- a/tests/various/muxpack.ys +++ b/tests/various/muxpack.ys @@ -215,8 +215,11 @@ sat -verify -prove-asserts -show-ports miter design -load read hierarchy -top case_nonoverlap -prep +#prep # Do not prep otherwise $pmux's overlapping entry will get removed +proc design -save gold +opt -fast -mux_undef +select -assert-count 2 t:$pmux muxpack opt stat @@ -233,6 +236,26 @@ hierarchy -top case_overlap #prep # Do not prep otherwise $pmux's overlapping entry will get removed proc design -save gold +opt -fast -mux_undef +select -assert-count 2 t:$pmux +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 case_overlap2 +#prep # Do not prep otherwise $pmux's overlapping entry will get removed +proc +design -save gold +opt -fast -mux_undef +select -assert-count 2 t:$pmux muxpack opt stat From 545cfbbe0dcc36f18dce6429498f4d87112879e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:31:14 -0700 Subject: [PATCH 620/927] Cope with $reduce_or common in case --- passes/opt/muxpack.cc | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 4468e8734..6697d6ca1 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,11 +29,13 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict> sig_cmp_prev; + dict>> sig_cmp_prev; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) { - SigSpec const_sig, nonconst_sig, y_port; + SigSpec const_sig, nonconst_sig; + SigBit y_port; + pool reduce_or; for (auto cell : module->cells()) { if (cell->type == "$eq") { nonconst_sig = sigmap(cell->getPort("\\A")); @@ -50,11 +52,40 @@ struct ExclusiveDatabase const_sig = Const(RTLIL::S0, GetSize(nonconst_sig)); y_port = sigmap(cell->getPort("\\Y")); } + else if (cell->type == "$reduce_or") { + reduce_or.insert(cell); + continue; + } else continue; log_assert(!nonconst_sig.empty()); log_assert(!const_sig.empty()); - sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::vector{const_sig.as_const()}); + } + + for (auto cell : reduce_or) { + nonconst_sig = SigSpec(); + std::vector values; + SigSpec a_port = sigmap(cell->getPort("\\A")); + for (auto bit : a_port) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) { + nonconst_sig = SigSpec(); + break; + } + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) { + nonconst_sig = SigSpec(); + break; + } + for (auto value : it->second.second) + values.push_back(value); + } + if (nonconst_sig.empty()) + continue; + y_port = sigmap(cell->getPort("\\Y")); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values)); } } @@ -73,8 +104,9 @@ struct ExclusiveDatabase else if (nonconst_sig != it->second.first) return false; - if (!const_values.insert(it->second.second).second) - return false; + for (auto value : it->second.second) + if (!const_values.insert(value).second) + return false; } return true; From 70ee10b650e01b7b262baa5c6fda934fb860dfce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:41:47 -0700 Subject: [PATCH 621/927] Stab in the dark with aig_map from dict -> std::map --- 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 48e902666..caf292d59 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -71,7 +71,7 @@ struct XAigerWriter vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - dict aig_map; + std::map aig_map; dict ordered_outputs; vector box_list; From 950bb4c2428aa546ee6abc861e7e87fea31a4b20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: [PATCH 622/927] 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 caf292d59..0e8ea65bf 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 ea154d5ff472e4e18abc7c6328fb8072b84f6582 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:46:55 -0700 Subject: [PATCH 623/927] 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 0e8ea65bf..b7a5d5761 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 638557de3ec600ebe240e2f25e337028ce453ba2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 13:28:42 -0700 Subject: [PATCH 624/927] Cat more stuff --- tests/tools/autotest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index d90abf848..7b1fb50b9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -227,6 +227,8 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi cat ${bn}.err + cat ${bn}_ref.v + cat ${bn}_syn.v $keeprunning || exit 1 fi done From 8f59afd62d6d28059efb6caad1232254146daddd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 13:47:07 -0700 Subject: [PATCH 625/927] Revert "Stab in the dark with aig_map from dict -> std::map" This reverts commit 70ee10b650e01b7b262baa5c6fda934fb860dfce. --- 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 b7a5d5761..6718e4f2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -71,7 +71,7 @@ struct XAigerWriter vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - std::map aig_map; + dict aig_map; dict ordered_outputs; vector box_list; From 848b023ccccc0cffa70d1aea45e558bdabb207b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:23:39 -0700 Subject: [PATCH 626/927] 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 d50a38b7a..5f236992d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -114,13 +114,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 43659e7c6d15d222553a4b55723aa1e56475d51d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:24:34 -0700 Subject: [PATCH 627/927] Revert "Cat more stuff" This reverts commit 638557de3ec600ebe240e2f25e337028ce453ba2. --- tests/tools/autotest.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 7b1fb50b9..d90abf848 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -227,8 +227,6 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi cat ${bn}.err - cat ${bn}_ref.v - cat ${bn}_syn.v $keeprunning || exit 1 fi done From 1845b762b6e1f91c2a4eeb807089945e7b307fc6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:24:35 -0700 Subject: [PATCH 628/927] Revert "autotest.sh to cat *.err on error" This reverts commit 21fa8972f3d04f717d0d4afbfa252e842c807619. --- tests/tools/autotest.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index d90abf848..96d9cdda9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -226,7 +226,6 @@ do if $warn_iverilog_git; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi - cat ${bn}.err $keeprunning || exit 1 fi done From 70c93ea0c4ce023d61553df11198aa0b7e518455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: [PATCH 629/927] 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 630/927] 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 631/927] 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 e581a3e6f4c8763c6a308d1330dbf1ee4bb19499 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: [PATCH 632/927] 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 65c1199acd52f90de86106652dbbca86d4ac5ebc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: [PATCH 633/927] 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 7acbea6b2874c40cc1e3dd4dc0dc31a3985d2abf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:38:30 -0700 Subject: [PATCH 634/927] Fix alignment --- 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 db3f5b7e4..567859f62 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -274,7 +274,7 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); + run("simplemap t:$mux", " (skip if -nomux)"); // FIXME: Must specify mux4, even if we don't need it, // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); From 6a0fb3035ebe7d096a22b13a2fb90de891d6ffe5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:45:51 -0700 Subject: [PATCH 635/927] 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 637c54ff9..110d727de 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 cf4ac332e1b0a4c5cb6c795cfa4b27c2bf9c0879 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:46:45 -0700 Subject: [PATCH 636/927] 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 b904b66c1..473c2b936 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -521,8 +521,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) { @@ -581,6 +581,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)]; @@ -589,19 +590,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 9abde121103a0b004e9c9fa256951553f9bb4732 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:47:42 -0700 Subject: [PATCH 637/927] Add $__XILINX_MUXF78 to preserve entire box --- techlibs/xilinx/abc_xc7.box | 11 ++++++++--- techlibs/xilinx/cells_map.v | 16 ++++++++++++---- techlibs/xilinx/cells_sim.v | 8 ++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 8a48bad4e..a312646f7 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -1,16 +1,21 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf -# F7BMUX slower than F7AMUX +# Average across F7[AB]MUX # Inputs: I0 I1 S0 # Outputs: O -F7BMUX 1 1 3 1 -217 223 296 +F7MUX 1 1 3 1 +204 208 286 # Inputs: I0 I1 S0 # Outputs: O MUXF8 2 1 3 1 104 94 273 +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +MUXF78 10 1 6 1 +190 193 217 223 296 273 + # CARRY4 + CARRY4_[ABCD]X # Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI # Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f139dc5d5..9313df7cc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -226,7 +226,6 @@ module \$__XILINX_SHIFTX (A, B, Y); 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])); @@ -238,9 +237,7 @@ module \$__XILINX_SHIFTX (A, B, Y); 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)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; @@ -274,3 +271,14 @@ 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 + +`ifndef _ABC +module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); + output O; + input I0, I1, I2, I3, S0, S1; + wire T0, T1; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); +endmodule +`endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index bf7a0ed44..3163d8446 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -169,6 +169,14 @@ module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +`ifdef _ABC +(* abc_box_id = 10, lib_whitebox *) +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); + assign O = S1 ? (S0 ? I3 : I2) + : (S0 ? I1 : I0); +endmodule +`endif + module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule From aa0b107afbe800e040886829d43e0b9fcb7219c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:48:20 -0700 Subject: [PATCH 638/927] synth_xilinx to use _ABC macro, and perform muxpack again --- 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 567859f62..170b3fb07 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -206,9 +206,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 -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); else - run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v"); + run("read_verilog -lib -icells -D _ABC +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_xtra.v"); @@ -238,8 +238,8 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - //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, @@ -308,7 +308,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); + run("techmap -map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"); run("clean"); } From 4d6fac019a9a2ca3d2f0a05eb8d08c88e04faad0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:06:13 -0700 Subject: [PATCH 639/927] Fix spacing --- techlibs/xilinx/mux_map.v | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index b7ff6ca90..4c1bb7d05 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -52,21 +52,21 @@ module \$shiftx (A, B, Y); else assign A_without_x[i] = A[i]; - if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else - // Since negative indices are out of the range of A - // and hence return 'bx, drop the sign bit - \$__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_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) - ); + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + // Since negative indices are out of the range of A + // and hence return 'bx, drop the sign bit + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(0), + .A_WIDTH(A_WIDTH), + .B_WIDTH($clog2(A_WIDTH*B_WIDTH)), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); end else begin if (B_WIDTH < 3 || A_WIDTH <= 4) From 44fc616fc701d698564d68a7facf210947b8bd9e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:18:14 -0700 Subject: [PATCH 640/927] Revert B_SIGNED optimisation, since only works for Y_WIDTH==1 --- techlibs/xilinx/mux_map.v | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 4c1bb7d05..89586d3c3 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -55,14 +55,13 @@ module \$shiftx (A, B, Y); if (B_SIGNED) begin if (B_WIDTH < 4 || A_WIDTH <= 4) wire _TECHMAP_FAIL_ = 1; - else - // Since negative indices are out of the range of A - // and hence return 'bx, drop the sign bit + else 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($clog2(A_WIDTH*B_WIDTH)), + .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) From 11886c874c6655bf635655324faa3af31f1c5cf7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:18:29 -0700 Subject: [PATCH 641/927] Restore wreduce to synth_xilinx, after muxcover --- 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 170b3fb07..174138e6a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,6 +279,7 @@ struct SynthXilinxPass : public ScriptPass // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } + run("wreduce"); // FIXME: Moved until after muxcover from 'coarse' run("opt -full"); if (!nosrl || help_mode) { From 694d40719f7a557bd82fe3d9d245353b19349123 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:47:07 -0700 Subject: [PATCH 642/927] Fix spacing again, A_forward -> A_backward --- techlibs/xilinx/mux_map.v | 78 ++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 89586d3c3..441c02ac2 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -37,49 +37,51 @@ module \$shiftx (A, B, Y); generate genvar i; wire [A_WIDTH-1:0] A_forward; - assign A_forward[A_WIDTH-1] = A[A_WIDTH-1]; + assign A_backward[A_WIDTH-1] = A[A_WIDTH-1]; for (i = A_WIDTH-2; i >= 0; i = i - 1) if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_forward[i] = A_forward[i+1]; + assign A_backward[i] = A_backward[i+1]; else - assign A_forward[i] = A[i]; + assign A_backward[i] = A[i]; - wire [A_WIDTH-1:0] A_without_x; - assign A_without_x[0] = A_forward[0]; - for (i = 1; i < A_WIDTH; i = i + 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_without_x[i] = A_without_x[i-1]; - else - assign A_without_x[i] = A[i]; + wire [A_WIDTH-1:0] A_without_x; + assign A_without_x[0] = A_backward[0]; + for (i = 1; i < A_WIDTH; i = i + 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_without_x[i] = A_without_x[i-1]; + else + assign A_without_x[i] = A[i]; - if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else 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_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) - ); - end - else begin - if (B_WIDTH < 3 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else - \$__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_without_x), .B(B), .Y(Y) - ); + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) + // 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_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); + else + wire _TECHMAP_FAIL_ = 1; + end + else begin + if (B_WIDTH < 3 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + \$__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_without_x), .B(B), .Y(Y) + ); end endgenerate endmodule From 8bce3fb32908fd5c74b57ecb178c4d68151149e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:55:34 -0700 Subject: [PATCH 643/927] Fix spacing --- techlibs/xilinx/cells_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 9313df7cc..18c926336 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -214,7 +214,7 @@ module \$__XILINX_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(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_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_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); else @@ -228,7 +228,7 @@ module \$__XILINX_SHIFTX (A, B, Y); wire [4-1:0] T; 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])); + \$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])); @@ -246,7 +246,7 @@ module \$__XILINX_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) - \$__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])); + \$__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])); From 29aee0989fb3a73388d4567409ad6998373edc99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:55:59 -0700 Subject: [PATCH 644/927] mux_map to no longer copy last value into 1'bx --- techlibs/xilinx/mux_map.v | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 441c02ac2..0c6b2b78c 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -35,23 +35,6 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate - genvar i; - wire [A_WIDTH-1:0] A_forward; - assign A_backward[A_WIDTH-1] = A[A_WIDTH-1]; - for (i = A_WIDTH-2; i >= 0; i = i - 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_backward[i] = A_backward[i+1]; - else - assign A_backward[i] = A[i]; - - wire [A_WIDTH-1:0] A_without_x; - assign A_without_x[0] = A_backward[0]; - for (i = 1; i < A_WIDTH; i = i + 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_without_x[i] = A_without_x[i-1]; - else - assign A_without_x[i] = A[i]; - if (B_SIGNED) begin if (B_WIDTH < 4 || A_WIDTH <= 4) wire _TECHMAP_FAIL_ = 1; @@ -64,7 +47,7 @@ module \$shiftx (A, B, Y); .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + .A(A), .B(B[B_WIDTH-2:0]), .Y(Y) ); else wire _TECHMAP_FAIL_ = 1; @@ -80,7 +63,7 @@ module \$shiftx (A, B, Y); .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B), .Y(Y) + .A(A), .B(B), .Y(Y) ); end endgenerate From ed00823b41becc87b52317a82c595c398dd6d10a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:56:56 -0700 Subject: [PATCH 645/927] synth_xilinx to now wreduce except $mux, remove extra peepopt --- techlibs/xilinx/synth_xilinx.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 174138e6a..3d39afcde 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -226,8 +226,7 @@ struct SynthXilinxPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - // FIXME - //run("wreduce"); + run("wreduce c:* t:$mux %d"); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -247,11 +246,6 @@ struct SynthXilinxPass : public ScriptPass // 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')")) { @@ -279,7 +273,6 @@ struct SynthXilinxPass : public ScriptPass // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } - run("wreduce"); // FIXME: Moved until after muxcover from 'coarse' run("opt -full"); if (!nosrl || help_mode) { From aeee9dcad7f6d5fc30f133a89c5dd6f209283c11 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:06:30 -0700 Subject: [PATCH 646/927] Simplify and comment out mux_map.v --- techlibs/xilinx/mux_map.v | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 0c6b2b78c..c47da155d 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -18,6 +18,11 @@ * */ +// The purpose of these mapping rules is to allow preserve all (sufficiently +// wide) $shiftx cells during 'techmap' so that they can be mapped to hard +// resources, rather than being bit-blasted to gates during 'techmap' +// execution + module \$shiftx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -29,18 +34,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 if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_SHIFTX #( + \$shiftx #( .A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), @@ -69,6 +70,10 @@ module \$shiftx (A, B, Y); endgenerate endmodule +// FIXME: This rule exists only because we can't block muxcover +// from using MUX4s -- if we disable MUX4 it will use MUX8s +// instead + module \$_MUX4_ (A, B, C, D, S, T, Y); input A, B, C, D, S, T; output Y; From faa2d6fc1c4bc10cda96c2dc3721df209d2d2117 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:12:34 -0700 Subject: [PATCH 647/927] Constrain wreduce only if wide mux --- 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 3d39afcde..882ebe439 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -226,7 +226,10 @@ struct SynthXilinxPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - run("wreduce c:* t:$mux %d"); + if (help_mode) + run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); + else + run("wreduce" + nomux ? "" : " c:* t:$mux %d"); run("peepopt"); run("opt_clean"); run("alumacc"); From 588196c473f79cf2e221e86f1177d363a1849dcc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: [PATCH 648/927] 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 110d727de..23132f108 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -665,6 +665,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(); @@ -701,6 +703,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 7074ec9cd5d5b5c01e3bbaa8ee45dbae1272f185 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: [PATCH 649/927] 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 650/927] 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 651/927] 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 652/927] 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 653/927] 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 39e0e006d5a6b1ae45d95d75895284e3c48f47d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 18:12:07 -0700 Subject: [PATCH 654/927] Fix wreduce call (!!!), tweak muxcover costs --- techlibs/xilinx/synth_xilinx.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 882ebe439..9724dff94 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -229,7 +229,7 @@ struct SynthXilinxPass : public ScriptPass if (help_mode) run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); else - run("wreduce" + nomux ? "" : " c:* t:$mux %d"); + run("wreduce" + std::string(nomux ? "" : " c:* t:$mux %d")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -271,10 +271,11 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); - // FIXME: Must specify mux4, even if we don't need it, - // otherwise it will use mux8 as mux4 - run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); + run("simplemap t:$mux", " (skip if -nomux)"); + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + run("muxcover -mux8=350 -mux16=400 -dmux=0", "(skip if -nomux)"); } run("opt -full"); From bbf3ad90f59a5b548d263c81ca83ca8f93f1c238 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 18:12:33 -0700 Subject: [PATCH 655/927] Remove $_MUX4_ techmap rule --- techlibs/xilinx/mux_map.v | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index c47da155d..e28070359 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -69,14 +69,3 @@ module \$shiftx (A, B, Y); end endgenerate endmodule - -// FIXME: This rule exists only because we can't block muxcover -// from using MUX4s -- if we disable MUX4 it will use MUX8s -// instead - -module \$_MUX4_ (A, B, C, D, S, T, Y); -input A, B, C, D, S, T; -output Y; -assign Y = T ? (S ? D : C) : - (S ? B : A); -endmodule From fb8fab4a29e5a3978cadf2b1bd8920b772150028 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 20:30:24 -0700 Subject: [PATCH 656/927] Add 'muxcover -dmux=' and '-nopartial' to CHANGELOG --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 496a521be..128f6c6ff 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 - - Extended "muxcover -mux{4,8,16}=" + - Added "muxcover -mux{4,8,16}=" + - Added "muxcover -dmux=" + - Added "muxcover -nopartial" - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 65c022c2572036a66bd06bafd3e3efa088aafb79 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 20:41:14 -0700 Subject: [PATCH 657/927] 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 658/927] 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 659/927] 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 660/927] 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 661/927] 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 36e6da53964b406ad379a60fc289aa3af9beb8a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 10:04:01 -0700 Subject: [PATCH 662/927] Change synth_xilinx's -nomux to -minmuxf --- techlibs/xilinx/cells_map.v | 66 ++++++++++++++++++++------------ techlibs/xilinx/mux_map.v | 2 +- techlibs/xilinx/synth_xilinx.cc | 68 +++++++++++++++++++-------------- 3 files changed, 82 insertions(+), 54 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 18c926336..2eb84ce04 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -155,6 +155,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule +`ifdef MIN_MUX_INPUTS module \$__XILINX_SHIFTX (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -207,10 +208,10 @@ module \$__XILINX_SHIFTX (A, B, Y); 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)); + else if (A_WIDTH < `MIN_MUX_INPUTS) begin + wire _TECHMAP_FAIL_ = 1; end - else if (B_WIDTH == 3) begin + else if (A_WIDTH <= 2 ** 3) begin localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; @@ -219,47 +220,61 @@ module \$__XILINX_SHIFTX (A, B, Y); \$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)); + MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[2]), .O(Y)); end - else if (B_WIDTH == 4) begin + else if (A_WIDTH <= 2 ** 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; - for (i = 0; i < 4; i++) + for (i = 0; i < num_mux8; 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 + \$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])); + if (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:num_mux8*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux8])); else - assign T[i] = 1'bx; + assign T[num_mux8] = A[A_WIDTH-1]; + end + else + assign T[num_mux8] = 1'bx; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(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 + wire [num_mux16-1:0] T; + for (i = 0; i < num_mux16; 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])); + if (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:num_mux16*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); else - assign T[i] = 1'bx; + assign T[num_mux16] = A[A_WIDTH-1]; + end + else + assign T[num_mux16] = 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 +(* techmap_celltype = "$__XILINX_SHIFTX" *) +module _90__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; + + \$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)); +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; @@ -271,6 +286,7 @@ 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 +`endif `ifndef _ABC module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index e28070359..91aaf2118 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -54,7 +54,7 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else begin - if (B_WIDTH < 3 || A_WIDTH <= 4) + if (((A_WIDTH + Y_WIDTH - 1) / Y_WIDTH) < `MIN_MUX_INPUTS) wire _TECHMAP_FAIL_ = 1; else \$__XILINX_SHIFTX #( diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 9724dff94..2cf28fce1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -73,8 +73,10 @@ 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(" -minmuxf \n"); + log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); + log(" above this number of inputs (minimum value 5).\n"); + log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); @@ -97,7 +99,8 @@ 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; + int minmuxf; void clear_flags() YS_OVERRIDE { @@ -112,8 +115,8 @@ struct SynthXilinxPass : public ScriptPass nobram = false; nodram = false; nosrl = false; - nomux = false; arch = "xc7"; + minmuxf = 0; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -176,8 +179,8 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } - if (args[argidx] == "-nomux") { - nomux = true; + if (args[argidx] == "-minmuxf" && argidx+1 < args.size()) { + minmuxf = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-abc9") { @@ -191,6 +194,9 @@ struct SynthXilinxPass : public ScriptPass if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s") log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str()); + if (minmuxf != 0 && minmuxf < 5) + log_cmd_error("-minmuxf value must be 0 or >= 5.\n"); + if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -227,9 +233,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); + run("wreduce [c:* t:$mux %d]", "(selection for '-minmuxf' only)"); else - run("wreduce" + std::string(nomux ? "" : " c:* t:$mux %d")); + run("wreduce" + std::string(minmuxf > 0 ? " c:* t:$mux %d" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -240,15 +246,15 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - if (!nomux || help_mode) - run("muxpack", " (skip if '-nomux')"); + if (minmuxf > 0 || help_mode) + run("muxpack", " ('-minmuxf' only)"); // 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 && minmuxf == 0) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-minmuxf' < 5)"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -270,12 +276,15 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - run("muxcover -mux8=350 -mux16=400 -dmux=0", "(skip if -nomux)"); + if (minmuxf > 0 || help_mode) { + run("simplemap t:$mux", " ('-minmuxf' only)"); + if (minmuxf > 0 || help_mode) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + std::string muxcover_args = " -dmux=0 -mux8=350 -mux16=400"; + run("muxcover " + muxcover_args, "('-minmuxf' only)"); + } } run("opt -full"); @@ -287,26 +296,29 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - std::string techmap_files = " -map +/techmap.v"; + std::string techmap_args = " -map +/techmap.v"; if (help_mode) - techmap_files += " [-map +/xilinx/mux_map.v]"; - else if (!nomux) - techmap_files += " -map +/xilinx/mux_map.v"; + techmap_args += " [-map +/xilinx/mux_map.v]"; + else if (minmuxf > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", minmuxf); if (help_mode) - techmap_files += " [-map +/xilinx/arith_map.v]"; + techmap_args += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { - techmap_files += " -map +/xilinx/arith_map.v"; + techmap_args += " -map +/xilinx/arith_map.v"; if (vpr) - techmap_files += " -D _EXPLICIT_CARRY"; + techmap_args += " -D _EXPLICIT_CARRY"; else if (abc == "abc9") - techmap_files += " -D _CLB_CARRY"; + techmap_args += " -D _CLB_CARRY"; } - run("techmap " + techmap_files); + run("techmap " + techmap_args); run("opt -fast"); } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"); + std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; + if (minmuxf > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", minmuxf); + run("techmap " + techmap_args); run("clean"); } From c2387394e32e7a4513076b5d81beb499ceea2542 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 11:50:37 -0700 Subject: [PATCH 663/927] 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 aa1eeda567d09e2d2ffd40cd008d0166d2910273 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 11:51:55 -0700 Subject: [PATCH 664/927] Modify costs for muxcover --- techlibs/xilinx/synth_xilinx.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2cf28fce1..a84f54e99 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,7 +282,21 @@ struct SynthXilinxPass : public ScriptPass // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented // out of mux2s - std::string muxcover_args = " -dmux=0 -mux8=350 -mux16=400"; + std::string muxcover_args = " -dmux=0"; + switch (minmuxf) { + case 5: muxcover_args += " -mux8=350 -mux16=400"; break; + case 6: muxcover_args += " -mux8=450 -mux16=500"; break; + case 7: muxcover_args += " -mux8=550 -mux16=600"; break; + case 8: muxcover_args += " -mux8=650 -mux16=700"; break; + case 9: muxcover_args += " -mux16=750"; break; + case 10: muxcover_args += " -mux16=850"; break; + case 11: muxcover_args += " -mux16=950"; break; + case 12: muxcover_args += " -mux16=1050"; break; + case 13: muxcover_args += " -mux16=1150"; break; + case 14: muxcover_args += " -mux16=1250"; break; + case 15: muxcover_args += " -mux16=1350"; break; + default: muxcover_args += " -mux16=1450"; break; + } run("muxcover " + muxcover_args, "('-minmuxf' only)"); } } From 2b4501503d05beaecc0f995d0681ff43e2c6fba4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 12:18:17 -0700 Subject: [PATCH 665/927] Fix mux techmapping --- techlibs/xilinx/cells_map.v | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 2eb84ce04..85f174d3d 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -226,35 +226,36 @@ module \$__XILINX_SHIFTX (A, B, Y); 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; - for (i = 0; i < num_mux8; i++) + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; 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])); - if (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:num_mux8*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux8])); + 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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end else - assign T[num_mux8] = A[A_WIDTH-1]; - end - else - assign T[num_mux8] = 1'bx; + assign T[i] = 1'bx; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(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 [num_mux16-1:0] T; - for (i = 0; i < num_mux16; 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])); - if (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:num_mux16*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; 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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end else - assign T[num_mux16] = A[A_WIDTH-1]; - end - else - assign T[num_mux16] = 1'bx; + 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 From 0aae3b4f4361db6d2c6b9c8d69df041f40519cec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 12:50:48 -0700 Subject: [PATCH 666/927] Fix techmapping muxes some more --- 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 85f174d3d..f4b7888b0 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; + localparam a_widthN = A_WIDTH % a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,9 +243,9 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; i++) + localparam a_widthN = A_WIDTH % 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 From 7fbfcf20d16751f4c1eab0c33848c5c05b970992 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:15:00 -0700 Subject: [PATCH 667/927] Move comment --- 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 a84f54e99..69b1580b8 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,11 +279,11 @@ struct SynthXilinxPass : public ScriptPass if (minmuxf > 0 || help_mode) { run("simplemap t:$mux", " ('-minmuxf' only)"); if (minmuxf > 0 || help_mode) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s std::string muxcover_args = " -dmux=0"; switch (minmuxf) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s case 5: muxcover_args += " -mux8=350 -mux16=400"; break; case 6: muxcover_args += " -mux8=450 -mux16=500"; break; case 7: muxcover_args += " -mux8=550 -mux16=600"; break; From 2e7992efffa1d75cf69c8942d03b53e1b6ec2895 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:15:31 -0700 Subject: [PATCH 668/927] Revert "Fix techmapping muxes some more" This reverts commit 0aae3b4f4361db6d2c6b9c8d69df041f40519cec. --- 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 f4b7888b0..85f174d3d 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,9 +243,9 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) + localparam a_widthN = A_WIDTH - num_mux16*a_width0; + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; 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 From db6a0b72b24022eacc84dba8b117dfb193b8d4c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:28:56 -0700 Subject: [PATCH 669/927] Reduce number of decomposed muxes during techmap --- techlibs/xilinx/cells_map.v | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 85f174d3d..6d9860b95 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; + localparam a_widthN = A_WIDTH % a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,20 +243,17 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; 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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + localparam a_widthN = A_WIDTH % a_width0; + wire [num_mux16 + (a_widthN > 0 ? 1 : 0) - 1:0] T; + for (i = 0; i < num_mux16; 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])); + if (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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); 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)); + assign T[num_mux16] = A[A_WIDTH-1]; + end + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(num_mux16 + (a_widthN > 0 ? 1 : 0)), .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 c3df895bf464fd651c4d634ecb58ba78ca572f5f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 15:16:44 -0700 Subject: [PATCH 670/927] Reduce MuxFx resources in mux techmapping --- techlibs/xilinx/cells_map.v | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 6d9860b95..bc0455b0c 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -230,14 +230,10 @@ module \$__XILINX_SHIFTX (A, B, Y); for (i = 0; i < a_width0; 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])); - 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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + else if (i == num_mux8 && 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_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else - assign T[i] = 1'bx; + assign T[i] = A[A_WIDTH-1]; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin @@ -291,8 +287,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); + parameter _TECHMAP_BITS_CONNMAP_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; + else + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; + else + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From efd04880dbeb2021c503c82ad962fe8c5d6802d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 16:16:50 -0700 Subject: [PATCH 671/927] Add RAM32X1D support --- techlibs/xilinx/cells_sim.v | 17 +++++++++++++++++ techlibs/xilinx/cells_xtra.sh | 4 ++-- techlibs/xilinx/cells_xtra.v | 18 ------------------ techlibs/xilinx/drams.txt | 20 ++++++++++++++++++++ techlibs/xilinx/drams_map.v | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3a4540b83..50d588a9e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -278,6 +278,23 @@ 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 +module RAM32X1D ( + output DPO, SPO, + input D, WCLK, WE, + input A0, A1, A2, A3, A4, + input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, +); + parameter INIT = 32'h0; + parameter IS_WCLK_INVERTED = 1'b0; + wire [4:0] a = {A4, A3, A2, A1, A0}; + wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}; + reg [31:0] mem = INIT; + assign SPO = mem[a]; + assign DPO = mem[dpra]; + wire clk = WCLK ^ IS_WCLK_INVERTED; + always @(posedge clk) if (WE) mem[a] <= D; +endmodule + module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 8e39b440d..83863bf0b 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -116,11 +116,11 @@ 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 - xtract_cell_decl RAM32X1D + #xtract_cell_decl RAM32X1D xtract_cell_decl RAM32X1S xtract_cell_decl RAM32X1S_1 xtract_cell_decl RAM32X2S diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index fbcc74682..6220da703 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; @@ -3705,13 +3694,6 @@ module RAM32M (...); input WE; endmodule -module RAM32X1D (...); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_WCLK_INVERTED = 1'b0; - output DPO, SPO; - input A0, A1, A2, A3, A4, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, WCLK, WE; -endmodule - module RAM32X1S (...); parameter [31:0] INIT = 32'h00000000; parameter [0:0] IS_WCLK_INVERTED = 1'b0; diff --git a/techlibs/xilinx/drams.txt b/techlibs/xilinx/drams.txt index 91632bcee..2613c206c 100644 --- a/techlibs/xilinx/drams.txt +++ b/techlibs/xilinx/drams.txt @@ -1,4 +1,17 @@ +bram $__XILINX_RAM32X1D + init 1 + abits 5 + dbits 1 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 0 0 + clocks 0 1 + clkpol 0 2 +endbram + bram $__XILINX_RAM64X1D init 1 abits 6 @@ -25,6 +38,13 @@ bram $__XILINX_RAM128X1D clkpol 0 2 endbram +match $__XILINX_RAM32X1D + min bits 3 + min wports 1 + make_outreg + or_next_if_better +endmatch + match $__XILINX_RAM64X1D min bits 5 min wports 1 diff --git a/techlibs/xilinx/drams_map.v b/techlibs/xilinx/drams_map.v index 47476b592..77041ca86 100644 --- a/techlibs/xilinx/drams_map.v +++ b/techlibs/xilinx/drams_map.v @@ -1,4 +1,38 @@ +module \$__XILINX_RAM32X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter [31:0] INIT = 32'bx; + parameter CLKPOL2 = 1; + input CLK1; + + input [4:0] A1ADDR; + output A1DATA; + + input [4:0] B1ADDR; + input B1DATA; + input B1EN; + + RAM32X1D #( + .INIT(INIT), + .IS_WCLK_INVERTED(!CLKPOL2) + ) _TECHMAP_REPLACE_ ( + .DPRA0(A1ADDR[0]), + .DPRA1(A1ADDR[1]), + .DPRA2(A1ADDR[2]), + .DPRA3(A1ADDR[3]), + .DPRA4(A1ADDR[4]), + .DPO(A1DATA), + + .A0(B1ADDR[0]), + .A1(B1ADDR[1]), + .A2(B1ADDR[2]), + .A3(B1ADDR[3]), + .A4(B1ADDR[4]), + .D(B1DATA), + .WCLK(CLK1), + .WE(B1EN) + ); +endmodule + module \$__XILINX_RAM64X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); parameter [63:0] INIT = 64'bx; parameter CLKPOL2 = 1; From a701a2accf36abb6d0d1a90dc1811eb15708d5db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 18:32:58 -0700 Subject: [PATCH 672/927] Add test --- tests/memories/issue00710.v | 17 +++++++++++++++++ tests/memories/run-test.sh | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/memories/issue00710.v diff --git a/tests/memories/issue00710.v b/tests/memories/issue00710.v new file mode 100644 index 000000000..7a5fad1c2 --- /dev/null +++ b/tests/memories/issue00710.v @@ -0,0 +1,17 @@ +// expect-wr-ports 1 +// expect-rd-ports 1 +// expect-rd-clk \clk + +module top(input clk, input we, re, reset, input [7:0] addr, wdata, output reg [7:0] rdata); + +reg [7:0] bram[0:255]; +(* keep *) reg dummy; + +always @(posedge clk) + if (reset) + dummy <= 1'b0; + else if (re) + rdata <= bram[addr]; + else if (we) + bram[addr] <= wdata; +endmodule diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh index 734a96682..d0537bb98 100755 --- a/tests/memories/run-test.sh +++ b/tests/memories/run-test.sh @@ -14,7 +14,7 @@ shift "$((OPTIND-1))" bash ../tools/autotest.sh $seed -G *.v -for f in `egrep -l 'expect-(wr|rd)-ports' *.v`; do +for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do echo -n "Testing expectations for $f .." ../../yosys -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem" $f if grep -q expect-wr-ports $f; then @@ -25,6 +25,10 @@ for f in `egrep -l 'expect-(wr|rd)-ports' *.v`; do grep -q "parameter \\\\RD_PORTS $(gawk '/expect-rd-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || { echo " ERROR: Unexpected number of read ports."; false; } fi + if grep -q expect-rd-clk $f; then + grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp || + { echo " ERROR: Unexpected read clock."; false; } + fi echo " ok." done From b7deaceadde865fa8bca47cfeeb43a82dc936076 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 18:33:06 -0700 Subject: [PATCH 673/927] Walk through as many muxes as exist for rd_en --- passes/memory/memory_dff.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 220d29295..d37cac28e 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -182,20 +182,28 @@ struct MemoryDffWorker if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)) { - bool enable_invert = mux_cells_a.count(sig_data) != 0; - Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); - SigSpec check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")); + RTLIL::SigSpec en; + RTLIL::SigSpec check_q; - sig_data = sigmap(mux->getPort("\\Y")); - for (auto bit : sig_data) - if (sigbit_users_count[bit] > 1) - goto skip_ff_after_read_merging; + do { + bool enable_invert = mux_cells_a.count(sig_data) != 0; + Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); + check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")); + + sig_data = sigmap(mux->getPort("\\Y")); + for (auto bit : sig_data) + if (sigbit_users_count[bit] > 1) { + goto skip_ff_after_read_merging; + } + + en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); + } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)); if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q) { disconnect_dff(sig_data); cell->setPort("\\CLK", clk_data); - cell->setPort("\\EN", enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); + cell->setPort("\\EN", en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en); cell->setPort("\\DATA", sig_data); cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); From 9dca024a30e5f6cfb06e1abb584ce1320fb81f16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 21:52:53 -0700 Subject: [PATCH 674/927] 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 675/927] 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 676/927] 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 677/927] 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 678/927] 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 679/927] 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 680/927] 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 681/927] 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 682/927] 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 e1ba25d79f0fc623006b250e72093199d0804d52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:54:35 -0700 Subject: [PATCH 683/927] 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 dafef9fef..39c535303 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -35,16 +35,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 - - - - - - - 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 +RAM128X1D 6 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 c6c49c3cd..e3391da40 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -289,6 +289,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, @@ -306,7 +307,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, @@ -324,7 +325,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 2f770b7400f6b12ca13e68496977094f92c13680 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:02:53 -0700 Subject: [PATCH 684/927] 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 158325956e6bf711137e6198fb88e95a1e6250b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:05:28 -0700 Subject: [PATCH 685/927] 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 c95ba4969..67d1ffb1e 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -39,8 +39,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 5b89553a1f1a3b3ec1667cadd34dc1939ebe67c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:37:01 -0700 Subject: [PATCH 686/927] 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 f90834aa9..0312e3e1f 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 d2fed0a7f1bb72ee285657b974f4996c77641a23 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:37:01 -0700 Subject: [PATCH 687/927] 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 c4e4902098153a4ab90d383ffc00987fc06ff072 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 25 Jun 2019 08:29:55 -0700 Subject: [PATCH 688/927] Move only one consumer check outside of while loop --- passes/memory/memory_dff.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index d37cac28e..91ae38fa3 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -189,16 +189,15 @@ struct MemoryDffWorker bool enable_invert = mux_cells_a.count(sig_data) != 0; Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")); - sig_data = sigmap(mux->getPort("\\Y")); - for (auto bit : sig_data) - if (sigbit_users_count[bit] > 1) { - goto skip_ff_after_read_merging; - } - en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)); + for (auto bit : sig_data) + if (sigbit_users_count[bit] > 1) { + goto skip_ff_after_read_merging; + } + if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q) { disconnect_dff(sig_data); From 42720ef6fefdf7645db47b97cd914008d68b00a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 25 Jun 2019 08:33:17 -0700 Subject: [PATCH 689/927] Fix spacing --- passes/memory/memory_dff.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 91ae38fa3..5215cce44 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -193,10 +193,9 @@ struct MemoryDffWorker en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)); - for (auto bit : sig_data) - if (sigbit_users_count[bit] > 1) { - goto skip_ff_after_read_merging; - } + for (auto bit : sig_data) + if (sigbit_users_count[bit] > 1) + goto skip_ff_after_read_merging; if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q) { From ab6e8ce0f00bc9fcf38dc62ae9de26405f7b59d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 25 Jun 2019 08:43:58 -0700 Subject: [PATCH 690/927] Add testcase from #335, fixed by #1130 --- tests/memories/issue00335.v | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/memories/issue00335.v diff --git a/tests/memories/issue00335.v b/tests/memories/issue00335.v new file mode 100644 index 000000000..f3b6e5dfe --- /dev/null +++ b/tests/memories/issue00335.v @@ -0,0 +1,28 @@ +// expect-wr-ports 1 +// expect-rd-ports 1 +// expect-rd-clk \clk + +module ram2 (input clk, + input sel, + input we, + input [SIZE-1:0] adr, + input [63:0] dat_i, + output reg [63:0] dat_o); + parameter SIZE = 5; // Address size + + reg [63:0] mem [0:(1 << SIZE)-1]; + integer i; + + initial begin + for (i = 0; i < (1< Date: Tue, 25 Jun 2019 09:21:46 -0700 Subject: [PATCH 691/927] This optimisation doesn't seem to work... --- techlibs/xilinx/cells_map.v | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index bc0455b0c..61c2c8f94 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -287,32 +287,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; - parameter _TECHMAP_BITS_CONNMAP_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S0_ = 0; - parameter _TECHMAP_CONSTVAL_S0_ = 0; - parameter _TECHMAP_CONSTMSK_S1_ = 0; - parameter _TECHMAP_CONSTVAL_S1_ = 0; - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T0 = I1; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign T0 = I0; - else +// parameter _TECHMAP_BITS_CONNMAP_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; +// parameter _TECHMAP_CONSTMSK_S0_ = 0; +// parameter _TECHMAP_CONSTVAL_S0_ = 0; +// parameter _TECHMAP_CONSTMSK_S1_ = 0; +// parameter _TECHMAP_CONSTVAL_S1_ = 0; +// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +// assign T0 = I1; +// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) +// assign T0 = I0; +// else MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T1 = I3; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign T1 = I2; - else +// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +// assign T1 = I3; +// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) +// assign T1 = I2; +// else MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) - assign O = T1; - else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) - assign O = T0; - else +// if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) +// assign O = T1; +// else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) +// assign O = T0; +// else MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From 609535739036c30efc35a57730e5ffe968267cdb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:54:35 -0700 Subject: [PATCH 692/927] 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 693/927] 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 694/927] 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 3d4102cfa4ae3d91eb03b2795c2dc962735bb80a Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 25 Jun 2019 16:37:36 +0000 Subject: [PATCH 695/927] Add more ECP5 Diamond flip-flops. This includes all I/O registers, and a few more regular FFs where it was convenient. --- techlibs/ecp5/cells_map.v | 40 ++++++++++++++++++- techlibs/ecp5/cells_sim.v | 81 +++++++++++++++++++++++++-------------- 2 files changed, 91 insertions(+), 30 deletions(-) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index f6c71a03d..a90d5e034 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 1e4002ee0..2458c1ca0 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -250,18 +250,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( @@ -558,19 +546,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 From b3c36b444808be36a4fb35a3d78ba3f9691b3da0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 10:58:39 +0200 Subject: [PATCH 696/927] Escape scope names starting with dollar sign in smtio.py Signed-off-by: Clifford Wolf --- backends/smt2/smtio.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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": From 8e9ef891febb47f512710de591401539ad521634 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 11:00:44 +0200 Subject: [PATCH 697/927] Do not clean up buffer cells with "keep" attribute, closes #1128 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cfb0f788a..5f75288e2 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -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"); From f6053b88103bfc652dec1959f30bfb1880613f61 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 11:09:43 +0200 Subject: [PATCH 698/927] Fix segfault on failed VERILOG_FRONTEND::const2ast, closes #1131 Signed-off-by: Clifford Wolf --- frontends/verilog/const2ast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 0dd850e6552a74430559ed63c3a9a67aa1c84512 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Jun 2019 11:39:44 +0100 Subject: [PATCH 699/927] 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 1b49380f6bd79cb037fb36a3d06adf386968dc47 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 17:42:00 +0200 Subject: [PATCH 700/927] Improve BTOR2 handling of undriven wires Signed-off-by: Clifford Wolf --- backends/btor/btor.cc | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 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)); + } } } From 0b7d648c6a71594f8a17e78aef8f62b6f6448390 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 17:54:17 +0200 Subject: [PATCH 701/927] Improve opt_clean handling of unused public wires Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5f75288e2..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 From 177c26ca359f85d0804c62f73e1df1665ffd1ec5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 09:16:45 -0700 Subject: [PATCH 702/927] Rename -minmuxf to -widemux --- techlibs/xilinx/synth_xilinx.cc | 46 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 69b1580b8..4367f2b99 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -73,7 +73,7 @@ struct SynthXilinxPass : public ScriptPass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); - log(" -minmuxf \n"); + log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); log(" above this number of inputs (minimum value 5).\n"); log(" default: 0 (no inference)\n"); @@ -100,7 +100,7 @@ struct SynthXilinxPass : public ScriptPass std::string top_opt, edif_file, blif_file, abc, arch; bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; - int minmuxf; + int widemux; void clear_flags() YS_OVERRIDE { @@ -116,7 +116,7 @@ struct SynthXilinxPass : public ScriptPass nodram = false; nosrl = false; arch = "xc7"; - minmuxf = 0; + widemux = 0; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -179,8 +179,8 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } - if (args[argidx] == "-minmuxf" && argidx+1 < args.size()) { - minmuxf = atoi(args[++argidx].c_str()); + if (args[argidx] == "-widemux" && argidx+1 < args.size()) { + widemux = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-abc9") { @@ -194,8 +194,8 @@ struct SynthXilinxPass : public ScriptPass if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s") log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str()); - if (minmuxf != 0 && minmuxf < 5) - log_cmd_error("-minmuxf value must be 0 or >= 5.\n"); + if (widemux != 0 && widemux < 5) + log_cmd_error("-widemux value must be 0 or >= 5.\n"); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -233,9 +233,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(selection for '-minmuxf' only)"); + run("wreduce [c:* t:$mux %d]", "(selection for '-widemux' only)"); else - run("wreduce" + std::string(minmuxf > 0 ? " c:* t:$mux %d" : "")); + run("wreduce" + std::string(widemux > 0 ? " c:* t:$mux %d" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -246,15 +246,15 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - if (minmuxf > 0 || help_mode) - run("muxpack", " ('-minmuxf' only)"); + if (widemux > 0 || help_mode) + run("muxpack", " ('-widemux' only)"); // 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 && minmuxf == 0) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-minmuxf' < 5)"); + if (!(nosrl && widemux == 0) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -272,15 +272,15 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast"); + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (minmuxf > 0 || help_mode) { - run("simplemap t:$mux", " ('-minmuxf' only)"); - if (minmuxf > 0 || help_mode) { + if (widemux > 0 || help_mode) { + run("simplemap t:$mux", " ('-widemux' only)"); + if (widemux > 0 || help_mode) { std::string muxcover_args = " -dmux=0"; - switch (minmuxf) { + switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented // out of mux2s @@ -297,7 +297,7 @@ struct SynthXilinxPass : public ScriptPass case 15: muxcover_args += " -mux16=1350"; break; default: muxcover_args += " -mux16=1450"; break; } - run("muxcover " + muxcover_args, "('-minmuxf' only)"); + run("muxcover " + muxcover_args, "('-widemux' only)"); } } run("opt -full"); @@ -313,8 +313,8 @@ struct SynthXilinxPass : public ScriptPass std::string techmap_args = " -map +/techmap.v"; if (help_mode) techmap_args += " [-map +/xilinx/mux_map.v]"; - else if (minmuxf > 0) - techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", minmuxf); + else if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux); if (help_mode) techmap_args += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { @@ -330,8 +330,8 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; - if (minmuxf > 0) - techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", minmuxf); + if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); run("techmap " + techmap_args); run("clean"); } From 4ce329aefd34c53ab2b96cd79540c3e528661037 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 09:33:48 -0700 Subject: [PATCH 703/927] synth_ecp5 rename -nomux to -nowidelut, but preserve former --- techlibs/ecp5/synth_ecp5.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index c6e12248e..01222e55c 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -76,7 +76,7 @@ struct SynthEcp5Pass : public ScriptPass log(" -nodram\n"); log(" do not use distributed RAM cells in output netlist\n"); log("\n"); - log(" -nomux\n"); + log(" -nowidelut\n"); log(" do not use PFU muxes to implement LUTs larger than LUT4s\n"); log("\n"); log(" -abc2\n"); @@ -93,7 +93,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, nowidelut, flatten, retime, abc2, vpr; void clear_flags() YS_OVERRIDE { @@ -105,7 +105,7 @@ struct SynthEcp5Pass : public ScriptPass nodffe = false; nobram = false; nodram = false; - nomux = false; + nowidelut = false; flatten = true; retime = false; abc2 = false; @@ -172,8 +172,8 @@ struct SynthEcp5Pass : public ScriptPass nodram = true; continue; } - if (args[argidx] == "-nomux") { - nomux = true; + if (args[argidx] == "-nowidelut" || args[argidx] == "-nomux") { + nowidelut = true; continue; } if (args[argidx] == "-abc2") { @@ -264,7 +264,7 @@ struct SynthEcp5Pass : public ScriptPass run("abc", " (only if -abc2)"); } run("techmap -map +/ecp5/latches_map.v"); - if (nomux) + if (nowidelut) run("abc -lut 4 -dress"); else run("abc -lut 4:7 -dress"); From ea0b6258ab392b6186ee5d75a75da944b25d0392 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 26 Jun 2019 18:34:34 +0200 Subject: [PATCH 704/927] Simulation model verilog fix --- techlibs/ecp5/cells_sim.v | 13 ------------- techlibs/xilinx/cells_sim.v | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 2458c1ca0..07fadfa10 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -281,19 +281,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 diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 50d588a9e..f4598dcf4 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -282,7 +282,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; From cb722e7b58d634370bb013641dcccb2b5041febb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:06:33 -0700 Subject: [PATCH 705/927] Oops. Actually use nocarry flag as spotted by @koriakin --- techlibs/xilinx/synth_xilinx.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 27125d56c..dc2b4f2ac 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -254,11 +254,13 @@ struct SynthXilinxPass : public ScriptPass } if (help_mode) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v", "(skip if '-nocarry')"); - else if (!vpr) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); - else - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + run("techmap -map +/techmap.v [-map +/xilinx/arith_map.v]", "(skip if '-nocarry')"); + else if (!nocarry) { + if (!vpr) + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + else + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + } run("opt -fast"); } From 138989e1a3d0bb21eef5415f1b2ccfe49f6ef4ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:09:18 -0700 Subject: [PATCH 706/927] Fix spacing --- 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 dc2b4f2ac..ced132968 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -256,11 +256,11 @@ struct SynthXilinxPass : public ScriptPass if (help_mode) run("techmap -map +/techmap.v [-map +/xilinx/arith_map.v]", "(skip if '-nocarry')"); else if (!nocarry) { - if (!vpr) - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); - else - run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - } + if (!vpr) + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + else + run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + } run("opt -fast"); } From 988e6163abae4ed0a01952c221d17f70bed9c244 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:23:29 -0700 Subject: [PATCH 707/927] 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 708/927] 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 71b046d63996a1813375e56f44543e58eb7e1b5e Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 26 Jun 2019 18:17:52 +0100 Subject: [PATCH 709/927] tests: Check that Icarus can parse arch sim models Signed-off-by: David Shah --- Makefile | 1 + tests/arch/run-test.sh | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100755 tests/arch/run-test.sh diff --git a/Makefile b/Makefile index 76dac48a5..67bcb3d15 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/arch && bash run-test.sh @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh new file mode 100755 index 000000000..fc4175be8 --- /dev/null +++ b/tests/arch/run-test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +echo "Running syntax check on arch sim models" +for arch in ../../techlibs/*; do + find $arch -name cells_sim.v -print0 | xargs -0 -n1 -r iverilog -t null -I$arch +done From 6db181471ec1a45eb47a0bffd7378b22c1f7e24d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 10:47:03 -0700 Subject: [PATCH 710/927] Grrr --- 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 ced132968..dfe4c647b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -153,8 +153,8 @@ struct SynthXilinxPass : public ScriptPass nocarry = true; continue; } - if (args[argidx] == "-nomux") { - nomux = true; + if (args[argidx] == "-nowidelut") { + nowidelut = true; continue; } if (args[argidx] == "-vpr") { From 4d0014d1b1a9e747389172b94a45a7dd4af86c6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:23:57 -0700 Subject: [PATCH 711/927] Cleanup abc_box_id --- techlibs/xilinx/abc_xc7.box | 10 +++++----- techlibs/xilinx/cells_sim.v | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 67d1ffb1e..b1c24ed24 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -16,7 +16,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O -MUXF78 10 1 6 1 +MUXF78 3 1 6 1 190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X @@ -25,7 +25,7 @@ MUXF78 10 1 6 1 # (NB: carry chain input/output must be last # input/output and have been moved there # overriding the alphabetical ordering) -CARRY4 3 1 10 8 +CARRY4 4 1 10 8 482 - - - - 223 - - - 222 598 407 - - - 400 205 - - 334 584 556 537 - - 523 558 226 - 239 @@ -38,20 +38,20 @@ CARRY4 3 1 10 8 # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE # Outputs: DPO SPO -RAM32X1D 4 0 13 2 +RAM32X1D 5 0 13 2 - - - - - - 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 # Outputs: DPO SPO -RAM64X1D 5 0 15 2 +RAM64X1D 6 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 6 0 17 2 +RAM128X1D 7 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 e3391da40..58e9c74d5 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -170,7 +170,7 @@ module MUXF8(output O, input I0, I1, S); endmodule `ifdef _ABC -(* abc_box_id = 10, lib_whitebox *) +(* abc_box_id = 3, lib_whitebox *) module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); assign O = S1 ? (S0 ? I3 : I2) : (S0 ? I1 : I0); @@ -181,7 +181,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, abc_carry, lib_whitebox *) +(* abc_box_id = 4, 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]; @@ -289,7 +289,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 = 5, abc_scc_break="D" *) module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, @@ -307,7 +307,7 @@ module RAM32X1D ( 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 RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -325,7 +325,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 6, abc_scc_break="D" *) +(* abc_box_id = 7, abc_scc_break="D" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 8d8261c71fd34de7eb4cb5ae7bdb2592f33ed852 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:38:28 -0700 Subject: [PATCH 712/927] Do not call opt with -full before muxcover --- 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 0372cb43c..efa4d43f0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -288,7 +288,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + run("opt -fast"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From c762be593042ed5d812a3a37d494a82565cbaad0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:48:35 -0700 Subject: [PATCH 713/927] Instead of blocking wreduce on $mux, use -keepdc instead #1132 --- 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 efa4d43f0..278098a58 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -249,9 +249,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(selection for '-widemux' only)"); + run("wreduce [-keepdc]", "('-widemux' only)"); else - run("wreduce" + std::string(widemux > 0 ? " c:* t:$mux %d" : "")); + run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); From 6d9ba402632b1fd49e2c5ea63268682f126457c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 13:49:51 -0700 Subject: [PATCH 714/927] Add tests --- tests/various/muxcover.ys | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 8ef619b46..55179a991 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -188,3 +188,171 @@ 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: Wed, 26 Jun 2019 13:50:19 -0700 Subject: [PATCH 715/927] Rework muxcover decoder gen if more significant muxes are 1'bx --- passes/techmap/muxcover.cc | 98 ++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b0722134e..0f86aeff0 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -324,13 +324,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(G, tree, bit, "BBA"); ok = ok && follow_muxtree(H, tree, bit, "BBB"); - ok = ok && follow_muxtree(S1, tree, bit, "AAS"); - ok = ok && follow_muxtree(S2, tree, bit, "ABS"); - ok = ok && follow_muxtree(S3, tree, bit, "BAS"); - ok = ok && follow_muxtree(S4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4; + ok = ok && follow_muxtree(U1, tree, bit, "S"); ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); @@ -338,7 +332,14 @@ struct MuxcoverWorker if (nodecode) ok = ok && T1 == T2; - ok = ok && follow_muxtree(U1, tree, bit, "S"); + ok = ok && follow_muxtree(S1, tree, bit, "AAS"); + ok = ok && follow_muxtree(S2, tree, bit, "ABS"); + ok = ok && follow_muxtree(S3, tree, bit, "BAS"); + ok = ok && follow_muxtree(S4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4; + // ^^ Should already be checked by T1 == T2 above if (ok) { @@ -353,12 +354,16 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + if (T1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + } + else + S1 = RTLIL::Sx; + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); @@ -397,6 +402,23 @@ struct MuxcoverWorker ok = ok && follow_muxtree(O, tree, bit, "BBBA"); ok = ok && follow_muxtree(P, tree, bit, "BBBB"); + ok = ok && follow_muxtree(V1, tree, bit, "S"); + + ok = ok && follow_muxtree(U1, tree, bit, "AS"); + ok = ok && follow_muxtree(U2, tree, bit, "BS"); + + if (nodecode) + ok = ok && U1 == U2; + + ok = ok && follow_muxtree(T1, tree, bit, "AAS"); + ok = ok && follow_muxtree(T2, tree, bit, "ABS"); + ok = ok && follow_muxtree(T3, tree, bit, "BAS"); + ok = ok && follow_muxtree(T4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && T1 == T2 && /*T2 == T3 &&*/ T3 == T4; + // ^^ Should already be checked by U1 == U2 above + ok = ok && follow_muxtree(S1, tree, bit, "AAAS"); ok = ok && follow_muxtree(S2, tree, bit, "AABS"); ok = ok && follow_muxtree(S3, tree, bit, "ABAS"); @@ -407,23 +429,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 && follow_muxtree(T1, tree, bit, "AAS"); - ok = ok && follow_muxtree(T2, tree, bit, "ABS"); - ok = ok && follow_muxtree(T3, tree, bit, "BAS"); - ok = ok && follow_muxtree(T4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && T1 == T2 && T2 == T3 && 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 && follow_muxtree(V1, tree, bit, "S"); + ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4 && /*S4 == S5 &&*/ S5 == S6 && /*S6 == S7 &&*/ S7 == S8; if (ok) { @@ -446,20 +452,30 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + if (U1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + + if (T1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + } + else + S1 = RTLIL::Sx; + } + else { + T1 = RTLIL::Sx; + S1 = RTLIL::Sx; + } + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From 585e6ddc6c55bcd5911124d58048701ea82da494 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 14:16:44 -0700 Subject: [PATCH 716/927] Let's not go crazy: use nonzero costs --- tests/various/muxcover.ys | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 55179a991..fb0556675 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -200,7 +200,7 @@ prep design -save gold techmap -muxcover -mux4=0 -nodecode +muxcover -mux4=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -228,7 +228,7 @@ prep design -save gold techmap -muxcover -mux8=0 -nodecode +muxcover -mux8=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -256,7 +256,7 @@ prep design -save gold techmap -muxcover -mux8=0 -nodecode +muxcover -mux8=299 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -284,7 +284,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -312,7 +312,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=299 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -341,7 +341,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=699 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ From 8ef64a19e795e08fa85c8baf8a7c57067efd8e54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 15:13:25 -0700 Subject: [PATCH 717/927] Revert "Rework muxcover decoder gen if more significant muxes are 1'bx" This reverts commit b2b5cf78e21def63c54c080217d77afefba8e4c7. --- passes/techmap/muxcover.cc | 98 ++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 0f86aeff0..b0722134e 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -324,7 +324,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(G, tree, bit, "BBA"); ok = ok && follow_muxtree(H, tree, bit, "BBB"); - ok = ok && follow_muxtree(U1, tree, bit, "S"); + ok = ok && follow_muxtree(S1, tree, bit, "AAS"); + ok = ok && follow_muxtree(S2, tree, bit, "ABS"); + ok = ok && follow_muxtree(S3, tree, bit, "BAS"); + ok = ok && follow_muxtree(S4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && S1 == S2 && S2 == S3 && S3 == S4; ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); @@ -332,14 +338,7 @@ struct MuxcoverWorker if (nodecode) ok = ok && T1 == T2; - ok = ok && follow_muxtree(S1, tree, bit, "AAS"); - ok = ok && follow_muxtree(S2, tree, bit, "ABS"); - ok = ok && follow_muxtree(S3, tree, bit, "BAS"); - ok = ok && follow_muxtree(S4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4; - // ^^ Should already be checked by T1 == T2 above + ok = ok && follow_muxtree(U1, tree, bit, "S"); if (ok) { @@ -354,15 +353,11 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); - if (T1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - } - else - S1 = RTLIL::Sx; + mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -402,23 +397,6 @@ struct MuxcoverWorker ok = ok && follow_muxtree(O, tree, bit, "BBBA"); ok = ok && follow_muxtree(P, tree, bit, "BBBB"); - ok = ok && follow_muxtree(V1, tree, bit, "S"); - - ok = ok && follow_muxtree(U1, tree, bit, "AS"); - ok = ok && follow_muxtree(U2, tree, bit, "BS"); - - if (nodecode) - ok = ok && U1 == U2; - - ok = ok && follow_muxtree(T1, tree, bit, "AAS"); - ok = ok && follow_muxtree(T2, tree, bit, "ABS"); - ok = ok && follow_muxtree(T3, tree, bit, "BAS"); - ok = ok && follow_muxtree(T4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && T1 == T2 && /*T2 == T3 &&*/ T3 == T4; - // ^^ Should already be checked by U1 == U2 above - ok = ok && follow_muxtree(S1, tree, bit, "AAAS"); ok = ok && follow_muxtree(S2, tree, bit, "AABS"); ok = ok && follow_muxtree(S3, tree, bit, "ABAS"); @@ -429,7 +407,23 @@ 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 && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; + + ok = ok && follow_muxtree(T1, tree, bit, "AAS"); + ok = ok && follow_muxtree(T2, tree, bit, "ABS"); + ok = ok && follow_muxtree(T3, tree, bit, "BAS"); + ok = ok && follow_muxtree(T4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && T1 == T2 && T2 == T3 && 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 && follow_muxtree(V1, tree, bit, "S"); if (ok) { @@ -452,30 +446,20 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + mux.cost += prepare_decode_mux(U1, U2, V1, bit); - if (U1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - - if (T1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - } - else - S1 = RTLIL::Sx; - } - else { - T1 = RTLIL::Sx; - S1 = RTLIL::Sx; - } - mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From 9cba05285b14ffb3433e2e9d9e44b755311562f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:06:30 -0700 Subject: [PATCH 718/927] muxcover to be undef-sensitive when computing decoders --- passes/techmap/muxcover.cc | 63 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b0722134e..61471e446 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -151,7 +151,7 @@ struct MuxcoverWorker return true; } char port_name[3] = {'\\', *path, 0}; - return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false); + return follow_muxtree(ret_bit, tree, tree.muxes.at(bit)->getPort(port_name), path+1, false); } else { ret_bit = bit; return true; @@ -160,7 +160,7 @@ struct MuxcoverWorker int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit) { - if (A == B || sel == State::Sx) + if (A == B || sel == State::Sx || A == State::Sx || B == State::Sx) return 0; tuple key(A, B, sel); @@ -330,13 +330,15 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S4, tree, bit, "BBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4; + ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && + /*S2 == S3 && */ + (S3 == S4 || S3 == State::Sx || S4 == State::Sx); ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); if (nodecode) - ok = ok && T1 == T2; + ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx); ok = ok && follow_muxtree(U1, tree, bit, "S"); @@ -353,11 +355,12 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) + mux.cost += prepare_decode_mux(S1, S3, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -407,7 +410,13 @@ 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 && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && + /*S2 == S3 &&*/ + (S3 == S4 || S3 == State::Sx || S4 == State::Sx) && + /*S4 == S5 &&*/ + (S5 == S6 || S5 == State::Sx || S6 == State::Sx) && + /*S6 == S7 &&*/ + (S7 == S8 || S7 == State::Sx || S8 == State::Sx); ok = ok && follow_muxtree(T1, tree, bit, "AAS"); ok = ok && follow_muxtree(T2, tree, bit, "ABS"); @@ -415,13 +424,15 @@ struct MuxcoverWorker ok = ok && follow_muxtree(T4, tree, bit, "BBS"); if (nodecode) - ok = ok && T1 == T2 && T2 == T3 && T3 == T4; + ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx) && + /*T2 == T3 &&*/ + (T3 == T4 || T3 == State::Sx || T4 == State::Sx); ok = ok && follow_muxtree(U1, tree, bit, "AS"); ok = ok && follow_muxtree(U2, tree, bit, "BS"); if (nodecode) - ok = ok && U1 == U2; + ok = ok && (U1 == U2 || U1 == State::Sx || U2 == State::Sx); ok = ok && follow_muxtree(V1, tree, bit, "S"); @@ -446,20 +457,28 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + if (U1 != State::Sx && U2 != State::Sx) { + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + } + + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + } + if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) { + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + } + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx && + T3 != T4 && T3 != State::Sx && T4 != State::Sx) + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From ca1fac7c4758b54feda24f28c9d46bb44fbd2cb8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:07:07 -0700 Subject: [PATCH 719/927] Add more tests --- tests/various/muxcover.ys | 152 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index fb0556675..67e9625e6 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -356,3 +356,155 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + +## mux_if_bal_5_1 :: https://github.com/YosysHQ/yosys/issues/1132 + +design -reset +read_verilog -formal < Date: Wed, 26 Jun 2019 16:16:44 -0700 Subject: [PATCH 720/927] Restore sigmap wrapper --- passes/techmap/muxcover.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 61471e446..ce9d145d4 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -151,7 +151,7 @@ struct MuxcoverWorker return true; } char port_name[3] = {'\\', *path, 0}; - return follow_muxtree(ret_bit, tree, tree.muxes.at(bit)->getPort(port_name), path+1, false); + return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false); } else { ret_bit = bit; return true; From 5f807a7a5b3f4c1eae7b75ad93d90f3d202e2b6c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:25:48 -0700 Subject: [PATCH 721/927] Return to upstream synth_xilinx with opt -full and wreduce --- techlibs/xilinx/synth_xilinx.cc | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 278098a58..c139fb3c4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -241,26 +241,10 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { - run("proc"); - if (flatten || help_mode) - run("flatten", "(with -flatten only)"); - run("opt_expr"); - run("opt_clean"); - run("check"); - run("opt"); if (help_mode) - run("wreduce [-keepdc]", "('-widemux' only)"); + run("synth -run coarse [-flatten]", "(with '-flatten')"); else - run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); - run("peepopt"); - run("opt_clean"); - run("alumacc"); - run("share"); - run("opt"); - run("fsm"); - run("opt -fast"); - run("memory -nomap"); - run("opt_clean"); + run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -288,7 +272,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast"); + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From d7d5ea6e0cc7cc0db7bb510d3d265dafc7aa93ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:13:56 -0700 Subject: [PATCH 722/927] Remove redundant check (done further down) --- passes/techmap/muxcover.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index ce9d145d4..b162fae22 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -160,7 +160,7 @@ struct MuxcoverWorker int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit) { - if (A == B || sel == State::Sx || A == State::Sx || B == State::Sx) + if (A == B || sel == State::Sx) return 0; tuple key(A, B, sel); From dd4667ef2bfc83a45552e43d9252375df4b8fedf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:33:26 -0700 Subject: [PATCH 723/927] Emprically (even if I don't fully understand it) this passes picorv32 tb --- passes/techmap/muxcover.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b162fae22..5642aeafc 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -459,25 +459,24 @@ struct MuxcoverWorker mux.cost += prepare_decode_mux(U1, U2, V1, bit); - if (U1 != State::Sx && U2 != State::Sx) { - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + if (U1 != U2 && U1 != State::Sx && U2 != State::Sx) { mux.cost += prepare_decode_mux(T1, T3, V1, bit); - } - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) { mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - } - if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) { + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); + if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + + if (T1 != T3 && T1 != State::Sx && T3 != State::Sx) + mux.cost += prepare_decode_mux(S1, S5, V1, bit); } - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx && - T3 != T4 && T3 != State::Sx && T4 != State::Sx) - mux.cost += prepare_decode_mux(S1, S5, V1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); From cae69a3eddda997c04aa7c6bd642f71ee1033477 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:41:21 -0700 Subject: [PATCH 724/927] Rework help_mode for synth_xilinx -widemux --- techlibs/xilinx/synth_xilinx.cc | 45 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c139fb3c4..199d0737d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -276,29 +276,30 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (widemux > 0 || help_mode) { - run("simplemap t:$mux", " ('-widemux' only)"); - if (widemux > 0 || help_mode) { - std::string muxcover_args = " -dmux=0"; - switch (widemux) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - case 5: muxcover_args += " -mux8=350 -mux16=400"; break; - case 6: muxcover_args += " -mux8=450 -mux16=500"; break; - case 7: muxcover_args += " -mux8=550 -mux16=600"; break; - case 8: muxcover_args += " -mux8=650 -mux16=700"; break; - case 9: muxcover_args += " -mux16=750"; break; - case 10: muxcover_args += " -mux16=850"; break; - case 11: muxcover_args += " -mux16=950"; break; - case 12: muxcover_args += " -mux16=1050"; break; - case 13: muxcover_args += " -mux16=1150"; break; - case 14: muxcover_args += " -mux16=1250"; break; - case 15: muxcover_args += " -mux16=1350"; break; - default: muxcover_args += " -mux16=1450"; break; - } - run("muxcover " + muxcover_args, "('-widemux' only)"); + if (help_mode) { + run("simplemap t:$mux", " ('-widemux' only)"); + run("muxcover -dmux=0 -mux8= -mux16=, ('-widemux' only)"); + } + else if (widemux > 0) { + std::string muxcover_args = " -dmux=0"; + switch (widemux) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + case 5: muxcover_args += " -mux8=350 -mux16=400"; break; + case 6: muxcover_args += " -mux8=450 -mux16=500"; break; + case 7: muxcover_args += " -mux8=550 -mux16=600"; break; + case 8: muxcover_args += " -mux8=650 -mux16=700"; break; + case 9: muxcover_args += " -mux16=750"; break; + case 10: muxcover_args += " -mux16=850"; break; + case 11: muxcover_args += " -mux16=950"; break; + case 12: muxcover_args += " -mux16=1050"; break; + case 13: muxcover_args += " -mux16=1150"; break; + case 14: muxcover_args += " -mux16=1250"; break; + case 15: muxcover_args += " -mux16=1350"; break; + default: muxcover_args += " -mux16=1450"; break; } + run("muxcover " + muxcover_args); } run("opt -full"); From 2b104ed6c8f86a62d192b43fe3f73cc6f0b43e27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:42:50 -0700 Subject: [PATCH 725/927] Replace with --- 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 199d0737d..877694e8a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -277,8 +277,8 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (help_mode) { - run("simplemap t:$mux", " ('-widemux' only)"); - run("muxcover -dmux=0 -mux8= -mux16=, ('-widemux' only)"); + run("simplemap t:$mux", " ('-widemux' only)"); + run("muxcover , ('-widemux' only)"); } else if (widemux > 0) { std::string muxcover_args = " -dmux=0"; From f0a1726a1ad4e14cdee81769565b80bea6cb48ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:48:49 -0700 Subject: [PATCH 726/927] Accidentally removed "simplemap $mux" --- 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 877694e8a..c3f434c51 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -281,6 +281,7 @@ struct SynthXilinxPass : public ScriptPass run("muxcover , ('-widemux' only)"); } else if (widemux > 0) { + run("simplemap t:$mux"); std::string muxcover_args = " -dmux=0"; switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 From b9ff0503f39795a1f749c955b129d9972fe03f0a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:57:10 -0700 Subject: [PATCH 727/927] synth_xilinx's muxcover call to be very conservative -- -nodecode --- 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 c3f434c51..2f3dfb012 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,7 +282,7 @@ struct SynthXilinxPass : public ScriptPass } else if (widemux > 0) { run("simplemap t:$mux"); - std::string muxcover_args = " -dmux=0"; + std::string muxcover_args = " -nodecode"; switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented From 1d0be89214466aa5120d6fc0e155c6366ae8e802 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:17:11 -0700 Subject: [PATCH 728/927] 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 729/927] 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 730/927] 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 731/927] 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 732/927] 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 733/927] 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 734/927] 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 593e4a30bb76ac1b64945b7b8090bedbd0bfb228 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:09:28 -0700 Subject: [PATCH 735/927] MUXF78 -> $__MUXF78 to indicate internal --- techlibs/xilinx/abc_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 7fe8a7236..273d36573 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -16,7 +16,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O -MUXF78 3 1 6 1 +$__MUXF78 3 1 6 1 190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X From 69d810e4a831fc1f17d886d7f371d9785e9022e7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 27 Jun 2019 09:42:49 +0200 Subject: [PATCH 736/927] Fix handling of partial covers in muxcover, fixes #1132 Signed-off-by: Clifford Wolf --- passes/techmap/muxcover.cc | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) 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"); From 7c14678ec0f4b16134d94a7419f59e7edb634cf6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 27 Jun 2019 10:59:12 +0200 Subject: [PATCH 737/927] Add "pmux2shiftx -norange", fixes #1135 Signed-off-by: Clifford Wolf --- CHANGELOG | 1 + passes/opt/pmux2shiftx.cc | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8c88a7db8..b8e53b4cf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "muxcover -dmux=" - Added "muxcover -nopartial" - Added "muxpack" pass + - Added "pmux2shiftx -norange" - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" - Fixed sign extension of unsized constants with 'bx and 'bz MSB diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 29870f510..65d8b8f32 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -221,6 +221,9 @@ struct Pmux2ShiftxPass : public Pass { log(" select strategy for one-hot encoded control signals\n"); log(" default: pmux\n"); log("\n"); + log(" -norange\n"); + log(" disable $sub inference for \"range decoders\"\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -230,6 +233,7 @@ struct Pmux2ShiftxPass : public Pass { bool optimize_onehot = true; bool verbose = false; bool verbose_onehot = false; + bool norange = false; log_header(design, "Executing PMUX2SHIFTX pass.\n"); @@ -270,6 +274,10 @@ struct Pmux2ShiftxPass : public Pass { verbose_onehot = true; continue; } + if (args[argidx] == "-norange") { + norange = true; + continue; + } break; } extra_args(args, argidx, design); @@ -559,7 +567,7 @@ struct Pmux2ShiftxPass : public Pass { int this_inv_delta = this_maxval - this_minval; bool this_inv = false; - if (this_delta != this_inv_delta) + if (!norange && this_delta != this_inv_delta) this_inv = this_inv_delta < this_delta; else if (this_maxval != this_inv_maxval) this_inv = this_inv_maxval < this_maxval; @@ -574,7 +582,7 @@ struct Pmux2ShiftxPass : public Pass { if (best_src_col < 0) this_is_better = true; - else if (this_delta != best_delta) + else if (!norange && this_delta != best_delta) this_is_better = this_delta < best_delta; else if (this_maxval != best_maxval) this_is_better = this_maxval < best_maxval; @@ -656,7 +664,7 @@ struct Pmux2ShiftxPass : public Pass { // check density percentages Const offset(State::S0, GetSize(sig)); - if (absolute_density < min_density && range_density >= min_density) + if (!norange && absolute_density < min_density && range_density >= min_density) { offset = Const(min_choice, GetSize(sig)); log(" offset: %s\n", log_signal(offset)); From 3910bc2ea63fa5ed0f3c961126866639058f651d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 06:01:50 -0700 Subject: [PATCH 738/927] Copy tests from eddie/fix1132 --- tests/various/muxcover.ys | 320 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) 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 06:02:25 -0700 Subject: [PATCH 739/927] Revert muxcover.cc to master --- passes/techmap/muxcover.cc | 52 +++++++++++++------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 5642aeafc..b0722134e 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -330,15 +330,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S4, tree, bit, "BBS"); if (nodecode) - ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && - /*S2 == S3 && */ - (S3 == S4 || S3 == State::Sx || S4 == State::Sx); + ok = ok && S1 == S2 && S2 == S3 && S3 == S4; ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); if (nodecode) - ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx); + ok = ok && T1 == T2; ok = ok && follow_muxtree(U1, tree, bit, "S"); @@ -355,12 +353,11 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) - mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + + mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -410,13 +407,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && - /*S2 == S3 &&*/ - (S3 == S4 || S3 == State::Sx || S4 == State::Sx) && - /*S4 == S5 &&*/ - (S5 == S6 || S5 == State::Sx || S6 == State::Sx) && - /*S6 == S7 &&*/ - (S7 == S8 || S7 == State::Sx || S8 == State::Sx); + ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; ok = ok && follow_muxtree(T1, tree, bit, "AAS"); ok = ok && follow_muxtree(T2, tree, bit, "ABS"); @@ -424,15 +415,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(T4, tree, bit, "BBS"); if (nodecode) - ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx) && - /*T2 == T3 &&*/ - (T3 == T4 || T3 == State::Sx || T4 == State::Sx); + ok = ok && T1 == T2 && T2 == T3 && T3 == T4; ok = ok && follow_muxtree(U1, tree, bit, "AS"); ok = ok && follow_muxtree(U2, tree, bit, "BS"); if (nodecode) - ok = ok && (U1 == U2 || U1 == State::Sx || U2 == State::Sx); + ok = ok && U1 == U2; ok = ok && follow_muxtree(V1, tree, bit, "S"); @@ -457,26 +446,19 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.cost += prepare_decode_mux(T3, T4, U2, bit); - if (U1 != U2 && U1 != State::Sx && U2 != State::Sx) { - mux.cost += prepare_decode_mux(T1, T3, V1, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - - if (T1 != T3 && T1 != State::Sx && T3 != State::Sx) - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - } + mux.cost += prepare_decode_mux(U1, U2, V1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); From 760819e10d1866ef4590f2fbaf20eed36cd7925d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 07:24:47 -0700 Subject: [PATCH 740/927] synth_xilinx -arch -> -family, consistent with older synth_intel --- 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 dfe4c647b..7dc9915e9 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -42,8 +42,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"); @@ -90,7 +91,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; void clear_flags() YS_OVERRIDE @@ -106,7 +107,7 @@ struct SynthXilinxPass : public ScriptPass nosrl = false; nocarry = false; nowidelut = false; - arch = "xc7"; + family = "xc7"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -121,8 +122,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()) { @@ -177,8 +178,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"); From 18acb72c05d270e2224ce55919cfb0524efb5757 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:02:52 -0700 Subject: [PATCH 741/927] Add #1135 testcase --- tests/various/pmux2shiftx.v | 10 ++++++++++ tests/various/pmux2shiftx.ys | 19 +++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/various/pmux2shiftx.v b/tests/various/pmux2shiftx.v index fec84187b..563394080 100644 --- a/tests/various/pmux2shiftx.v +++ b/tests/various/pmux2shiftx.v @@ -32,3 +32,13 @@ module pmux2shiftx_test ( endcase end endmodule + +module issue01135(input [7:0] i, output o); +always @* +case (i[6:3]) + 4: o <= i[0]; + 3: o <= i[2]; + 7: o <= i[3]; + default: o <= 1'b0; +endcase +endmodule diff --git a/tests/various/pmux2shiftx.ys b/tests/various/pmux2shiftx.ys index deb134083..51ee2f7be 100644 --- a/tests/various/pmux2shiftx.ys +++ b/tests/various/pmux2shiftx.ys @@ -1,4 +1,7 @@ read_verilog pmux2shiftx.v +design -save read + +hierarchy -top pmux2shiftx_test prep design -save gold @@ -21,8 +24,16 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter -design -load gold -stat +#design -load gold +#stat +# +#design -load gate +#stat -design -load gate -stat +design -load read +hierarchy -top issue01135 +proc +pmux2shiftx -norange +opt -full +select -assert-count 0 t:$shift* +select -assert-count 1 t:$pmux From ab7c4319058bbae8758cda9f246c92c324dfafbf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:13:49 -0700 Subject: [PATCH 742/927] Add simcells.v, simlib.v, and some output --- tests/arch/run-test.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh index fc4175be8..5292d1615 100755 --- a/tests/arch/run-test.sh +++ b/tests/arch/run-test.sh @@ -4,5 +4,15 @@ set -e echo "Running syntax check on arch sim models" for arch in ../../techlibs/*; do - find $arch -name cells_sim.v -print0 | xargs -0 -n1 -r iverilog -t null -I$arch + find $arch -name cells_sim.v | while read path; do + echo -n "Test $path ->" + iverilog -t null -I$arch $path + echo " ok" + done +done + +for path in "../../techlibs/common/simcells.v" "../../techlibs/common/simlib.v"; do + echo -n "Test $path ->" + iverilog -t null $path + echo " ok" done From 6c256b8cda66e2ba128d5fa3ba344fe4717711f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:20:15 -0700 Subject: [PATCH 743/927] 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 744/927] 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 745/927] 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 d5cfe341f9a2d8decbef1b59617f51ae6369f0a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:25:57 -0700 Subject: [PATCH 746/927] Make CHANGELOG clearer --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index b8e53b4cf..6931c3de0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ 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 "muxcover -mux{4,8,16}=" - Added "muxcover -dmux=" From 36f3cc9dcc07fc8a0c718fa0611ec39fd267900b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:26:44 -0700 Subject: [PATCH 747/927] Capitalisation --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 6931c3de0..6f476a2cb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,7 +47,7 @@ Yosys 0.7 .. Yosys 0.8 - Added Verilog $rtoi and $itor support - Added "check -initdrv" - Added "read_blif -wideports" - - Added support for systemVerilog "++" and "--" operators + - Added support for SystemVerilog "++" and "--" operators - Added support for SystemVerilog unique, unique0, and priority case - Added "write_edif" options for edif "flavors" - Added support for resetall compiler directive From eab8384ec7108db62573567f9fbceca62adfdbe5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 11:53:42 -0700 Subject: [PATCH 748/927] Grr --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 6f476a2cb..4d0c31e28 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,7 +23,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "muxcover -nopartial" - Added "muxpack" pass - Added "pmux2shiftx -norange" - - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" + - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 35fa7b30574244e4f99373f2a790f004b4a1dbbb Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 27 Jun 2019 22:02:12 +0200 Subject: [PATCH 749/927] Fix memory leak when one of multiple DFF cells is removed in opt_rmdff When there are multiple DFFs and one of them is removed, its reference lingers inside bit2driver dict. While invoking handle_dff() function for other DFFs, this broken reference is used isnside sat_import_cell() function. --- passes/opt/opt_rmdff.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 5fc28ae92..17e0d7cd4 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -530,6 +530,11 @@ delete_dff: log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); remove_init_attr(dff->getPort("\\Q")); mod->remove(dff); + + for (auto &entry : bit2driver) + if (entry.second == dff) + bit2driver.erase(entry.first); + return true; } From 3225bfb98403271bbe8a56418ccd027b42eabda1 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 27 Jun 2019 22:06:23 +0200 Subject: [PATCH 750/927] Add help for "-sat" option inside opt_rmdff. "opt" can pass "-sat" too --- passes/opt/opt.cc | 8 ++++++-- passes/opt/opt_rmdff.cc | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index a4aca2fee..e9a43e0f3 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -44,7 +44,7 @@ struct OptPass : public Pass { log(" opt_muxtree\n"); log(" opt_reduce [-fine] [-full]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_rmdff [-keepdc]\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" while \n"); @@ -54,7 +54,7 @@ struct OptPass : public Pass { log(" do\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_rmdff [-keepdc]\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" while \n"); log("\n"); @@ -112,6 +112,10 @@ struct OptPass : public Pass { opt_rmdff_args += " -keepdc"; continue; } + if (args[argidx] == "-sat") { + opt_rmdff_args += " -sat"; + continue; + } if (args[argidx] == "-share_all") { opt_merge_args += " -share_all"; continue; diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 17e0d7cd4..be6ac2d30 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -549,6 +549,10 @@ struct OptRmdffPass : public Pass { log("This pass identifies flip-flops with constant inputs and replaces them with\n"); log("a constant driver.\n"); log("\n"); + log(" -sat\n"); + log(" additionally invoke SAT solver to detect and remove flip-flops (with \n"); + log(" non-constant inputs) that can also be replaced with a constant driver\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From fb30fcb7c582406f627ebb15833791411091f738 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 15:03:21 -0700 Subject: [PATCH 751/927] 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 752/927] 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 753/927] 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 754/927] 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 755/927] 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 756/927] 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 757/927] 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 758/927] 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 759/927] 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 6f1c1379891651b0d110e35fb2c73fd78fde3f69 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Thu, 27 Jun 2019 22:54:09 -0400 Subject: [PATCH 760/927] tests: use optional ABCEXTERNAL when specified Commits 65924fd1, abc40924, and ebe29b66 hard-code the invocation of yosys-abc, which fails if ABCEXTERNAL was specified during the build. Allow tests to utilize an optional, externally specified abc binary. Signed-off-by: Gabriel Somlo --- Makefile | 10 ++++++++-- tests/aiger/run-test.sh | 14 ++++++++++++-- tests/memories/run-test.sh | 6 ++++-- tests/tools/autotest.sh | 7 +++++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 67bcb3d15..5ec3e0312 100644 --- a/Makefile +++ b/Makefile @@ -666,6 +666,12 @@ else SEEDOPT="" endif +ifneq ($(ABCEXTERNAL),) +ABCOPT="-A $(ABCEXTERNAL)" +else +ABCOPT="" +endif + test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/simple && bash run-test.sh $(SEEDOPT) +cd tests/hana && bash run-test.sh $(SEEDOPT) @@ -674,13 +680,13 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/share && bash run-test.sh $(SEEDOPT) +cd tests/fsm && bash run-test.sh $(SEEDOPT) +cd tests/techmap && bash run-test.sh - +cd tests/memories && bash run-test.sh $(SEEDOPT) + +cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT) +cd tests/bram && bash run-test.sh $(SEEDOPT) +cd tests/various && bash run-test.sh +cd tests/sat && bash run-test.sh +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +cd tests/opt && bash run-test.sh - +cd tests/aiger && bash run-test.sh + +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh @echo "" @echo " Passed \"make test\"." diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 5246c1b48..deaf48a3d 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -2,6 +2,16 @@ set -e +OPTIND=1 +abcprog="../../yosys-abc" # default to built-in version of abc +while getopts "A:" opt +do + case "$opt" in + A) abcprog="$OPTARG" ;; + esac +done +shift "$((OPTIND-1))" + # NB: *.aag and *.aig must contain a symbol table naming the primary # inputs and outputs, otherwise ABC and Yosys will name them # arbitrarily (and inconsistently with each other). @@ -11,7 +21,7 @@ for aag in *.aag; do # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) echo "Checking $aag." - ../../yosys-abc -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" ../../yosys -qp " read_verilog ${aag%.*}_ref.v prep @@ -28,7 +38,7 @@ done for aig in *.aig; do echo "Checking $aig." - ../../yosys-abc -q "read -c $aig; write ${aig%.*}_ref.v" + $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" ../../yosys -qp " read_verilog ${aig%.*}_ref.v prep diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh index d0537bb98..76acaa9cd 100755 --- a/tests/memories/run-test.sh +++ b/tests/memories/run-test.sh @@ -4,15 +4,17 @@ set -e OPTIND=1 seed="" # default to no seed specified -while getopts "S:" opt +abcopt="" +while getopts "A:S:" opt do case "$opt" in + A) abcopt="-A $OPTARG" ;; S) seed="-S $OPTARG" ;; esac done shift "$((OPTIND-1))" -bash ../tools/autotest.sh $seed -G *.v +bash ../tools/autotest.sh $abcopt $seed -G *.v for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do echo -n "Testing expectations for $f .." diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 96d9cdda9..7b64b357f 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -23,12 +23,13 @@ warn_iverilog_git=false # The tests are skipped if firrtl2verilog is the empty string (the default). firrtl2verilog="" xfirrtl="../xfirrtl" +abcprog="$toolsdir/../../yosys-abc" if [ ! -f $toolsdir/cmp_tbdata -o $toolsdir/cmp_tbdata.c -nt $toolsdir/cmp_tbdata ]; then ( set -ex; ${CC:-gcc} -Wall -o $toolsdir/cmp_tbdata $toolsdir/cmp_tbdata.c; ) || exit 1 fi -while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do +while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do case "$opt" in x) use_xsim=true ;; @@ -65,6 +66,8 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do include_opts="$include_opts -I $OPTARG" xinclude_opts="$xinclude_opts -i $OPTARG" minclude_opts="$minclude_opts +incdir+$OPTARG" ;; + A) + abcprog="$OPTARG" ;; -) case "${OPTARG}" in xfirrtl) @@ -147,7 +150,7 @@ do if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then - "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" + $abcprog -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" else refext=$ext cp ../${fn} ${bn}_ref.${refext} From af744097496702926f4fbff5d6eb889ad82fa6cf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 28 Jun 2019 10:21:16 +0200 Subject: [PATCH 761/927] Improve specify dummy parser, fixes #1144 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index d89b2dc88..dab5b5919 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1068,11 +1068,18 @@ list_of_path_delay_extra_expressions : path_delay_expression ',' path_delay_expression ',' path_delay_expression ; +specify_edge_identifier : + TOK_POSEDGE | TOK_NEGEDGE ; + parallel_path_description : - '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ; + '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' | + '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor opt_polarity_operator ':' ignspec_expr ')' ')' | + '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr ')' ')' ; full_path_description : - '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ; + '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' | + '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs opt_polarity_operator ':' ignspec_expr ')' ')' | + '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs TOK_POS_INDEXED ignspec_expr ')' ')' ; // This was broken into 2 rules to solve shift/reduce conflicts list_of_path_inputs : From b9ddee0c87ef3f089995d734ad7f5ea1c65eedce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:45:40 -0700 Subject: [PATCH 762/927] 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 763/927] 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 764/927] 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 765/927] 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 766/927] 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 767/927] 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 768/927] 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" From dc677c791de438a493ad5e0101987da29c6a6d0f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 10:12:48 -0700 Subject: [PATCH 769/927] Add test from #1144, and try reading without '-specify' flag --- tests/various/specify.v | 14 ++++++++++++++ tests/various/specify.ys | 2 ++ 2 files changed, 16 insertions(+) diff --git a/tests/various/specify.v b/tests/various/specify.v index afc421da8..b1f399267 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -28,3 +28,17 @@ module test2 ( (B => Q) = 1.5; endspecify endmodule + +module issue01144(input clk, d, output q); +specify + // Fails: + (posedge clk => (q +: d)) = (3,1); + (/*posedge*/ clk => (q +: d)) = (3,1); + (posedge clk *> (q +: d)) = (3,1); + (/*posedge*/ clk *> (q +: d)) = (3,1); + + // Works: + (/*posedge*/ clk => q) = (3,1); + (/*posedge*/ clk *> q) = (3,1); +endspecify +endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index a5ca07219..a2b6038e4 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -54,3 +54,5 @@ equiv_struct equiv_induct -seq 5 equiv_status -assert design -reset + +read_verilog specify.v From 4a2a93aa069db9397175a98a6836953ee71223d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:10:36 -0700 Subject: [PATCH 770/927] Fix spacing --- 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 3721b82b7..f107f9947 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -673,8 +673,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto cell : boxes) - module->remove(cell); + for (auto cell : boxes) + module->remove(cell); // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { From c5b3830f737310602118851416f9c1931ad91a19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:12:41 -0700 Subject: [PATCH 771/927] Update CHANGELOG with -widemux --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 439870ac8..f10301427 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,7 +29,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - - "synth_xilinx" to now infer wide multiplexers (-nomux to disable) + - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From b5f1bd0df1a467679a93d05604c6cc72696854ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:16:15 -0700 Subject: [PATCH 772/927] Add missing CHANGELOG entries --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index c280f4f12..15dd5d002 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,9 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "muxcover -nopartial" - Added "muxpack" pass - Added "pmux2shiftx -norange" + - Added "synth_xilinx -nocarry" + - Added "synth_xilinx -nowidelut" + - Added "synth_ecp5 -nowidelut" - Added "write_xaiger" backend - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) From 0d347e17089eb4b23ef444a7c9adf8420aa2c93e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:28:29 -0700 Subject: [PATCH 773/927] Replace log_assert() with meaningful log_error() --- frontends/aiger/aigerparse.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7008d0542..1ac0f7ba4 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -376,7 +376,11 @@ void AigerReader::parse_xaiger() continue; if (m->name.begins_with("$paramod")) continue; - auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name)); + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); log_assert(r.second); } From cf020befeb99df2296f2efe722410e49becb44dd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:28:50 -0700 Subject: [PATCH 774/927] Fix CARRY4 abc_box_id --- 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 94bc3ef86..3937d3536 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -181,7 +181,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, abc_carry="CI,CO", lib_whitebox *) +(* abc_box_id = 4, 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]; From 8cb3655ecdf89102213a33c7474fb85f1ad0a033 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Fri, 28 Jun 2019 14:54:58 -0400 Subject: [PATCH 775/927] Make abc9 pass aware of optional ABCEXTERNAL override Signed-off-by: Gabriel Somlo --- passes/techmap/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index c45571b01..56f05eca4 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -10,6 +10,7 @@ OBJS += passes/techmap/abc.o OBJS += passes/techmap/abc9.o ifneq ($(ABCEXTERNAL),) passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' +passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' endif endif From a193bf27c94153d6cf27848391f1738bacff06b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:03:43 -0700 Subject: [PATCH 776/927] Clean up trimming leading 1'bx in A during techmappnig --- techlibs/xilinx/cells_map.v | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index cce70d69e..c6e734974 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -170,19 +170,14 @@ module \$__XILINX_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; + function integer A_WIDTH_trimmed; + input integer start; 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 + A_WIDTH_trimmed = start; + while (A_WIDTH_trimmed > 0 && _TECHMAP_CONSTMSK_A_[A_WIDTH_trimmed-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH_trimmed-1] === 1'bx) + A_WIDTH_trimmed = A_WIDTH_trimmed - 1; end endfunction - localparam num_leading_X_in_A = compute_num_leading_X_in_A(); generate genvar i, j; @@ -200,11 +195,10 @@ module \$__XILINX_SHIFTX (A, B, Y); 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)); + // Trim off any leading 1'bx -es in A + else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH-1] === 1'bx) begin + localparam A_WIDTH_new = A_WIDTH_trimmed(A_WIDTH-1); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B), .Y(Y)); end else if (A_WIDTH < `MIN_MUX_INPUTS) begin wire _TECHMAP_FAIL_ = 1; From ea0f7c9be9283e927591d1a33c2db663d3bbd82c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:12:41 -0700 Subject: [PATCH 777/927] Restore $__XILINX_MUXF78 const optimisation --- techlibs/xilinx/cells_map.v | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index c6e734974..b13f8d1ee 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -279,32 +279,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; -// parameter _TECHMAP_BITS_CONNMAP_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; -// parameter _TECHMAP_CONSTMSK_S0_ = 0; -// parameter _TECHMAP_CONSTVAL_S0_ = 0; -// parameter _TECHMAP_CONSTMSK_S1_ = 0; -// parameter _TECHMAP_CONSTVAL_S1_ = 0; -// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) -// assign T0 = I1; -// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) -// assign T0 = I0; -// else + parameter _TECHMAP_BITS_CONNMAP_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; + else MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); -// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) -// assign T1 = I3; -// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) -// assign T1 = I2; -// else + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; + else MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); -// if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) -// assign O = T1; -// else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) -// assign O = T0; -// else + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From 728839d6caca41ebbd9ae052668057f978a418e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:53:38 -0700 Subject: [PATCH 778/927] Remove peepopt call in synth_xilinx since already in synth -run coarse --- techlibs/xilinx/synth_xilinx.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c24f66e52..b7c32d2e0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -239,11 +239,6 @@ struct SynthXilinxPass : public ScriptPass // so attempt to convert $pmux-es to the former 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 - // and that aids wide mux analysis - run("peepopt"); } if (check_label("bram", "(skip if '-nobram')")) { From b3f162e94e61f739b84d8c6b31f203119805b2fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:28:29 -0700 Subject: [PATCH 779/927] Replace log_assert() with meaningful log_error() --- frontends/aiger/aigerparse.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7008d0542..1ac0f7ba4 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -376,7 +376,11 @@ void AigerReader::parse_xaiger() continue; if (m->name.begins_with("$paramod")) continue; - auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name)); + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); log_assert(r.second); } From 2c6aaef3db87fe7955eded675fac452705e5cd48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 13:32:09 -0700 Subject: [PATCH 780/927] Add test --- tests/various/script.ys | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/various/script.ys diff --git a/tests/various/script.ys b/tests/various/script.ys new file mode 100644 index 000000000..6044ad9b3 --- /dev/null +++ b/tests/various/script.ys @@ -0,0 +1,17 @@ +read_verilog -formal < Date: Fri, 28 Jun 2019 13:36:33 -0700 Subject: [PATCH 781/927] Support ability for "script -select" to take commands from wires --- kernel/yosys.cc | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 94d6d675f..7d4948881 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1254,24 +1254,55 @@ struct HistoryPass : public Pass { #endif struct ScriptCmdPass : public Pass { - ScriptCmdPass() : Pass("script", "execute commands from script file") { } + ScriptCmdPass() : Pass("script", "execute commands from file or wire") { } void help() YS_OVERRIDE { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" script [:]\n"); + log(" script -select [selection]\n"); log("\n"); - log("This command executes the yosys commands in the specified file.\n"); + log("This command executes the yosys commands in the specified file (default\n"); + log("behaviour), or commands embedded in the constant text value connected to the\n"); + log("selected wires.\n"); log("\n"); - log("The 2nd argument can be used to only execute the section of the\n"); - log("file between the specified labels. An empty from label is synonymous\n"); - log("for the beginning of the file and an empty to label is synonymous\n"); - log("for the end of the file.\n"); + log("In the default (file) case, the 2nd argument can be used to only execute the\n"); + log("section of the file between the specified labels. An empty from label is\n"); + log("synonymous with the beginning of the file and an empty to label is synonymous\n"); + log("with the end of the file.\n"); log("\n"); log("If only one label is specified (without ':') then only the block\n"); log("marked with that label (until the next label) is executed.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - if (args.size() < 2) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + bool select_mode = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-select") { + select_mode = true; + continue; + } + break; + } + if (select_mode) { + extra_args(args, argidx, design); + + for (auto mod : design->selected_modules()) + for (auto &c : mod->connections()) { + if (!c.first.is_wire()) + continue; + auto w = c.first.as_wire(); + if (!mod->selected(w)) + continue; + if (!c.second.is_fully_const()) + log_error("RHS of selected wire %s.%s is not constant.\n", log_id(mod), log_id(w)); + auto v = c.second.as_const(); + Pass::call(design, v.decode_string()); + } + } + else if (args.size() < 2) log_cmd_error("Missing script file.\n"); else if (args.size() == 2) run_frontend(args[1], "script", design); From 4e1a4927e29d1b571b88d9be80a0ff2e0716d5fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 13:39:06 -0700 Subject: [PATCH 782/927] Add to CHANGELOG --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 15dd5d002..af9642d66 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,12 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.9 .. Yosys 0.9-dev +-------------------------- + + * Various + - Added "script -select" + Yosys 0.8 .. Yosys 0.8-dev -------------------------- From 64f6b0c747eb915be9205b36bd69745a2385aea1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 13:41:32 -0700 Subject: [PATCH 783/927] Try command in another module --- tests/various/script.ys | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/various/script.ys b/tests/various/script.ys index 6044ad9b3..9ccc727eb 100644 --- a/tests/various/script.ys +++ b/tests/various/script.ys @@ -6,6 +6,9 @@ read_verilog -formal < Date: Fri, 28 Jun 2019 14:18:56 -0700 Subject: [PATCH 784/927] autotest.sh to define _AUTOTB when test_autotb --- 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 7b64b357f..4d3478628 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -157,7 +157,7 @@ do fi if [ ! -f ../${bn}_tb.v ]; then - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} + "$toolsdir"/../../yosys -f "$frontend $include_opts -D_AUTOTB" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} else cp ../${bn}_tb.v ${bn}_tb.v fi From 0ec7c09756a84d123745a381881b9e9803da210d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 14:18:56 -0700 Subject: [PATCH 785/927] autotest.sh to define _AUTOTB when test_autotb --- 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 7b64b357f..4d3478628 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -157,7 +157,7 @@ do fi if [ ! -f ../${bn}_tb.v ]; then - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} + "$toolsdir"/../../yosys -f "$frontend $include_opts -D_AUTOTB" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext} else cp ../${bn}_tb.v ${bn}_tb.v fi From dd8d264bf5b4a3d8230caf5ec7160f971131b33c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 29 Jun 2019 19:37:04 -0700 Subject: [PATCH 786/927] install *_nowide.lut files --- techlibs/ecp5/Makefile.inc | 1 + techlibs/xilinx/Makefile.inc | 2 ++ 2 files changed, 3 insertions(+) diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index eee3b418f..ff39ba4fe 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -13,6 +13,7 @@ $(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)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g_nowide.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/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 1a652eb27..e9ea10e48 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,8 +30,10 @@ $(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_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7_nowide.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)) From 85f1c2dcbe1ebd3fa609f2a9a558810dfcc8484c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 29 Jun 2019 21:42:20 -0700 Subject: [PATCH 787/927] Cleanup SRL inference/make more consistent --- techlibs/xilinx/cells_map.v | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 9a316fc96..89671c0fc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -56,7 +56,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o localparam [DEPTH-1:0] INIT_R = brev(INIT); parameter _TECHMAP_CONSTMSK_L_ = 0; - parameter _TECHMAP_CONSTVAL_L_ = 0; wire CE; generate @@ -129,26 +128,33 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); end end - else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin - // Handle cases where fixed-length depth is - // just 1 over a convenient value - \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + // For fixed length, if just 1 over a convenient value, decompose + else if (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_) begin + wire T; + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(D), .L({32{1'b1}}), .E(E), .Q(T)); + \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(T), .L(L), .E(E), .Q(Q)); end + // For variable length, if just 1 over a convenient value, then bump up one more + else if (DEPTH < 129 && ~&_TECHMAP_CONSTMSK_L_) + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); else begin - localparam lower_clog2 = $clog2((DEPTH+1)/2); - localparam lower_depth = 2 ** lower_clog2; - wire T0, T1, T2, T3; - if (&_TECHMAP_CONSTMSK_L_) begin - \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0)); - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3)); - end - else begin - \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); - assign Q = L[lower_clog2] ? T2 : T0; - end - if (DEPTH == 2 * lower_depth) - assign SO = T3; + localparam depth0 = 128; + localparam num_srl128 = DEPTH / depth0; + localparam depthN = DEPTH % depth0; + wire [num_srl128 + (depthN > 0 ? 1 : 0) - 1:0] T; + wire [num_srl128 + (depthN > 0 ? 1 : 0) :0] S; + assign S[0] = D; + genvar i; + for (i = 0; i < num_srl128; i++) + \$__XILINX_SHREG_ #(.DEPTH(depth0), .INIT(INIT[DEPTH-1-i*depth0-:depth0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(S[i]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[i]), .SO(S[i+1])); + + if (depthN > 0) + \$__XILINX_SHREG_ #(.DEPTH(depthN), .INIT(INIT[depthN-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(S[num_srl128]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[num_srl128])); + + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T[num_srl128 + (depthN > 0 ? 1 : 0) - 1]; + else + assign Q = T[L[DEPTH-1:$clog2(depth0)]]; end endgenerate endmodule From 04459cb30aff2341d6de43f7eefe5acaa4bb1db1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 30 Jun 2019 11:48:01 -0700 Subject: [PATCH 788/927] Comment out invalid syntax --- tests/various/specify.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/various/specify.v b/tests/various/specify.v index b1f399267..985879f85 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -33,9 +33,9 @@ module issue01144(input clk, d, output q); specify // Fails: (posedge clk => (q +: d)) = (3,1); - (/*posedge*/ clk => (q +: d)) = (3,1); + //(/*posedge*/ clk => (q +: d)) = (3,1); // Invalid syntax (posedge clk *> (q +: d)) = (3,1); - (/*posedge*/ clk *> (q +: d)) = (3,1); + //(/*posedge*/ clk *> (q +: d)) = (3,1); // Invalid syntax // Works: (/*posedge*/ clk => q) = (3,1); From 0067dc44f3928833eede2b9bb40260be78e11a93 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 09:44:53 -0700 Subject: [PATCH 789/927] Move abc9 from yosys-0.8 to yosys-0.9 in CHANGELOG --- CHANGELOG | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 15dd5d002..5535ce418 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,17 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.9 .. Yosys 0.9-dev +-------------------------- + + * Various + - 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) + - Added "synth -abc9" (experimental) + + Yosys 0.8 .. Yosys 0.8-dev -------------------------- @@ -26,11 +37,6 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_xilinx -nocarry" - Added "synth_xilinx -nowidelut" - Added "synth_ecp5 -nowidelut" - - 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) - - Added "synth -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 62fb3d5d15cedf84f6b977bf107cce56d36913af Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 09:45:51 -0700 Subject: [PATCH 790/927] Move wide mux from yosys-0.8 to 0.9 --- CHANGELOG | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7ac418160..29dc05ac0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,13 +2,6 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.9 .. Yosys 0.9-dev --------------------------- - - * Various - - Added "script -select" - - Yosys 0.9 .. Yosys 0.9-dev -------------------------- @@ -18,6 +11,8 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) + - Added "script -select" + - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) Yosys 0.8 .. Yosys 0.8-dev @@ -44,7 +39,6 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_xilinx -nowidelut" - Added "synth_ecp5 -nowidelut" - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 9018f29d54cb33328546580e0c7f9ee12e8a4ae3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 09:46:56 -0700 Subject: [PATCH 791/927] Move CHANGELOG entry from yosys-0.8 to 0.9 --- CHANGELOG | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b54897d89..818225e56 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,13 +2,6 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.9 .. Yosys 0.9-dev --------------------------- - - * Various - - Added "script -select" - - Yosys 0.9 .. Yosys 0.9-dev -------------------------- @@ -18,6 +11,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) + - Added "script -select" Yosys 0.8 .. Yosys 0.8-dev From 603fe9cda9ea6c18374ae4c5545d55b97cfa4c81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:58:41 -0700 Subject: [PATCH 792/927] Space --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 29dc05ac0..ae11b8f3c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ List of major changes and improvements between releases ======================================================= + Yosys 0.9 .. Yosys 0.9-dev -------------------------- From 6282a67332e9ca0ffe68b7ae57e93b6248946d4a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:59:10 -0700 Subject: [PATCH 793/927] Space --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 818225e56..4348b3d7a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ List of major changes and improvements between releases ======================================================= + Yosys 0.9 .. Yosys 0.9-dev -------------------------- From a9a140aa6c84e71edc1a244cfe363400c7e09d90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 13:36:27 -0700 Subject: [PATCH 794/927] Fix broken MUXFx box, use MUXF7x2 box instead --- techlibs/xilinx/abc_xc7.box | 9 +++--- techlibs/xilinx/cells_map.v | 58 ++++++++++++++++++------------------- techlibs/xilinx/cells_sim.v | 6 ++-- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 273d36573..0f24d6d66 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -14,10 +14,11 @@ F7MUX 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -# Inputs: I0 I1 I2 I3 S0 S1 -# Outputs: O -$__MUXF78 3 1 6 1 -190 193 217 223 296 273 +# Inputs: I0 I1 I2 I3 S +# Outputs: O0 O1 +$__MUXF7x2 3 1 5 2 +190 193 - - 276 +- - 217 223 296 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 27e860801..af4427dcf 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -95,7 +95,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T4; else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux7 (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S(L[5]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); end else if (DEPTH > 97 && DEPTH < 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; @@ -106,7 +108,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; @@ -116,8 +120,11 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o 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; - else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + else begin + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(T7), .O1(T8)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + end end else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin // Handle cases where fixed-length depth is @@ -216,7 +223,9 @@ module \$__XILINX_SHIFTX (A, B, Y); \$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_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T[0]), .I1(T[2]), .I2(T[4]), .I3(T[6]), .S(B[2]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(B[3]), .O(Q)); end else begin localparam a_width0 = 2 ** 4; @@ -265,36 +274,27 @@ endmodule `endif `ifndef _ABC -module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); - output O; - input I0, I1, I2, I3, S0, S1; - wire T0, T1; +module \$__XILINX_MUXF7x2 (O0, O1, I0, I1, I2, I3, S); + output O0, O1; + input I0, I1, I2, I3, S; parameter _TECHMAP_BITS_CONNMAP_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S0_ = 0; - parameter _TECHMAP_CONSTVAL_S0_ = 0; - parameter _TECHMAP_CONSTMSK_S1_ = 0; - parameter _TECHMAP_CONSTVAL_S1_ = 0; - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T0 = I1; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign T0 = I0; + parameter _TECHMAP_CONSTMSK_S_ = 0; + parameter _TECHMAP_CONSTVAL_S_ = 0; + if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) + assign O0 = I1; + else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign O0 = I0; else - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T1 = I3; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign T1 = I2; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S), .O(O0)); + if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) + assign O1 = I3; + else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign O1 = I2; else - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) - assign O = T1; - else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) - assign O = T0; - else - MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S), .O(O1)); endmodule `endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3937d3536..d1877cf1a 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -171,9 +171,9 @@ endmodule `ifdef _ABC (* abc_box_id = 3, lib_whitebox *) -module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); - assign O = S1 ? (S0 ? I3 : I2) - : (S0 ? I1 : I0); +module \$__XILINX_MUXF7x2 (output O0, O1, input I0, I1, I2, I3, S); + assign O0 = S ? I1 : I0; + assign O1 = S ? I3 : I2; endmodule `endif From 09ac27471667d1316b09984624dde981e860a94e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 14:01:09 -0700 Subject: [PATCH 795/927] Revert "Fix broken MUXFx box, use MUXF7x2 box instead" This reverts commit a9a140aa6c84e71edc1a244cfe363400c7e09d90. --- techlibs/xilinx/abc_xc7.box | 9 +++--- techlibs/xilinx/cells_map.v | 58 ++++++++++++++++++------------------- techlibs/xilinx/cells_sim.v | 6 ++-- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 0f24d6d66..273d36573 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -14,11 +14,10 @@ F7MUX 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -# Inputs: I0 I1 I2 I3 S -# Outputs: O0 O1 -$__MUXF7x2 3 1 5 2 -190 193 - - 276 -- - 217 223 296 +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +$__MUXF78 3 1 6 1 +190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index af4427dcf..27e860801 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -95,9 +95,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T4; else - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux7 (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S(L[5]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH > 97 && DEPTH < 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; @@ -108,9 +106,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; else - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; @@ -120,11 +116,8 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o 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; - else begin - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(T7), .O1(T8)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); - end + else + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin // Handle cases where fixed-length depth is @@ -223,9 +216,7 @@ module \$__XILINX_SHIFTX (A, B, Y); \$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_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T[0]), .I1(T[2]), .I2(T[4]), .I3(T[6]), .S(B[2]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(B[3]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; @@ -274,27 +265,36 @@ endmodule `endif `ifndef _ABC -module \$__XILINX_MUXF7x2 (O0, O1, I0, I1, I2, I3, S); - output O0, O1; - input I0, I1, I2, I3, S; +module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); + output O; + input I0, I1, I2, I3, S0, S1; + wire T0, T1; parameter _TECHMAP_BITS_CONNMAP_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S_ = 0; - parameter _TECHMAP_CONSTVAL_S_ = 0; - if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) - assign O0 = I1; - else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign O0 = I0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; else - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S), .O(O0)); - if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) - assign O1 = I3; - else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign O1 = I2; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; else - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S), .O(O1)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index d1877cf1a..3937d3536 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -171,9 +171,9 @@ endmodule `ifdef _ABC (* abc_box_id = 3, lib_whitebox *) -module \$__XILINX_MUXF7x2 (output O0, O1, input I0, I1, I2, I3, S); - assign O0 = S ? I1 : I0; - assign O1 = S ? I3 : I2; +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); + assign O = S1 ? (S0 ? I3 : I2) + : (S0 ? I1 : I0); endmodule `endif From 2ea6083b7ecea979838c2be40f5f7ef907f553d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 14:04:06 -0700 Subject: [PATCH 796/927] Fix $__XILINX_MUXF78 box timing --- techlibs/xilinx/abc_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 273d36573..3789ff350 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -17,7 +17,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O $__MUXF78 3 1 6 1 -190 193 217 223 296 273 +294 297 311 317 390 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI From d206eca03b8aa7bb982fb2486c02c90a61354066 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 2 Jul 2019 11:36:26 +0200 Subject: [PATCH 797/927] Fix read_verilog assert/assume/etc on default case label, fixes YosysHQ/SymbiYosys#53 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index d3fd91473..951d9c66f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -193,6 +193,8 @@ YOSYS_NAMESPACE_END to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some global state.. its a mess) */ [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { + if (!strcmp(yytext, "default")) + return TOK_DEFAULT; frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); return TOK_SVA_LABEL; } From d45936fe5f2c6fd1e6f371b2fc3d6d820868ef72 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 2 Jul 2019 13:27:37 +0100 Subject: [PATCH 798/927] memory_dff: Fix checking of feedback mux input when more than one mux Signed-off-by: David Shah --- passes/memory/memory_dff.cc | 8 +++++--- tests/memories/read_two_mux.v | 16 ++++++++++++++++ tests/memories/run-test.sh | 4 ++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/memories/read_two_mux.v diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 5215cce44..32b97f27a 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -17,6 +17,7 @@ * */ +#include #include "kernel/yosys.h" #include "kernel/sigtools.h" @@ -183,12 +184,12 @@ struct MemoryDffWorker if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)) { RTLIL::SigSpec en; - RTLIL::SigSpec check_q; + std::vector check_q; do { bool enable_invert = mux_cells_a.count(sig_data) != 0; Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); - check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")); + check_q.push_back(sigmap(mux->getPort(enable_invert ? "\\B" : "\\A"))); sig_data = sigmap(mux->getPort("\\Y")); en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)); @@ -197,7 +198,8 @@ struct MemoryDffWorker if (sigbit_users_count[bit] > 1) goto skip_ff_after_read_merging; - if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q) + if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && + std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_data; })) { disconnect_dff(sig_data); cell->setPort("\\CLK", clk_data); diff --git a/tests/memories/read_two_mux.v b/tests/memories/read_two_mux.v new file mode 100644 index 000000000..4f2e7e1cd --- /dev/null +++ b/tests/memories/read_two_mux.v @@ -0,0 +1,16 @@ +// expect-wr-ports 1 +// expect-rd-ports 1 +// expect-no-rd-clk + +module top(input clk, input we, re, reset, input [7:0] addr, wdata, output reg [7:0] rdata); + +reg [7:0] bram[0:255]; +(* keep *) reg dummy; + +always @(posedge clk) begin + rdata <= re ? (reset ? 8'b0 : bram[addr]) : rdata; + if (we) + bram[addr] <= wdata; +end + +endmodule diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh index 76acaa9cd..8d1a8b413 100755 --- a/tests/memories/run-test.sh +++ b/tests/memories/run-test.sh @@ -31,6 +31,10 @@ for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp || { echo " ERROR: Unexpected read clock."; false; } fi + if grep -q expect-no-rd-clk $f; then + grep -q "connect \\\\RD_CLK 1'x\$" ${f%.v}.dmp || + { echo " ERROR: Expected no read clock."; false; } + fi echo " ok." done From 02ba85b13302f0d20f6b51cc7fdff2fb953421df Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 08:17:26 -0700 Subject: [PATCH 799/927] script -select -> script -scriptwire --- CHANGELOG | 2 +- kernel/yosys.cc | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4348b3d7a..ae7d28236 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,7 +12,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - - Added "script -select" + - Added "script -scriptwire Yosys 0.8 .. Yosys 0.8-dev diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 7d4948881..456ad48a0 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1259,7 +1259,7 @@ struct ScriptCmdPass : public Pass { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" script [:]\n"); - log(" script -select [selection]\n"); + log(" script -scriptwire [selection]\n"); log("\n"); log("This command executes the yosys commands in the specified file (default\n"); log("behaviour), or commands embedded in the constant text value connected to the\n"); @@ -1276,17 +1276,17 @@ struct ScriptCmdPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool select_mode = false; + bool scriptwire = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-select") { - select_mode = true; + if (args[argidx] == "-scriptwire") { + scriptwire = true; continue; } break; } - if (select_mode) { + if (scriptwire) { extra_args(args, argidx, design); for (auto mod : design->selected_modules()) From 90382a0f6d1ad7dfd14ced95051e5e76de89491c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 08:19:23 -0700 Subject: [PATCH 800/927] Update test too --- tests/various/script.ys | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/various/script.ys b/tests/various/script.ys index 9ccc727eb..4152145e8 100644 --- a/tests/various/script.ys +++ b/tests/various/script.ys @@ -13,8 +13,8 @@ read_verilog -formal < Date: Tue, 2 Jul 2019 08:20:37 -0700 Subject: [PATCH 801/927] Use Pass::call_on_module() as per @cliffordwolf comments --- kernel/yosys.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 456ad48a0..f95c0127b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1299,7 +1299,7 @@ struct ScriptCmdPass : public Pass { if (!c.second.is_fully_const()) log_error("RHS of selected wire %s.%s is not constant.\n", log_id(mod), log_id(w)); auto v = c.second.as_const(); - Pass::call(design, v.decode_string()); + Pass::call_on_module(design, mod, v.decode_string()); } } else if (args.size() < 2) From 81a717e9b767792f64535757f905a5061c627fbd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 08:22:31 -0700 Subject: [PATCH 802/927] Update test for Pass::call_on_module() --- tests/various/script.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/various/script.ys b/tests/various/script.ys index 4152145e8..66b7b5caa 100644 --- a/tests/various/script.ys +++ b/tests/various/script.ys @@ -9,7 +9,7 @@ read_verilog -formal < Date: Tue, 2 Jul 2019 17:10:13 +0000 Subject: [PATCH 803/927] manual: explain the purpose of `sync always`. --- manual/CHAPTER_Overview.tex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 1a25c477f..3009bf2c0 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -331,8 +331,9 @@ to update {\tt \textbackslash{}q}. An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and exactly one RTLIL::CaseRule object, which is called the {\it root case}. -An RTLIL::SyncRule object contains an (optional) synchronization condition -(signal and edge-type) and zero or more assignments (RTLIL::SigSig). +An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and zero or +more assignments (RTLIL::SigSig). The {\tt always} synchronization condition is used to break combinatorial +loops when a latch should be inferred instead. An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig) and zero or more RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a From 9c556e3c02a8b25fbcd764e019e3870d021684ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:13:40 -0700 Subject: [PATCH 804/927] Add test --- tests/various/abc9.v | 4 ++++ tests/various/abc9.ys | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/various/abc9.v b/tests/various/abc9.v index 8271cd249..a08b613a8 100644 --- a/tests/various/abc9.v +++ b/tests/various/abc9.v @@ -3,3 +3,7 @@ initial o = 1'b0; always @* o <= ~o; endmodule + +module abc9_test028(input i, output o); +unknown u(~i, o); +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 922f7005d..a84b637d9 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -1,4 +1,6 @@ read_verilog abc9.v +design -save read +hierarchy -top abc9_test027 proc design -save gold @@ -12,3 +14,11 @@ 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 abc9_test028 +proc + +abc9 -lut 4 +select -assert-count 1 t:$lut r:LUT=1 r:WIDTH=1 %i %i +select -assert-count 1 t:unknown +select -assert-none t:$lut t:unknown %% t: %D From 10524064e94b9fe21483092e2733b1b71ae60b4e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:14:30 -0700 Subject: [PATCH 805/927] write_xaiger to treat unknown cell connections as keep-s --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index eb3d47569..869b741a6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -138,6 +138,7 @@ struct XAigerWriter { pool undriven_bits; pool unused_bits; + pool keep_bits; // promote public wires for (auto wire : module->wires()) @@ -168,6 +169,9 @@ struct XAigerWriter unused_bits.insert(bit); } + if (keep) + keep_bits.insert(bit); + if (wire->port_input || keep) { if (bit != wirebit) alias_map[bit] = wirebit; @@ -235,7 +239,7 @@ struct XAigerWriter log_assert(!holes_mode); RTLIL::Module* inst_module = module->design->module(cell->type); - 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) { @@ -255,10 +259,11 @@ struct XAigerWriter } } else { + bool cell_known = cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); + auto is_input = !cell_known || cell->input(c.first); + auto is_output = !cell_known || cell->output(c.first); 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)); @@ -266,12 +271,15 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (!w->port_output) { + if (!w->port_output || !cell_known) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; output_bits.insert(b); unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); } } } @@ -424,7 +432,7 @@ struct XAigerWriter auto jt = input_bits.find(b); if (jt != input_bits.end()) { - log_assert(b.wire->attributes.count("\\keep")); + log_assert(keep_bits.count(O)); input_bits.erase(b); } } @@ -444,7 +452,7 @@ struct XAigerWriter // 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")) { + || keep_bits.count(bit)) { RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) From ba365679082cff2b9879eef5349bfdf2b5291449 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 3 Jul 2019 11:22:10 +0200 Subject: [PATCH 806/927] Some cleanups in "ignore specify parser" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 84 ++---------------------------- tests/various/specify.v | 2 +- 2 files changed, 6 insertions(+), 80 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index dab5b5919..0fec445fa 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1021,13 +1021,8 @@ list_of_specparam_assignments: specparam_assignment: ignspec_id '=' constant_mintypmax_expression ; -/* -pulsestyle_declaration : - ; - -showcancelled_declaration : - ; -*/ +ignspec_opt_cond: + TOK_IF '(' ignspec_expr ')' | /* empty */; path_declaration : simple_path_declaration ';' @@ -1036,8 +1031,8 @@ path_declaration : ; simple_path_declaration : - parallel_path_description '=' path_delay_value | - full_path_description '=' path_delay_value + ignspec_opt_cond parallel_path_description '=' path_delay_value | + ignspec_opt_cond full_path_description '=' path_delay_value ; path_delay_value : @@ -1047,26 +1042,7 @@ path_delay_value : ; list_of_path_delay_extra_expressions : -/* - t_path_delay_expression - | trise_path_delay_expression ',' tfall_path_delay_expression - | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression - | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' - tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression - | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' - tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ',' - t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ',' - tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression -*/ - ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression - ; + ',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions; specify_edge_identifier : TOK_POSEDGE | TOK_NEGEDGE ; @@ -1119,56 +1095,6 @@ system_timing_args : system_timing_arg | system_timing_args ',' system_timing_arg ; -/* -t_path_delay_expression : - path_delay_expression; - -trise_path_delay_expression : - path_delay_expression; - -tfall_path_delay_expression : - path_delay_expression; - -tz_path_delay_expression : - path_delay_expression; - -t01_path_delay_expression : - path_delay_expression; - -t10_path_delay_expression : - path_delay_expression; - -t0z_path_delay_expression : - path_delay_expression; - -tz1_path_delay_expression : - path_delay_expression; - -t1z_path_delay_expression : - path_delay_expression; - -tz0_path_delay_expression : - path_delay_expression; - -t0x_path_delay_expression : - path_delay_expression; - -tx1_path_delay_expression : - path_delay_expression; - -t1x_path_delay_expression : - path_delay_expression; - -tx0_path_delay_expression : - path_delay_expression; - -txz_path_delay_expression : - path_delay_expression; - -tzx_path_delay_expression : - path_delay_expression; -*/ - path_delay_expression : ignspec_constant_expression; diff --git a/tests/various/specify.v b/tests/various/specify.v index 985879f85..73a59eb7a 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -7,7 +7,7 @@ module test ( if (EN) Q <= D; specify - if (EN) (CLK *> (Q : D)) = (1, 2:3:4); + if (EN) (posedge CLK *> (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); endspecify From 1f173210ebbf2cd5b5714e351ed40b6141d90b14 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 3 Jul 2019 11:25:05 +0200 Subject: [PATCH 807/927] Fix tests/various/specify.v Signed-off-by: Clifford Wolf --- tests/various/specify.v | 9 ++------- tests/various/specify.ys | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/various/specify.v b/tests/various/specify.v index 73a59eb7a..5d44d78f7 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -7,9 +7,11 @@ module test ( if (EN) Q <= D; specify +`ifndef SKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS if (EN) (posedge CLK *> (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); +`endif endspecify endmodule @@ -31,14 +33,7 @@ endmodule module issue01144(input clk, d, output q); specify - // Fails: (posedge clk => (q +: d)) = (3,1); - //(/*posedge*/ clk => (q +: d)) = (3,1); // Invalid syntax (posedge clk *> (q +: d)) = (3,1); - //(/*posedge*/ clk *> (q +: d)) = (3,1); // Invalid syntax - - // Works: - (/*posedge*/ clk => q) = (3,1); - (/*posedge*/ clk *> q) = (3,1); endspecify endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index a2b6038e4..00597e1e2 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -55,4 +55,4 @@ equiv_induct -seq 5 equiv_status -assert design -reset -read_verilog specify.v +read_verilog -DSKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS specify.v From 3a1a41bdb16c9cdf587147f8fb9dc910bcddfd26 Mon Sep 17 00:00:00 2001 From: Benedikt Tutzer Date: Thu, 4 Jul 2019 14:20:13 +0200 Subject: [PATCH 808/927] Throw runtime exception when trying to convert a c++-pointer to a python-object in case the pointer is a nullptr to avoid a segfault. Fixes #1090 --- misc/py_wrap_generator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 9e5727499..66d661fa1 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -779,6 +779,9 @@ class WClass: #if self.link_type != link_types.pointer: text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{" + text += "\n\t\t\tif(ref == nullptr){" + text += "\n\t\t\t\tthrow std::runtime_error(\"" + self.name + " does not exist.\");" + text += "\n\t\t\t}" text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));" if self.link_type == link_types.pointer: text += "\n\t\t\tret->ref_obj = ref;" From 4f798cda9d1b05d141e16a21b9e357de364021de Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Sun, 7 Jul 2019 16:00:38 +0100 Subject: [PATCH 809/927] synth_intel: Warn about untested Quartus backend --- techlibs/intel/synth_intel.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 639cba2c2..09c9ba3af 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -48,6 +48,8 @@ struct SynthIntelPass : public ScriptPass { log(" -vqm \n"); log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); log(" output file is omitted if this parameter is not specified.\n"); + log(" Note that this backend has not been tested and is likely incompatible\n"); + log(" with recent versions of Quartus.\n"); log("\n"); log(" -vpr \n"); log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n"); @@ -108,6 +110,7 @@ struct SynthIntelPass : public ScriptPass { } if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { vout_file = args[++argidx]; + log_warning("The Quartus backend has not been tested recently and is likely incompatible with modern versions of Quartus.\n"); continue; } if (args[argidx] == "-vpr" && argidx + 1 < args.size()) { From 93bc5affd3fc635dafec3a37bf4c5b94c252036f Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 11:34:58 +0000 Subject: [PATCH 810/927] Allow attributes on individual switch cases in RTLIL. The parser changes are slightly awkward. Consider the following IL: process $0 switch \foo case 1'1 assign \bar \baz ... case end end Before this commit, attributes are valid in , and iff it is immediately followed by a `switch`. (They are essentially attached to the switch.) But, after this commit, and because switch cases do not have an ending delimiter, becomes ambiguous: the attribute could attach to either the following `case`, or to the following `switch`. This isn't expressible in LALR(1) and results in a reduce/reduce conflict. To address this, attributes inside processes are now valid anywhere inside the process: in and a part of case body, and in as a separate rule. As a consequence, attributes can now precede `assign`s, which is made illegal in the same way it is illegal to attach attributes to `connect`. Attributes are tracked separately from the parser state, so this does not affect collection of attributes at all, other than allowing them on `case`s. The grammar change serves purely to allow attributes in more syntactic places. --- backends/ilang/ilang_backend.cc | 5 +++++ frontends/ilang/ilang_parser.y | 13 +++++++++---- kernel/rtlil.h | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index b4ba2b03f..313af7d5c 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -204,6 +204,11 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) { + f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str()); + dump_const(f, ait->second); + f << stringf("\n"); + } f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 44c99906a..b4b9693da 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -282,14 +282,14 @@ proc_stmt: } case_body sync_list TOK_END EOL; switch_stmt: - attr_list TOK_SWITCH sigspec EOL { + TOK_SWITCH sigspec EOL { RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; - rule->signal = *$3; + rule->signal = *$2; rule->attributes = attrbuf; switch_stack.back()->push_back(rule); attrbuf.clear(); - delete $3; - } switch_body TOK_END EOL; + delete $2; + } attr_list switch_body TOK_END EOL; attr_list: /* empty */ | @@ -298,9 +298,11 @@ attr_list: switch_body: switch_body TOK_CASE { RTLIL::CaseRule *rule = new RTLIL::CaseRule; + rule->attributes = attrbuf; switch_stack.back()->back()->cases.push_back(rule); switch_stack.push_back(&rule->switches); case_stack.push_back(rule); + attrbuf.clear(); } compare_list EOL case_body { switch_stack.pop_back(); case_stack.pop_back(); @@ -319,12 +321,15 @@ compare_list: /* empty */; case_body: + case_body attr_stmt | case_body switch_stmt | case_body assign_stmt | /* empty */; assign_stmt: TOK_ASSIGN sigspec sigspec EOL { + if (attrbuf.size() != 0) + rtlil_frontend_ilang_yyerror("dangling attribute"); case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3)); delete $2; delete $3; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f4fcf5dcf..82cbfaf28 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1327,7 +1327,7 @@ public: #endif }; -struct RTLIL::CaseRule +struct RTLIL::CaseRule : public RTLIL::AttrObject { std::vector compare; std::vector actions; From b1f400aeb8de657d5fa28c153df14246378df2b1 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 12:29:08 +0000 Subject: [PATCH 811/927] genrtlil: emit \src attribute on CaseRule. --- frontends/ast/genrtlil.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 079fc11e5..571ddd988 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -504,6 +504,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; current_case = new RTLIL::CaseRule; + current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum); last_generated_case = current_case; addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); for (auto node : child->children) { From 55c1f4027794a89971055b705254832b189a1c83 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 12:48:50 +0000 Subject: [PATCH 812/927] verilog_backend: dump attributes on CaseRule, as comments. Attributes are not permitted in that position by Verilog grammar. --- backends/verilog/verilog_backend.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 827af5d85..18c92521f 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -364,20 +364,22 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) } } -void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false) +void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false, bool as_comment = false) { if (noattr) return; + if (attr2comment) + as_comment = true; for (auto it = attributes.begin(); it != attributes.end(); ++it) { - f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str()); + f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); f << stringf(" = "); if (modattr && (it->second == Const(0, 1) || it->second == Const(0))) f << stringf(" 0 "); else if (modattr && (it->second == Const(1, 1) || it->second == Const(1))) f << stringf(" 1 "); else - dump_const(f, it->second, -1, 0, false, attr2comment); - f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); + dump_const(f, it->second, -1, 0, false, as_comment); + f << stringf(" %s%c", as_comment ? "*/" : "*)", term); } } @@ -1511,7 +1513,9 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":\n"); + f << stringf(":"); + dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); + f << stringf("\n"); dump_case_body(f, indent + " ", *it); } @@ -1662,7 +1666,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } } - dump_attributes(f, indent, module->attributes, '\n', true); + dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true); f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { From 48655dfb8b4dda7607ed7a790eb5f6bce5c27d38 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 13:18:18 +0000 Subject: [PATCH 813/927] proc_mux: consider \src attribute on CaseRule. --- passes/proc/proc_mux.cc | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index aac0b121c..d029282fd 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -144,7 +144,13 @@ struct SnippetSwCache } }; -RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw, bool ifxmode) +void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs) +{ + cell->attributes = sw->attributes; + cell->add_strpool_attribute("\\src", cs->get_strpool_attribute("\\src")); +} + +RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { std::stringstream sstr; sstr << "$procmux$" << (autoidx++); @@ -173,7 +179,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s { // create compare cell RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? "$eqx" : "$eq"); - eq_cell->attributes = sw->attributes; + apply_attrs(eq_cell, sw, cs); eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(0); @@ -199,7 +205,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s // reduce cmp vector to one logic signal RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", "$reduce_or"); - any_cell->attributes = sw->attributes; + apply_attrs(any_cell, sw, cs); any_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); any_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cmp_wire->width); @@ -212,7 +218,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return RTLIL::SigSpec(ctrl_wire); } -RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode) +RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { log_assert(when_signal.size() == else_signal.size()); @@ -224,7 +230,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return when_signal; // compare results - RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode); + RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode); if (ctrl_sig.size() == 0) return when_signal; log_assert(ctrl_sig.size() == 1); @@ -234,7 +240,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s // create the multiplexer itself RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), "$mux"); - mux_cell->attributes = sw->attributes; + apply_attrs(mux_cell, sw, cs); mux_cell->parameters["\\WIDTH"] = RTLIL::Const(when_signal.size()); mux_cell->setPort("\\A", else_signal); @@ -246,7 +252,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return RTLIL::SigSpec(result_wire); } -void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode) +void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { log_assert(last_mux_cell != NULL); log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size()); @@ -254,7 +260,7 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve if (when_signal == last_mux_cell->getPort("\\A")) return; - RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode); + RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode); log_assert(ctrl_sig.size() == 1); last_mux_cell->type = "$pmux"; @@ -395,9 +401,9 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d RTLIL::CaseRule *cs2 = sw->cases[case_idx]; RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val, ifxmode); if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1]) - append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode); + append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, cs2, ifxmode); else - result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode); + result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, cs2, ifxmode); } } From 628437b01cd37b95c020b2f4c4e2f2d8f0e9bf8b Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 15:11:29 +0000 Subject: [PATCH 814/927] verilog_backend: dump attributes on SwitchRule. This appears to be an omission. --- backends/verilog/verilog_backend.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 18c92521f..6288502a5 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1494,6 +1494,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw return; } + dump_attributes(f, indent, sw->attributes); f << stringf("%s" "casez (", indent.c_str()); dump_sigspec(f, sw->signal); f << stringf(")\n"); From c58998a7d2c1066ea28cabe9bc6e1e52bb6668f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 10:48:10 -0700 Subject: [PATCH 815/927] atoi -> stoi as per @daveshah1 --- 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 0a30848aa..c18c3918f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -194,7 +194,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-widemux" && argidx+1 < args.size()) { - widemux = atoi(args[++argidx].c_str()); + widemux = std::stoi(args[++argidx]); continue; } if (args[argidx] == "-abc9") { From a34c5612e702d481798fa7fc27cf2fef06a2b544 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 10:59:12 -0700 Subject: [PATCH 816/927] Add muxcover -mux2=cost option --- passes/techmap/muxcover.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index c84cfc39a..4d9c111e7 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -631,7 +631,7 @@ struct MuxcoverPass : public Pass { log("\n"); log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); log("\n"); - log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); + log(" -mux2=cost, -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); @@ -661,6 +661,7 @@ struct MuxcoverPass : public Pass { bool nodecode = false; bool nopartial = false; int cost_dmux = COST_DMUX; + int cost_mux2 = COST_MUX2; int cost_mux4 = COST_MUX4; int cost_mux8 = COST_MUX8; int cost_mux16 = COST_MUX16; @@ -669,6 +670,10 @@ struct MuxcoverPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { const auto &arg = args[argidx]; + if (arg.size() >= 6 && arg.substr(0,6) == "-mux2=") { + cost_mux2 = atoi(arg.substr(6).c_str()); + continue; + } if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") { use_mux4 = true; if (arg.size() > 5) { @@ -722,6 +727,7 @@ struct MuxcoverPass : public Pass { worker.use_mux8 = use_mux8; worker.use_mux16 = use_mux16; worker.cost_dmux = cost_dmux; + worker.cost_mux2 = cost_mux2; worker.cost_mux4 = cost_mux4; worker.cost_mux8 = cost_mux8; worker.cost_mux16 = cost_mux16; From 3681162c8d6826cf5ccf5de485ba14b4200a5221 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:00:06 -0700 Subject: [PATCH 817/927] atoi -> stoi --- passes/techmap/muxcover.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 4d9c111e7..fa97239f5 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -671,14 +671,14 @@ struct MuxcoverPass : public Pass { { const auto &arg = args[argidx]; if (arg.size() >= 6 && arg.substr(0,6) == "-mux2=") { - cost_mux2 = atoi(arg.substr(6).c_str()); + cost_mux2 = std::stoi(arg.substr(6)); continue; } 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(6).c_str()); + cost_mux4 = std::stoi(arg.substr(6)); } continue; } @@ -686,7 +686,7 @@ struct MuxcoverPass : public Pass { use_mux8 = true; if (arg.size() > 5) { if (arg[5] != '=') break; - cost_mux8 = atoi(arg.substr(6).c_str()); + cost_mux8 = std::stoi(arg.substr(6)); } continue; } @@ -694,12 +694,12 @@ struct MuxcoverPass : public Pass { use_mux16 = true; if (arg.size() > 6) { if (arg[6] != '=') break; - cost_mux16 = atoi(arg.substr(7).c_str()); + cost_mux16 = std::stoi(arg.substr(7)); } continue; } if (arg.size() >= 6 && arg.substr(0,6) == "-dmux=") { - cost_dmux = atoi(arg.substr(6).c_str()); + cost_dmux = std::stoi(arg.substr(6)); continue; } if (arg == "-nodecode") { From dbe1326573e878f4f9d4fc80ce1afcd0f7d84ec6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:08:20 -0700 Subject: [PATCH 818/927] Parametric muxcover costs as per @daveshah1 --- techlibs/xilinx/synth_xilinx.cc | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c18c3918f..f43923afb 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -280,23 +280,21 @@ struct SynthXilinxPass : public ScriptPass } else if (widemux > 0) { run("simplemap t:$mux"); - std::string muxcover_args = " -nodecode"; + constexpr int cost_mux2 = 100; + std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - case 5: muxcover_args += " -mux8=350 -mux16=400"; break; - case 6: muxcover_args += " -mux8=450 -mux16=500"; break; - case 7: muxcover_args += " -mux8=550 -mux16=600"; break; - case 8: muxcover_args += " -mux8=650 -mux16=700"; break; - case 9: muxcover_args += " -mux16=750"; break; - case 10: muxcover_args += " -mux16=850"; break; - case 11: muxcover_args += " -mux16=950"; break; - case 12: muxcover_args += " -mux16=1050"; break; - case 13: muxcover_args += " -mux16=1150"; break; - case 14: muxcover_args += " -mux16=1250"; break; - case 15: muxcover_args += " -mux16=1350"; break; - default: muxcover_args += " -mux16=1450"; break; + case 5: + case 6: + case 7: + case 8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break; } run("muxcover " + muxcover_args); } From 0944acf3affd8c6b161a2381b37eed3931c801a5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:29:21 -0700 Subject: [PATCH 819/927] synth_xilinx -widemux=2 is minimum now --- techlibs/xilinx/synth_xilinx.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f43923afb..4f597de4d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -79,7 +79,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); - log(" above this number of inputs (minimum value 5).\n"); + log(" above this number of inputs (minimum value 2).\n"); log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); @@ -208,8 +208,8 @@ struct SynthXilinxPass : public ScriptPass if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s") log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); - if (widemux != 0 && widemux < 5) - log_cmd_error("-widemux value must be 0 or >= 5.\n"); + if (widemux != 0 && widemux < 2) + log_cmd_error("-widemux value must be 0 or >= 2.\n"); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -252,7 +252,7 @@ struct SynthXilinxPass : public ScriptPass // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)"); + run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -283,6 +283,9 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { + case 2: + case 3: + case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: case 6: case 7: From 895ca501734d2f33b61f118a288832b55a366bd2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 12:03:38 -0700 Subject: [PATCH 820/927] Fixes for 2:1 muxes --- techlibs/xilinx/cells_map.v | 33 +++++++++++++++++++++++++++++---- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 27e860801..e12dd2833 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -193,6 +193,14 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH < `MIN_MUX_INPUTS) begin wire _TECHMAP_FAIL_ = 1; end + else if (A_WIDTH == 2) begin + MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); + end + else if (A_WIDTH <= 2 ** 2) begin + wire [4-1:0] T; + assign T = {{(4-A_WIDTH){1'bx}}, A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + end else if (A_WIDTH <= 2 ** 3) begin localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; @@ -251,15 +259,32 @@ module _90__XILINX_SHIFTX (A, B, Y); \$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)); endmodule +module \$_MUX_ (A, B, S, Y); + input A, B, S; + output Y; + generate + if (`MIN_MUX_INPUTS == 2) + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(2), .B_WIDTH(1), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({B,A}), .B(S), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + endgenerate +endmodule + +module \$_MUX4_ (A, B, C, D, S, T, Y); + input A, B, C, D, S, T; + output Y; + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({D,C,B,A}), .B({T,S}), .Y(Y)); +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; + 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; + 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 `endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4f597de4d..62bfaaaf1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -283,7 +283,7 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - case 2: + case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; case 3: case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: From b5072256f2c6b94423adb0ac1e2aec965230afe3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 12:50:59 -0700 Subject: [PATCH 821/927] Update muxcover doc as per @ZirconiumX --- passes/techmap/muxcover.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index fa97239f5..d53378a29 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -631,11 +631,16 @@ struct MuxcoverPass : public Pass { log("\n"); log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); log("\n"); - log(" -mux2=cost, -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(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); + log(" Cover $_MUX_ trees using the specified types of MUXes (with optional\n"); + log(" integer costs). If none of these options are given, the effect is the\n"); + log(" same as if all of them are.\n"); + log(" Default costs: $_MUX4_ = %d, $_MUX8_ = %d, \n", COST_MUX4, COST_MUX8); + log(" $_MUX16_ = %d\n", COST_MUX16); + log("\n"); + log(" -mux2=cost\n"); + log(" Use the specified cost for $_MUX_ cells when making covering decisions.\n"); + log(" Default cost: $_MUX_ = %d\n", COST_MUX2); log("\n"); log(" -dmux=cost\n"); log(" Use the specified cost for $_MUX_ cells used in decoders.\n"); From baf47e496f35cb90e5c7181079d38c04907c42da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:04:39 -0700 Subject: [PATCH 822/927] Add synth_xilinx -widemux recommended value --- 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 62bfaaaf1..7836f9f3e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -79,7 +79,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); - log(" above this number of inputs (minimum value 2).\n"); + log(" above this number of inputs (minimum value 2, recommended value >= 5).\n"); log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); From 78914e2e0e0a92e65cb1594c4858bc2225322ade Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:06:22 -0700 Subject: [PATCH 823/927] Capitalisation --- 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 7836f9f3e..b404dc8e7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -78,7 +78,7 @@ struct SynthXilinxPass : public ScriptPass log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n"); log("\n"); log(" -widemux \n"); - log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); + log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n"); log(" above this number of inputs (minimum value 2, recommended value >= 5).\n"); log(" default: 0 (no inference)\n"); log("\n"); From 3f86407cc32e20a8885c73f959082c5c0449bf9a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:06:35 -0700 Subject: [PATCH 824/927] Map $__XILINX_SHIFTX in a more balanced manner --- techlibs/xilinx/cells_map.v | 85 +++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e12dd2833..d48a3f15c 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -197,49 +197,62 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 2 ** 2) begin - wire [4-1:0] T; - assign T = {{(4-A_WIDTH){1'bx}}, A}; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end else if (A_WIDTH <= 2 ** 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[2]), .O(Y)); + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" state to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 + wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; + wire T0 = B[0] ? Ax[1] : Ax[0]; + wire T1 = B[0] ? Ax[3] : Ax[2]; + wire T2 = B[0] ? Ax[5] : Ax[4]; + wire T3 = B[0] ? Ax[7] : Ax[6]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); end else if (A_WIDTH <= 2 ** 4) begin - localparam a_width0 = 2 ** 2; - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; 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])); - else if (i == num_mux8 && 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_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" state to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 + wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; + wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] + : B[0] ? Ax[ 1] : Ax[ 0]; + wire T1 = B[1] ? B[0] ? Ax[ 7] : Ax[ 6] + : B[0] ? Ax[ 5] : Ax[ 4]; + wire T2 = B[1] ? B[0] ? Ax[11] : Ax[10] + : B[0] ? Ax[ 9] : Ax[ 8]; + wire T3 = B[1] ? B[0] ? Ax[15] : Ax[14] + : B[0] ? Ax[13] : Ax[12]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin - localparam a_width0 = 2 ** 4; - localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [num_mux16 + (a_widthN > 0 ? 1 : 0) - 1:0] T; + localparam num_mux16 = (A_WIDTH+15) / 16; + localparam clog2_num_mux16 = $clog2(num_mux16); + wire [num_mux16-1:0] T; + wire [num_mux16*16-1:0] Ax = {{(num_mux16*16-A_WIDTH){1'bx}}, A}; for (i = 0; i < num_mux16; 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])); - if (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-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); - else - assign T[num_mux16] = A[A_WIDTH-1]; - end - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(num_mux16 + (a_widthN > 0 ? 1 : 0)), .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(16), + .B_WIDTH(4), + .Y_WIDTH(Y_WIDTH) + ) fpga_mux ( + .A(Ax[i*16+:16]), + .B(B[3:0]), + .Y(T[i]) + ); + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(num_mux16), + .B_WIDTH(clog2_num_mux16), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(T), + .B(B[B_WIDTH-1-:clog2_num_mux16]), + .Y(Y)); end endgenerate endmodule From dd9771cbcdc14366c6acc501833c6050c39251de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:14:54 -0700 Subject: [PATCH 825/927] Add synth -keepdc option --- techlibs/common/synth.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 555de9fba..af70cc498 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -78,6 +78,9 @@ struct SynthPass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); + log(" -keepdc\n"); + log(" do not optimize explicit don't-care values on $mux cells.\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -85,7 +88,7 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, keepdc; int lut; void clear_flags() YS_OVERRIDE @@ -102,6 +105,7 @@ struct SynthPass : public ScriptPass noabc = false; noshare = false; abc = "abc"; + keepdc = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -167,6 +171,10 @@ struct SynthPass : public ScriptPass abc = "abc9"; continue; } + if (args[argidx] == "-keepdc") { + keepdc = true; + continue; + } break; } extra_args(args, argidx, design); @@ -211,7 +219,10 @@ struct SynthPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - run("wreduce"); + if (help_mode) + run("wreduce [-keepdc]"); + else + run("wreduce" + std::string(keepdc ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); if (help_mode) From 37b58f43242086de13fb2966d11b71efa29e7bfd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:15:07 -0700 Subject: [PATCH 826/927] Clarify 'wreduce -keepdc' doc --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..f749c8249 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values.\n"); + log(" Do not optimize explicit don't-care values on $mux cells.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE From fccabd09436aae780875fae2d833f58549f38418 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:15:37 -0700 Subject: [PATCH 827/927] Add synth -keepdc to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index ae7d28236..646d63a63 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) + - Added "synth -keepdc" - Added "script -scriptwire From 41d7d9d24b8ba7fd84dd72b27eb9aede10b8ef15 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:21:21 -0700 Subject: [PATCH 828/927] Clarify script -scriptwire doc --- kernel/yosys.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index f95c0127b..a42a7c0b8 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1273,6 +1273,10 @@ struct ScriptCmdPass : public Pass { log("If only one label is specified (without ':') then only the block\n"); log("marked with that label (until the next label) is executed.\n"); log("\n"); + log("In \"-scriptwire\" mode, the commands on the selected wire(s) will be executed\n"); + log("in the scope of (and thus, relative to) the wires' owning module(s). This\n"); + log("'-module' mode can be exited by using the 'cd' command.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From 7f964859ec99500e471853f5914b6e5b7c35a031 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:23:24 -0700 Subject: [PATCH 829/927] synth_xilinx to call "synth -run coarse" with "-keepdc" --- 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 b404dc8e7..15a37a439 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -240,9 +240,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { if (help_mode) - run("synth -run coarse [-flatten]", "(with '-flatten')"); + run("synth -keepdc -run coarse [-flatten]", "(with '-flatten')"); else - run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("synth -keepdc -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); From de404535538fe4d2548be82724515961e6e92519 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 22:56:19 -0700 Subject: [PATCH 830/927] Reword --- 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 d48a3f15c..63095880e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -202,7 +202,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 2 ** 3) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" state to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; wire T0 = B[0] ? Ax[1] : Ax[0]; @@ -213,7 +213,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 2 ** 4) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" state to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] From 939a225f921efc4276121fe957f545a98d252fa0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:02:57 -0700 Subject: [PATCH 831/927] Less thinking --- techlibs/xilinx/cells_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 63095880e..7c67c7a79 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -196,11 +196,11 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH == 2) begin MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end - else if (A_WIDTH <= 2 ** 2) begin + else if (A_WIDTH <= 4) begin wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end - else if (A_WIDTH <= 2 ** 3) begin + else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 @@ -211,7 +211,7 @@ module \$__XILINX_SHIFTX (A, B, Y); wire T3 = B[0] ? Ax[7] : Ax[6]; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); end - else if (A_WIDTH <= 2 ** 4) begin + else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 From d4ab43d9403899dcae74a24e71385fd959de98f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:05:48 -0700 Subject: [PATCH 832/927] Add one more 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 7c67c7a79..39427cc90 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -197,6 +197,9 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" status to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end From 45da3ada7babc8f2b23a8b23ce25430a98e2e58e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:49:16 -0700 Subject: [PATCH 833/927] Do not call opt -mux_undef (part of -full) before muxcover --- techlibs/xilinx/synth_xilinx.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 15a37a439..6eab74a21 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -270,7 +270,11 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + if (widemux > 0) + run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover + // performs less efficiently + else + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From 6951e3207063f66814e765d7d72e553b8b8eace1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:51:13 -0700 Subject: [PATCH 834/927] Decompose mux inputs in delay-orientated (rather than area) fashion --- techlibs/xilinx/cells_map.v | 48 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 39427cc90..35eea9858 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -200,34 +200,46 @@ module \$__XILINX_SHIFTX (A, B, Y); // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + wire [4-1:0] Ax; + if (A_WIDTH == 4) + assign Ax = A; + else + assign Ax = {A[1-:4-A_WIDTH], A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; - wire T0 = B[0] ? Ax[1] : Ax[0]; - wire T1 = B[0] ? Ax[3] : Ax[2]; - wire T2 = B[0] ? Ax[5] : Ax[4]; - wire T3 = B[0] ? Ax[7] : Ax[6]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); + wire [8-1:0] Ax; + if (A_WIDTH == 8) + assign Ax = A; + else + assign Ax = {A[3-:8-A_WIDTH], A}; + wire T0 = B[2] ? Ax[4] : Ax[0]; + wire T1 = B[2] ? Ax[5] : Ax[1]; + wire T2 = B[2] ? Ax[6] : Ax[2]; + wire T3 = B[2] ? Ax[7] : Ax[3]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; - wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] - : B[0] ? Ax[ 1] : Ax[ 0]; - wire T1 = B[1] ? B[0] ? Ax[ 7] : Ax[ 6] - : B[0] ? Ax[ 5] : Ax[ 4]; - wire T2 = B[1] ? B[0] ? Ax[11] : Ax[10] - : B[0] ? Ax[ 9] : Ax[ 8]; - wire T3 = B[1] ? B[0] ? Ax[15] : Ax[14] - : B[0] ? Ax[13] : Ax[12]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[2]), .S1(B[3]), .O(Y)); + wire [16-1:0] Ax; + if (A_WIDTH == 16) + assign Ax = A; + else + assign Ax = {A[7-:8-A_WIDTH], A}; + wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] + : B[3] ? Ax[ 8] : Ax[0]; + wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] + : B[3] ? Ax[ 9] : Ax[1]; + wire T2 = B[2] ? B[3] ? Ax[14] : Ax[6] + : B[3] ? Ax[10] : Ax[2]; + wire T3 = B[2] ? B[3] ? Ax[15] : Ax[7] + : B[3] ? Ax[11] : Ax[3]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else begin localparam num_mux16 = (A_WIDTH+15) / 16; From f7a14a56780fedfc38a104f46b801b84fa357d01 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 08:57:57 +0000 Subject: [PATCH 835/927] proc_clean: add -quiet option. This is useful for other passes that call it often, like bugpoint. --- passes/proc/proc_clean.cc | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 52141a8ec..97f4c6573 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -143,7 +143,7 @@ void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int m YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN -void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) +void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool quiet) { int count = 0; bool did_something = true; @@ -160,7 +160,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) did_something = false; proc_clean_case(&proc->root_case, did_something, count, -1); } - if (count > 0) + if (count > 0 && !quiet) log("Found and cleaned up %d empty switch%s in `%s.%s'.\n", count, count == 1 ? "" : "es", mod->name.c_str(), proc->name.c_str()); total_count += count; } @@ -171,7 +171,10 @@ struct ProcCleanPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" proc_clean [selection]\n"); + log(" proc_clean [options] [selection]\n"); + log("\n"); + log(" -quiet\n"); + log(" do not print any messages.\n"); log("\n"); log("This pass removes empty parts of processes and ultimately removes a process\n"); log("if it contains only empty structures.\n"); @@ -180,9 +183,20 @@ struct ProcCleanPass : public Pass { void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_count = 0; - log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n"); + bool quiet = false; - extra_args(args, 1, design); + if (find(args.begin(), args.end(), "-quiet") == args.end()) + log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-quiet") { + quiet = true; + continue; + } + } + extra_args(args, argidx, design); for (auto mod : design->modules()) { std::vector delme; @@ -191,10 +205,11 @@ struct ProcCleanPass : public Pass { for (auto &proc_it : mod->processes) { if (!design->selected(mod, proc_it.second)) continue; - proc_clean(mod, proc_it.second, total_count); + proc_clean(mod, proc_it.second, total_count, quiet); if (proc_it.second->syncs.size() == 0 && proc_it.second->root_case.switches.size() == 0 && proc_it.second->root_case.actions.size() == 0) { - log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); + if (!quiet) + log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); delme.push_back(proc_it.first); } } @@ -204,7 +219,8 @@ struct ProcCleanPass : public Pass { } } - log("Cleaned up %d empty switch%s.\n", total_count, total_count == 1 ? "" : "es"); + if (!quiet) + log("Cleaned up %d empty switch%s.\n", total_count, total_count == 1 ? "" : "es"); } } ProcCleanPass; From f2fb958d44bada70859ef2c4db9076e27da643e7 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 09:08:38 +0000 Subject: [PATCH 836/927] bugpoint: add -assigns and -updates options. --- passes/cmds/bugpoint.cc | 90 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 038ab7c7c..5a47988ec 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -51,14 +51,14 @@ struct BugpointPass : public Pass { log(" only consider crashes that place this string in the log file.\n"); log("\n"); log(" -fast\n"); - log(" run `clean -purge` after each minimization step. converges faster, but\n"); - log(" produces larger testcases, and may fail to produce any testcase at all if\n"); - log(" the crash is related to dangling wires.\n"); + log(" run `proc_clean; clean -purge` after each minimization step. converges\n"); + log(" faster, but produces larger testcases, and may fail to produce any\n"); + log(" testcase at all if the crash is related to dangling wires.\n"); log("\n"); log(" -clean\n"); - log(" run `clean -purge` before checking testcase and after finishing. produces\n"); - log(" smaller and more useful testcases, but may fail to produce any testcase\n"); - log(" at all if the crash is related to dangling wires.\n"); + log(" run `proc_clean; clean -purge` before checking testcase and after\n"); + log(" finishing. produces smaller and more useful testcases, but may fail to\n"); + log(" produce any testcase at all if the crash is related to dangling wires.\n"); log("\n"); log(" -modules\n"); log(" try to remove modules.\n"); @@ -72,6 +72,12 @@ struct BugpointPass : public Pass { log(" -connections\n"); log(" try to reconnect ports to 'x.\n"); log("\n"); + log(" -assigns\n"); + log(" try to remove process assigns from cases.\n"); + log("\n"); + log(" -updates\n"); + log(" try to remove process updates from syncs.\n"); + log("\n"); } bool run_yosys(RTLIL::Design *design, string yosys_cmd, string script) @@ -110,6 +116,7 @@ struct BugpointPass : public Pass { RTLIL::Design *design_copy = new RTLIL::Design; for (auto &it : design->modules_) design_copy->add(it.second->clone()); + Pass::call(design_copy, "proc_clean -quiet"); Pass::call(design_copy, "clean -purge"); if (do_delete) @@ -117,7 +124,7 @@ struct BugpointPass : public Pass { return design_copy; } - RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections) + RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates) { RTLIL::Design *design_copy = new RTLIL::Design; for (auto &it : design->modules_) @@ -225,6 +232,59 @@ struct BugpointPass : public Pass { } } } + if (assigns) + { + for (auto mod : design_copy->modules()) + { + if (mod->get_blackbox_attribute()) + continue; + + for (auto &pr : mod->processes) + { + vector cases = {&pr.second->root_case}; + while (!cases.empty()) + { + RTLIL::CaseRule *cs = cases[0]; + cases.erase(cases.begin()); + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) + { + if (index++ == seed) + { + log("Trying to remove assign %s %s in %s.%s.\n", log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); + cs->actions.erase(it); + return design_copy; + } + } + for (auto &sw : cs->switches) + cases.insert(cases.end(), sw->cases.begin(), sw->cases.end()); + } + } + } + } + if (updates) + { + for (auto mod : design_copy->modules()) + { + if (mod->get_blackbox_attribute()) + continue; + + for (auto &pr : mod->processes) + { + for (auto &sy : pr.second->syncs) + { + for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) + { + if (index++ == seed) + { + log("Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); + sy->actions.erase(it); + return design_copy; + } + } + } + } + } + } return NULL; } @@ -232,7 +292,7 @@ struct BugpointPass : public Pass { { string yosys_cmd = "yosys", script, grep; bool fast = false, clean = false; - bool modules = false, ports = false, cells = false, connections = false, has_part = false; + bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -277,6 +337,16 @@ struct BugpointPass : public Pass { has_part = true; continue; } + if (args[argidx] == "-assigns") { + assigns = true; + has_part = true; + continue; + } + if (args[argidx] == "-updates") { + updates = true; + has_part = true; + continue; + } break; } extra_args(args, argidx, design); @@ -290,6 +360,8 @@ struct BugpointPass : public Pass { ports = true; cells = true; connections = true; + assigns = true; + updates = true; } if (!design->full_selection()) @@ -305,7 +377,7 @@ struct BugpointPass : public Pass { bool found_something = false, stage2 = false; while (true) { - if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections)) + if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, assigns, updates)) { simplified = clean_design(simplified, fast, /*do_delete=*/true); From 5fe0ffe30f315d50b2405c2d436ad8e7ca9ba2f6 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 15:19:01 +0000 Subject: [PATCH 837/927] proc_prune: new pass. The proc_prune pass is similar in nature to proc_rmdead pass: while proc_rmdead removes branches that never become active because another branch preempts it, proc_prune removes assignments that never become active because another assignment preempts them. Genrtlil contains logic similar to the proc_prune pass, but their purpose is different: genrtlil has to prune assignments to adapt the semantics of blocking assignments in HDLs (latest assignment wins) to semantics of assignments in RTLIL processes (assignment in the most specific case wins). On the other hand proc_prune is a general purpose RTLIL simplification that benefits all frontends, even those not using the Yosys AST library. The proc_prune pass is added to the proc script after proc_rmdead, since it gives better results with fewer branches. --- passes/proc/Makefile.inc | 2 +- passes/proc/proc.cc | 2 + passes/proc/proc_prune.cc | 135 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 passes/proc/proc_prune.cc diff --git a/passes/proc/Makefile.inc b/passes/proc/Makefile.inc index 397fe46a1..4b56979f8 100644 --- a/passes/proc/Makefile.inc +++ b/passes/proc/Makefile.inc @@ -1,5 +1,6 @@ OBJS += passes/proc/proc.o +OBJS += passes/proc/proc_prune.o OBJS += passes/proc/proc_clean.o OBJS += passes/proc/proc_rmdead.o OBJS += passes/proc/proc_init.o @@ -7,4 +8,3 @@ OBJS += passes/proc/proc_arst.o OBJS += passes/proc/proc_mux.o OBJS += passes/proc/proc_dlatch.o OBJS += passes/proc/proc_dff.o - diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index ef7cb0f71..a5b4a3112 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -37,6 +37,7 @@ struct ProcPass : public Pass { log("\n"); log(" proc_clean\n"); log(" proc_rmdead\n"); + log(" proc_prune\n"); log(" proc_init\n"); log(" proc_arst\n"); log(" proc_mux\n"); @@ -83,6 +84,7 @@ struct ProcPass : public Pass { Pass::call(design, "proc_clean"); if (!ifxmode) Pass::call(design, "proc_rmdead"); + Pass::call(design, "proc_prune"); Pass::call(design, "proc_init"); if (global_arst.empty()) Pass::call(design, "proc_arst"); diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc new file mode 100644 index 000000000..7222d414d --- /dev/null +++ b/passes/proc/proc_prune.cc @@ -0,0 +1,135 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 whitequark + * + * 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/register.h" +#include "kernel/sigtools.h" +#include "kernel/log.h" +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct PruneWorker +{ + RTLIL::Module *module; + SigMap sigmap; + + int count = 0; + + PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {} + + pool do_switch(RTLIL::SwitchRule *sw, pool assigned) + { + pool all_assigned; + bool full_case = sw->get_bool_attribute("\\full_case"); + bool first = true; + for (auto it : sw->cases) { + if (it->compare.empty()) + full_case = true; + pool case_assigned = do_case(it, assigned); + if (first) { + first = false; + all_assigned = case_assigned; + } else { + for (auto &bit : all_assigned) + if (!case_assigned[bit]) + all_assigned.erase(bit); + } + } + if (full_case) + assigned.insert(all_assigned.begin(), all_assigned.end()); + return assigned; + } + + pool do_case(RTLIL::CaseRule *cs, pool assigned) + { + for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) { + pool sw_assigned = do_switch((*it), assigned); + assigned.insert(sw_assigned.begin(), sw_assigned.end()); + } + pool remove; + for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) { + RTLIL::SigSpec lhs = sigmap(it->first); + bool redundant = true; + for (auto &bit : lhs) { + if (bit.wire && !assigned[bit]) { + redundant = false; + break; + } + } + if (redundant) + remove.insert(*it); + else { + for (auto &bit : lhs) + if (bit.wire) + assigned.insert(bit); + } + } + for (auto it = cs->actions.begin(); it != cs->actions.end(); ) { + if (remove[*it]) { + it = cs->actions.erase(it); + count++; + } else it++; + } + return assigned; + } + + void do_process(RTLIL::Process *pr) + { + do_case(&pr->root_case, {}); + } +}; + +struct ProcPrunePass : public Pass { + ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" proc_prune [selection]\n"); + log("\n"); + log("This pass identifies assignments in processes that are always overwritten by\n"); + log("a later assignment to the same signal and removes them.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + int total_count = 0; + log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n"); + + extra_args(args, 1, design); + + for (auto mod : design->modules()) { + if (!design->selected(mod)) + continue; + PruneWorker worker(mod); + for (auto &proc_it : mod->processes) { + if (!design->selected(mod, proc_it.second)) + continue; + worker.do_process(proc_it.second); + } + total_count += worker.count; + } + + log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s"); + } +} ProcPrunePass; + +PRIVATE_NAMESPACE_END From 44bcb7a187ffa00921cb14fa50428ce272ce3b6b Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 08:14:52 +0000 Subject: [PATCH 838/927] proc_prune: promote assigns to module connections when legal. This can pave the way for further transformations by exposing identities that were previously hidden in a process to any pass that uses SigMap. Indeed, this commit removes some ad-hoc logic from proc_init that appears to have been tailored to the output of genrtlil in favor of using `SigMap.apply()`. (This removal is not optional, as the ad-hoc logic cannot cope with the result of running proc_prune; a similar issue was fixed in proc_arst.) --- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_init.cc | 26 +++++----------------- passes/proc/proc_prune.cc | 47 +++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index b69eba3f9..d069f152a 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -172,7 +172,7 @@ restart_proc_arst: sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0; } for (auto &action : sync->actions) { - RTLIL::SigSpec rspec = action.second; + RTLIL::SigSpec rspec = assign_map(action.second); RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size()); for (int i = 0; i < GetSize(rspec); i++) if (rspec[i].wire == NULL) diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index e2dc07e53..462a384b7 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -26,21 +26,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) -{ - log_assert(rule.compare.size() == 0); - - while (1) { - RTLIL::SigSpec tmp = sig; - for (auto &it : rule.actions) - tmp.replace(it.first, it.second); - if (tmp == sig) - break; - sig = tmp; - } -} - -void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) +void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) { bool found_init = false; @@ -53,9 +39,7 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) for (auto &action : sync->actions) { RTLIL::SigSpec lhs = action.first; - RTLIL::SigSpec rhs = action.second; - - proc_get_const(rhs, proc->root_case); + RTLIL::SigSpec rhs = sigmap(action.second); if (!rhs.is_fully_const()) log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs)); @@ -120,10 +104,12 @@ struct ProcInitPass : public Pass { extra_args(args, 1, design); for (auto mod : design->modules()) - if (design->selected(mod)) + if (design->selected(mod)) { + SigMap sigmap(mod); for (auto &proc_it : mod->processes) if (design->selected(mod, proc_it.second)) - proc_init(mod, proc_it.second); + proc_init(mod, sigmap, proc_it.second); + } } } ProcInitPass; diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index 7222d414d..9e00b0a8a 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -31,11 +31,11 @@ struct PruneWorker RTLIL::Module *module; SigMap sigmap; - int count = 0; + int removed_count = 0, promoted_count = 0; PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {} - pool do_switch(RTLIL::SwitchRule *sw, pool assigned) + pool do_switch(RTLIL::SwitchRule *sw, pool assigned, pool &affected) { pool all_assigned; bool full_case = sw->get_bool_attribute("\\full_case"); @@ -43,7 +43,7 @@ struct PruneWorker for (auto it : sw->cases) { if (it->compare.empty()) full_case = true; - pool case_assigned = do_case(it, assigned); + pool case_assigned = do_case(it, assigned, affected); if (first) { first = false; all_assigned = case_assigned; @@ -58,10 +58,11 @@ struct PruneWorker return assigned; } - pool do_case(RTLIL::CaseRule *cs, pool assigned) + pool do_case(RTLIL::CaseRule *cs, pool assigned, pool &affected, + bool root = false) { for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) { - pool sw_assigned = do_switch((*it), assigned); + pool sw_assigned = do_switch((*it), assigned, affected); assigned.insert(sw_assigned.begin(), sw_assigned.end()); } pool remove; @@ -74,18 +75,35 @@ struct PruneWorker break; } } - if (redundant) + if (redundant) { + removed_count++; remove.insert(*it); - else { + } else { + if (root) { + bool promotable = true; + for (auto &bit : lhs) { + if (bit.wire && affected[bit]) { + promotable = false; + break; + } + } + if (promotable) { + promoted_count++; + module->connect(*it); + remove.insert(*it); + } + } for (auto &bit : lhs) if (bit.wire) assigned.insert(bit); + for (auto &bit : lhs) + if (bit.wire) + affected.insert(bit); } } for (auto it = cs->actions.begin(); it != cs->actions.end(); ) { if (remove[*it]) { it = cs->actions.erase(it); - count++; } else it++; } return assigned; @@ -93,7 +111,8 @@ struct PruneWorker void do_process(RTLIL::Process *pr) { - do_case(&pr->root_case, {}); + pool affected; + do_case(&pr->root_case, {}, affected, /*root=*/true); } }; @@ -111,7 +130,7 @@ struct ProcPrunePass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - int total_count = 0; + int total_removed_count = 0, total_promoted_count = 0; log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n"); extra_args(args, 1, design); @@ -125,10 +144,14 @@ struct ProcPrunePass : public Pass { continue; worker.do_process(proc_it.second); } - total_count += worker.count; + total_removed_count += worker.removed_count; + total_promoted_count += worker.promoted_count; } - log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s"); + log("Removed %d redundant assignment%s.\n", + total_removed_count, total_removed_count == 1 ? "" : "s"); + log("Promoted %d assignment%s to connection%s.\n", + total_promoted_count, total_promoted_count == 1 ? "" : "s", total_promoted_count == 1 ? "" : "s"); } } ProcPrunePass; From 667199d46013d116bdbeb9be8592a77503a470e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:16:00 -0700 Subject: [PATCH 839/927] Fix spacing --- 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 6eab74a21..abdf7f9cc 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -287,7 +287,7 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; + case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; case 3: case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: From bc84f7dd10ad44118fd6d800cb7a896069fd223d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:22:12 -0700 Subject: [PATCH 840/927] Fix spacing --- 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 abdf7f9cc..2a77ce397 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -270,7 +270,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - if (widemux > 0) + if (widemux > 0) run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover // performs less efficiently else From 5a0f2e43c796ed91693d60261bd75a489f778a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:35:09 -0700 Subject: [PATCH 841/927] Rename __builtin_bswap32 -> bswap32 --- 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 869b741a6..69f63486c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -21,13 +21,15 @@ // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include -#define __builtin_bswap32 _byteswap_ulong +#define bswap32 _byteswap_ulong #elif defined(__APPLE__) #include -#define __builtin_bswap32 OSSwapInt32 -#elif !defined(__GNUC__) +#define bswap32 OSSwapInt32 +#elif defined(__GNUC__) +#define bswap32 __builtin_bswap32 +#else #include -inline uint32_t __builtin_bswap32(uint32_t x) +inline static uint32_t bswap32(uint32_t x) { // https://stackoverflow.com/a/27796212 register uint32_t value = number_to_be_reversed; From 713337255e6ab57b0679d64539d5c87d036c067f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:14:23 -0700 Subject: [PATCH 842/927] Revert "Add "synth -keepdc" option" --- CHANGELOG | 1 - passes/opt/wreduce.cc | 2 +- techlibs/common/synth.cc | 15 ++------------- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 646d63a63..ae7d28236 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,7 +12,6 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - - Added "synth -keepdc" - Added "script -scriptwire diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index f749c8249..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values on $mux cells.\n"); + log(" Do not optimize explicit don't-care values.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index af70cc498..555de9fba 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -78,9 +78,6 @@ struct SynthPass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); - log(" -keepdc\n"); - log(" do not optimize explicit don't-care values on $mux cells.\n"); - log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -88,7 +85,7 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, keepdc; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare; int lut; void clear_flags() YS_OVERRIDE @@ -105,7 +102,6 @@ struct SynthPass : public ScriptPass noabc = false; noshare = false; abc = "abc"; - keepdc = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -171,10 +167,6 @@ struct SynthPass : public ScriptPass abc = "abc9"; continue; } - if (args[argidx] == "-keepdc") { - keepdc = true; - continue; - } break; } extra_args(args, argidx, design); @@ -219,10 +211,7 @@ struct SynthPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - if (help_mode) - run("wreduce [-keepdc]"); - else - run("wreduce" + std::string(keepdc ? " -keepdc" : "")); + run("wreduce"); run("peepopt"); run("opt_clean"); if (help_mode) From 737340327fd8bae4a3b958d85cb14eecb767ed67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:15:02 -0700 Subject: [PATCH 843/927] Revert "synth_xilinx to call "synth -run coarse" with "-keepdc"" This reverts commit 7f964859ec99500e471853f5914b6e5b7c35a031. --- 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 2a77ce397..8da6df57e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -240,9 +240,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { if (help_mode) - run("synth -keepdc -run coarse [-flatten]", "(with '-flatten')"); + run("synth -run coarse [-flatten]", "(with '-flatten')"); else - run("synth -keepdc -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); From c68b9092100280dbc059526a88f9d8e2902ff6a3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:21:54 -0700 Subject: [PATCH 844/927] synth_xilinx to call commands of synth -coarse directly --- techlibs/xilinx/synth_xilinx.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8da6df57e..0152af481 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -239,10 +239,25 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { + run("proc"); + if (help_mode || flatten) + run("flatten", "(if -flatten)"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt"); if (help_mode) - run("synth -run coarse [-flatten]", "(with '-flatten')"); + run("wreduce [-keepdc]", "(option for '-widemux')"); else - run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); + run("peepopt"); + run("opt_clean"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -253,6 +268,8 @@ struct SynthXilinxPass : public ScriptPass // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); + + run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -344,7 +361,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef"); if (help_mode) - run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')"); + run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')"); else if (abc9) { if (family != "xc7") log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); From c8649953431d3789296c4a7c1bd559ec136af6e3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:38:07 -0700 Subject: [PATCH 845/927] Fix typo and comments --- 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 d3f6a60cc..233a56003 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -204,7 +204,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 4) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [4-1:0] Ax; if (A_WIDTH == 4) @@ -215,7 +215,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [8-1:0] Ax; if (A_WIDTH == 8) @@ -230,13 +230,13 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [16-1:0] Ax; if (A_WIDTH == 16) assign Ax = A; else - assign Ax = {A[7-:8-A_WIDTH], A}; + assign Ax = {A[7-:16-A_WIDTH], A}; wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] : B[3] ? Ax[ 8] : Ax[0]; wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] From 93522b0ae15466297e45edecf55f7e33c4ebcc1c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:59:37 -0700 Subject: [PATCH 846/927] Extend during mux decomposition with 1'bx --- techlibs/xilinx/cells_map.v | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 233a56003..e81ff8f53 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -203,25 +203,11 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [4-1:0] Ax; - if (A_WIDTH == 4) - assign Ax = A; - else - assign Ax = {A[1-:4-A_WIDTH], A}; + wire [4-1:0] Ax = {{{4-A_WIDTH}{1'bx}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [8-1:0] Ax; - if (A_WIDTH == 8) - assign Ax = A; - else - assign Ax = {A[3-:8-A_WIDTH], A}; + wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? Ax[4] : Ax[0]; wire T1 = B[2] ? Ax[5] : Ax[1]; wire T2 = B[2] ? Ax[6] : Ax[2]; @@ -229,14 +215,7 @@ module \$__XILINX_SHIFTX (A, B, Y); \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 16) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [16-1:0] Ax; - if (A_WIDTH == 16) - assign Ax = A; - else - assign Ax = {A[7-:16-A_WIDTH], A}; + wire [16-1:0] Ax = {{{16-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] : B[3] ? Ax[ 8] : Ax[0]; wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] From 6a29e1f5b7e8ac36fcf8c5f00c509ebeaa5257e5 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 18:30:24 +0000 Subject: [PATCH 847/927] write_verilog: write RTLIL::Sa aka - as Verilog ?. Currently, the only ways (determined by grepping for regex \bSa\b) to end up with RTLIL::Sa in a netlist is by reading a Verilog constant with ? in it as a part of case, or by running certain FSM passes. Both of these cases should be round-tripped back to ? in Verilog. --- backends/verilog/verilog_backend.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6288502a5..1c68288ce 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -222,7 +222,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o case RTLIL::S1: bin_digits.push_back('1'); break; case RTLIL::Sx: bin_digits.push_back('x'); break; case RTLIL::Sz: bin_digits.push_back('z'); break; - case RTLIL::Sa: bin_digits.push_back('z'); break; + case RTLIL::Sa: bin_digits.push_back('?'); break; case RTLIL::Sm: log_error("Found marker state in final netlist."); } } @@ -251,6 +251,12 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o hex_digits.push_back('z'); continue; } + if (bit_3 == '?' || bit_2 == '?' || bit_1 == '?' || bit_0 == '?') { + if (bit_3 != '?' || bit_2 != '?' || bit_1 != '?' || bit_0 != '?') + goto dump_bin; + hex_digits.push_back('?'); + continue; + } int val = 8*(bit_3 - '0') + 4*(bit_2 - '0') + 2*(bit_1 - '0') + (bit_0 - '0'); hex_digits.push_back(val < 10 ? '0' + val : 'a' + val - 10); } @@ -270,7 +276,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o case RTLIL::S1: f << stringf("1"); break; case RTLIL::Sx: f << stringf("x"); break; case RTLIL::Sz: f << stringf("z"); break; - case RTLIL::Sa: f << stringf("z"); break; + case RTLIL::Sa: f << stringf("?"); break; case RTLIL::Sm: log_error("Found marker state in final netlist."); } } From f8512864cd2b9c0c17d71d4196dbf3f25ec554d1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:01 +0200 Subject: [PATCH 848/927] Add tests/simple_abc9/.gitignore Signed-off-by: Clifford Wolf --- tests/simple_abc9/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/simple_abc9/.gitignore diff --git a/tests/simple_abc9/.gitignore b/tests/simple_abc9/.gitignore new file mode 100644 index 000000000..598951333 --- /dev/null +++ b/tests/simple_abc9/.gitignore @@ -0,0 +1,3 @@ +*.v +*.log +*.out From 3dd92fcd15bc3f1448a97e6bb7c997d36781b55c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:28 +0200 Subject: [PATCH 849/927] Improve tests/various/run-test.sh Signed-off-by: Clifford Wolf --- tests/various/run-test.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh index d49553ede..92b905765 100755 --- a/tests/various/run-test.sh +++ b/tests/various/run-test.sh @@ -4,11 +4,9 @@ for x in *.ys; do echo "Running $x.." ../../yosys -ql ${x%.ys}.log $x done -# Run any .sh files in this directory (with the exception of the file - run-test.sh -shell_tests=$(echo *.sh | sed -e 's/run-test.sh//') -if [ "$shell_tests" ]; then - for s in $shell_tests; do - echo "Running $s.." - bash $s - done -fi +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "Running $s.." + bash $s + fi +done From c18b23f0559f2232186ce3b97b4ffb64877abd5c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:59 +0200 Subject: [PATCH 850/927] Add tests/various/async.{sh,v} Signed-off-by: Clifford Wolf --- tests/various/async.sh | 6 ++++ tests/various/async.v | 82 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/various/async.sh create mode 100644 tests/various/async.v diff --git a/tests/various/async.sh b/tests/various/async.sh new file mode 100644 index 000000000..423034eb8 --- /dev/null +++ b/tests/various/async.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -ex +../../yosys -q -o async_syn.v -p 'synth; rename uut syn' async.v +iverilog -o async_sim -DTESTBENCH async.v async_syn.v +vvp -N async_sim > async.out +rm -f async_syn.v async_sim async.out async.vcd diff --git a/tests/various/async.v b/tests/various/async.v new file mode 100644 index 000000000..229b5b939 --- /dev/null +++ b/tests/various/async.v @@ -0,0 +1,82 @@ +`define MAXQ 2 +module uut ( + input clk, + input d, r, e, + output [`MAXQ:0] q +); + reg q0; + always @(posedge clk) begin + if (r) + q0 <= 0; + else if (e) + q0 <= d; + end + + reg q1; + always @(posedge clk, posedge r) begin + if (r) + q1 <= 0; + else if (e) + q1 <= d; + end + + reg q2; + always @(posedge clk, negedge r) begin + if (!r) + q2 <= 0; + else if (!e) + q2 <= d; + end + + assign q = {q2, q1, q0}; +endmodule + +`ifdef TESTBENCH +module testbench; + reg clk; + always #5 clk = (clk === 1'b0); + + reg d, r, e; + + wire [`MAXQ:0] q_uut; + uut uut (.clk(clk), .d(d), .r(r), .e(e), .q(q_uut)); + + wire [`MAXQ:0] q_syn; + syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn)); + + task printq; + reg [5*8-1:0] msg; + begin + msg = "OK"; + if (q_uut != q_syn) msg = "SYN"; + $display("%6t %b %b %s", $time, q_uut, q_syn, msg); + if (msg != "OK") $stop; + end + endtask + + initial if(0) begin + $dumpfile("async.vcd"); + $dumpvars(0, testbench); + end + + initial begin + @(posedge clk); + d <= 0; + r <= 0; + e <= 0; + @(posedge clk); + e <= 1; + @(posedge clk); + e <= 0; + repeat (10000) begin + @(posedge clk); + printq; + d <= $random; + r <= $random; + e <= $random; + end + $display("OK"); + $finish; + end +endmodule +`endif From c2db70f41e2697d141439c093813ae48f3b7a5d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 12:14:00 -0700 Subject: [PATCH 851/927] Increment _TECHMAP_BITS_CONNMAP_ by one since counting from zero --- passes/techmap/techmap.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index ab0bd3b54..ceb053825 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -649,10 +649,13 @@ struct TechmapWorker unique_bit_id[bit] = unique_bit_id_counter++; } + // Find highest bit set int bits = 0; for (int i = 0; i < 32; i++) if (((unique_bit_id_counter-1) & (1 << i)) != 0) bits = i; + // Increment index by one to get number of bits + bits++; if (tpl->avail_parameters.count("\\_TECHMAP_BITS_CONNMAP_")) parameters["\\_TECHMAP_BITS_CONNMAP_"] = bits; From 37bb6b5e96fcedc1126c31aac84b8c029e192f5f Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 19:14:03 +0000 Subject: [PATCH 852/927] write_verilog: fix placement of case attributes. NFC. --- backends/verilog/verilog_backend.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6288502a5..087c6fec6 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1501,6 +1501,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw bool got_default = false; for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true); if ((*it)->compare.size() == 0) { if (got_default) continue; @@ -1514,9 +1515,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":"); - dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); - f << stringf("\n"); + f << stringf(":\n"); dump_case_body(f, indent + " ", *it); } From b1a048a703b12bc02433d8c2c98b4b35cc799979 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 12:35:41 -0700 Subject: [PATCH 853/927] Extend using A[1] to preserve don't care --- techlibs/xilinx/cells_map.v | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e81ff8f53..f20fe253e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -203,7 +203,15 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin - wire [4-1:0] Ax = {{{4-A_WIDTH}{1'bx}}, A}; + wire [4-1:0] Ax; + if (A_WIDTH == 4) + assign Ax = A; + else + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" status to get lost, extend with + // the same driver of F7B.I0 so that we can optimise F7B away + // later + assign Ax = {A[1], A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin From 513862148211401fe71fb7966c81773042665acd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 22:21:25 +0200 Subject: [PATCH 854/927] Improve tests/various/async, disable failing ffl test Signed-off-by: Clifford Wolf --- tests/various/async.sh | 9 +++++++-- tests/various/async.v | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tests/various/async.sh b/tests/various/async.sh index 423034eb8..7c41d6d94 100644 --- a/tests/various/async.sh +++ b/tests/various/async.sh @@ -1,6 +1,11 @@ #!/bin/bash set -ex ../../yosys -q -o async_syn.v -p 'synth; rename uut syn' async.v -iverilog -o async_sim -DTESTBENCH async.v async_syn.v +../../yosys -q -o async_prp.v -p 'prep; rename uut prp' async.v +../../yosys -q -o async_a2s.v -p 'prep; async2sync; rename uut a2s' async.v +../../yosys -q -o async_ffl.v -p 'prep; clk2fflogic; rename uut ffl' async.v +iverilog -o async_sim -DTESTBENCH async.v async_???.v vvp -N async_sim > async.out -rm -f async_syn.v async_sim async.out async.vcd +tail async.out +grep PASS async.out +rm -f async_???.v async_sim async.out async.vcd diff --git a/tests/various/async.v b/tests/various/async.v index 229b5b939..1e32a06b5 100644 --- a/tests/various/async.v +++ b/tests/various/async.v @@ -32,9 +32,23 @@ module uut ( endmodule `ifdef TESTBENCH +module \$ff #( + parameter integer WIDTH = 1 +) ( + input [WIDTH-1:0] D, + output reg [WIDTH-1:0] Q +); + wire sysclk = testbench.sysclk; + always @(posedge sysclk) + Q <= D; +endmodule + module testbench; + reg sysclk; + always #5 sysclk = (sysclk === 1'b0); + reg clk; - always #5 clk = (clk === 1'b0); + always @(posedge sysclk) clk = (clk === 1'b0); reg d, r, e; @@ -44,13 +58,25 @@ module testbench; wire [`MAXQ:0] q_syn; syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn)); + wire [`MAXQ:0] q_prp; + prp prp (.clk(clk), .d(d), .r(r), .e(e), .q(q_prp)); + + wire [`MAXQ:0] q_a2s; + a2s a2s (.clk(clk), .d(d), .r(r), .e(e), .q(q_a2s)); + + wire [`MAXQ:0] q_ffl; + ffl ffl (.clk(clk), .d(d), .r(r), .e(e), .q(q_ffl)); + task printq; reg [5*8-1:0] msg; begin msg = "OK"; - if (q_uut != q_syn) msg = "SYN"; - $display("%6t %b %b %s", $time, q_uut, q_syn, msg); - if (msg != "OK") $stop; + if (q_uut !== q_syn) msg = "SYN"; + if (q_uut !== q_prp) msg = "PRP"; + if (q_uut !== q_a2s) msg = "A2S"; + // if (q_uut !== q_ffl) msg = "FFL"; + $display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg); + if (msg != "OK") $finish; end endtask @@ -75,7 +101,7 @@ module testbench; r <= $random; e <= $random; end - $display("OK"); + $display("PASS"); $finish; end endmodule From 9546ccdbd348b1dc056884a536246801cdf1c4f1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 22:44:39 +0200 Subject: [PATCH 855/927] Fix tests/various/async FFL test Signed-off-by: Clifford Wolf --- passes/sat/clk2fflogic.cc | 7 +++++++ tests/various/async.v | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index 49ec795d3..4bb4aa047 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -253,6 +253,13 @@ struct Clk2fflogicPass : public Pass { SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge); Const rstval = cell->parameters["\\ARST_VALUE"]; + Wire *past_arst = module->addWire(NEW_ID); + module->addFf(NEW_ID, arst, past_arst); + if (cell->parameters["\\ARST_POLARITY"].as_bool()) + arst = module->LogicOr(NEW_ID, arst, past_arst); + else + arst = module->LogicAnd(NEW_ID, arst, past_arst); + if (cell->parameters["\\ARST_POLARITY"].as_bool()) module->addMux(NEW_ID, qval, rstval, arst, sig_q); else diff --git a/tests/various/async.v b/tests/various/async.v index 1e32a06b5..c27e30c4b 100644 --- a/tests/various/async.v +++ b/tests/various/async.v @@ -74,7 +74,7 @@ module testbench; if (q_uut !== q_syn) msg = "SYN"; if (q_uut !== q_prp) msg = "PRP"; if (q_uut !== q_a2s) msg = "A2S"; - // if (q_uut !== q_ffl) msg = "FFL"; + if (q_uut !== q_ffl) msg = "FFL"; $display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg); if (msg != "OK") $finish; end From 27b27b8781ab8d57aa85a432aba7e914570feffb Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 9 Jul 2019 22:26:10 +0100 Subject: [PATCH 856/927] synth_ecp5: Fix typo in copyright header Signed-off-by: David Shah --- techlibs/ecp5/synth_ecp5.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index f16a47f01..3b0c2ea9e 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 David Shah * * 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 5b48b18d29dabfaa3aa51fc4946f14b0ea8954e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 14:28:54 -0700 Subject: [PATCH 857/927] Restore missing techmap -map +/cmp2lut.v with LUT_WIDTH=6 --- 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 0152af481..7e10a392a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * (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 @@ -252,6 +253,7 @@ struct SynthXilinxPass : public ScriptPass run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); run("alumacc"); run("share"); run("opt"); From c55530b90197302e7c27eb106094fa74a178fc67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 14:29:58 -0700 Subject: [PATCH 858/927] Restore opt_clean back to original place --- techlibs/xilinx/synth_xilinx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7e10a392a..c4877c8af 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -260,6 +260,7 @@ struct SynthXilinxPass : public ScriptPass run("fsm"); run("opt -fast"); run("memory -nomap"); + run("opt_clean"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -270,8 +271,6 @@ struct SynthXilinxPass : public ScriptPass // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); - - run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { From 1122a2e0671ed00b7c03658f5012e34df12f26de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 15:49:16 -0700 Subject: [PATCH 859/927] Fix first divergence in #1178 --- passes/opt/wreduce.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..65068238b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -430,6 +430,7 @@ struct WreduceWorker for (auto w : module->wires()) complete_wires.insert(mi.sigmap(w)); + std::vector> swap_wire_names; for (auto w : module->selected_wires()) { int unused_top_bits = 0; @@ -454,9 +455,12 @@ struct WreduceWorker log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w)); Wire *nw = module->addWire(NEW_ID, GetSize(w) - unused_top_bits); module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); - module->swap_names(w, nw); + swap_wire_names.emplace_back(w, nw); } + for (const auto &i : swap_wire_names) + module->swap_names(i.first, i.second); + if (!remove_init_bits.empty()) { for (auto w : module->wires()) { if (w->attributes.count("\\init")) { From e573d024a257a6cf8925784f6f22d192a1f24693 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 21:26:38 -0700 Subject: [PATCH 860/927] Call muxpack and pmux2shiftx before cmp2lut --- techlibs/xilinx/synth_xilinx.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c4877c8af..ef7660288 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -253,14 +253,6 @@ struct SynthXilinxPass : public ScriptPass run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); - run("alumacc"); - run("share"); - run("opt"); - run("fsm"); - run("opt -fast"); - run("memory -nomap"); - run("opt_clean"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -269,8 +261,19 @@ 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 && widemux == 0) || help_mode) + if (!(nosrl && widemux == 0) || help_mode) { run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); + run("clean", " (skip if '-nosrl' and '-widemux=0')"); + } + + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { From ea447220dab2a5a66adb3a78ca2789068f046f3a Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 10 Jul 2019 12:28:32 +0000 Subject: [PATCH 861/927] attrmap: also consider process, switch and case attributes. --- passes/techmap/attrmap.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index aa48e1125..a38638e0b 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -263,6 +263,25 @@ struct AttrmapPass : public Pass { for (auto cell : module->selected_cells()) attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->attributes); + + for (auto proc : module->processes) + { + if (!design->selected(module, proc.second)) + continue; + attrmap_apply(stringf("%s.%s", log_id(module), log_id(proc.first)), actions, proc.second->attributes); + + std::vector all_cases = {&proc.second->root_case}; + while (!all_cases.empty()) { + RTLIL::CaseRule *cs = all_cases.back(); + all_cases.pop_back(); + attrmap_apply(stringf("%s.%s (case)", log_id(module), log_id(proc.first)), actions, cs->attributes); + + for (auto &sw : cs->switches) { + attrmap_apply(stringf("%s.%s (switch)", log_id(module), log_id(proc.first)), actions, sw->attributes); + all_cases.insert(all_cases.end(), sw->cases.begin(), sw->cases.end()); + } + } + } } } } From 521971e32ef54fa64474a8ed1c2748572901aaf5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:20:04 -0700 Subject: [PATCH 862/927] Add some ASCII art explaining mux decomposition --- techlibs/xilinx/cells_map.v | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f20fe253e..82399be08 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -214,6 +214,27 @@ module \$__XILINX_SHIFTX (A, B, Y); assign Ax = {A[1], A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end + // Note that the following decompositions are 'backwards' in that + // the LSBs are placed on the hard resources, and the soft resources + // are used for MSBs. + // This has the effect of more effectively utilising the hard mux; + // take for example a 5:1 multiplexer, currently this would map as: + // + // A[0] \___ __ A[0] \__ __ + // A[4] / \| \ whereas the more A[1] / \| \ + // A[1] _____| | obvious mapping A[2] \___| | + // A[2] _____| |-- of MSBs to hard A[3] / | |__ + // A[3]______| | resources would A[4] ____| | + // |__/ lead to: 1'bx ____| | + // || |__/ + // || || + // B[1:0] B[1:2] + // + // Expectation would be that the 'forward' mapping (right) is more + // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers + // on its I0 and I1 inputs, and A[8] and 1'bx on its I2 and I3 inputs) + // but that the 'backwards' mapping (left) is more delay efficient + // since smaller LUTs are faster than wider ones. else if (A_WIDTH <= 8) begin wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? Ax[4] : Ax[0]; From 58bb84e5b22ba66310fd54fecdbf5817138a5fd1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:32:33 -0700 Subject: [PATCH 863/927] Add some spacing --- techlibs/xilinx/cells_map.v | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 82399be08..2eb9fa2c1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -220,15 +220,15 @@ module \$__XILINX_SHIFTX (A, B, Y); // This has the effect of more effectively utilising the hard mux; // take for example a 5:1 multiplexer, currently this would map as: // - // A[0] \___ __ A[0] \__ __ - // A[4] / \| \ whereas the more A[1] / \| \ - // A[1] _____| | obvious mapping A[2] \___| | - // A[2] _____| |-- of MSBs to hard A[3] / | |__ - // A[3]______| | resources would A[4] ____| | - // |__/ lead to: 1'bx ____| | - // || |__/ - // || || - // B[1:0] B[1:2] + // A[0] \___ __ A[0] \__ __ + // A[4] / \| \ whereas the more A[1] / \| \ + // A[1] _____| | obvious mapping A[2] \___| | + // A[2] _____| |-- of MSBs to hard A[3] / | |__ + // A[3]______| | resources would A[4] ____| | + // |__/ lead to: 1'bx ____| | + // || |__/ + // || || + // B[1:0] B[1:2] // // Expectation would be that the 'forward' mapping (right) is more // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers From 6bbd286e033ed25bb49684316a86d6227dec4cd7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:47:48 -0700 Subject: [PATCH 864/927] Error out if -abc9 and -retime specified --- techlibs/ecp5/synth_ecp5.cc | 3 +++ techlibs/ice40/synth_ice40.cc | 5 ++++- techlibs/xilinx/synth_xilinx.cc | 13 ++++++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 3b0c2ea9e..9f409ca51 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -199,6 +199,9 @@ struct SynthEcp5Pass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_ECP5 pass.\n"); log_push(); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 9dd5d81f7..2c75215cb 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -227,6 +227,9 @@ struct SynthIce40Pass : public ScriptPass if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); + if (abc == "abc9" && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_ICE40 pass.\n"); log_push(); @@ -296,7 +299,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap"); else run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); - if ((retime || help_mode) && abc != "abc9") + if (retime || help_mode) run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b7c32d2e0..22c4a1a1b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,8 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate - // to one LUT6 (instead of a LUT5 + LUT2) +#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 { @@ -195,11 +195,14 @@ struct SynthXilinxPass : public ScriptPass extra_args(args, argidx, design); if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s") - log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); + 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"); + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_XILINX pass.\n"); log_push(); @@ -297,9 +300,9 @@ struct SynthXilinxPass : public ScriptPass 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" : "")); + run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY)); else - run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); + run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY)); } else { if (nowidelut) From ce250b341c912a3357b13259c1b0b6ed0a7b95a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Tue, 2 Jul 2019 14:28:35 +0200 Subject: [PATCH 865/927] synth_xilinx: Initial Spartan 6 block RAM inference support. --- techlibs/xilinx/Makefile.inc | 15 +- techlibs/xilinx/brams_init.py | 16 ++ techlibs/xilinx/synth_xilinx.cc | 25 +- techlibs/xilinx/xc6s_brams.txt | 84 ++++++ techlibs/xilinx/xc6s_brams_bb.v | 211 +++++++++++++++ techlibs/xilinx/xc6s_brams_map.v | 255 ++++++++++++++++++ techlibs/xilinx/{brams.txt => xc7_brams.txt} | 0 .../xilinx/{brams_bb.v => xc7_brams_bb.v} | 0 .../xilinx/{brams_map.v => xc7_brams_map.v} | 0 9 files changed, 598 insertions(+), 8 deletions(-) create mode 100644 techlibs/xilinx/xc6s_brams.txt create mode 100644 techlibs/xilinx/xc6s_brams_bb.v create mode 100644 techlibs/xilinx/xc6s_brams_map.v rename techlibs/xilinx/{brams.txt => xc7_brams.txt} (100%) rename techlibs/xilinx/{brams_bb.v => xc7_brams_bb.v} (100%) rename techlibs/xilinx/{brams_map.v => xc7_brams_map.v} (100%) diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 17c5df37d..2c6e7432e 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -5,6 +5,8 @@ GENFILES += techlibs/xilinx/brams_init_36.vh GENFILES += techlibs/xilinx/brams_init_32.vh GENFILES += techlibs/xilinx/brams_init_18.vh GENFILES += techlibs/xilinx/brams_init_16.vh +GENFILES += techlibs/xilinx/brams_init_9.vh +GENFILES += techlibs/xilinx/brams_init_8.vh EXTRA_OBJS += techlibs/xilinx/brams_init.mk .SECONDARY: techlibs/xilinx/brams_init.mk @@ -18,13 +20,18 @@ techlibs/xilinx/brams_init_36.vh: techlibs/xilinx/brams_init.mk techlibs/xilinx/brams_init_32.vh: techlibs/xilinx/brams_init.mk techlibs/xilinx/brams_init_18.vh: techlibs/xilinx/brams_init.mk techlibs/xilinx/brams_init_16.vh: techlibs/xilinx/brams_init.mk +techlibs/xilinx/brams_init_9.vh: techlibs/xilinx/brams_init.mk +techlibs/xilinx/brams_init_8.vh: techlibs/xilinx/brams_init.mk $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_xtra.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.txt)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams.txt)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_bb.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) @@ -40,4 +47,6 @@ $(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)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_18.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_16.vh)) +$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_9.vh)) +$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_8.vh)) diff --git a/techlibs/xilinx/brams_init.py b/techlibs/xilinx/brams_init.py index d46a2b4f7..10057a0cb 100644 --- a/techlibs/xilinx/brams_init.py +++ b/techlibs/xilinx/brams_init.py @@ -1,5 +1,17 @@ #!/usr/bin/env python3 +with open("techlibs/xilinx/brams_init_9.vh", "w") as f: + for i in range(4): + init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)] + for k in range(4, 256, 4): + init_snippets[k] = "\n " + init_snippets[k] + print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f) + for i in range(32): + init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)] + for k in range(4, 32, 4): + init_snippets[k] = "\n " + init_snippets[k] + print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f) + with open("techlibs/xilinx/brams_init_18.vh", "w") as f: for i in range(8): init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)] @@ -24,6 +36,10 @@ with open("techlibs/xilinx/brams_init_36.vh", "w") as f: init_snippets[k] = "\n " + init_snippets[k] print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f) +with open("techlibs/xilinx/brams_init_8.vh", "w") as f: + for i in range(32): + print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f) + with open("techlibs/xilinx/brams_init_16.vh", "w") as f: for i in range(64): print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 77daa745c..b672a0d4f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -236,8 +236,13 @@ struct SynthXilinxPass : public ScriptPass run("read_verilog -lib +/xilinx/cells_xtra.v"); - if (!nobram || help_mode) - run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')"); + if (help_mode) { + run("read_verilog -lib +/xilinx/{family}_brams_bb.v"); + } else if (family == "xc6s") { + run("read_verilog -lib +/xilinx/xc6s_brams_bb.v"); + } else if (family == "xc7") { + run("read_verilog -lib +/xilinx/xc7_brams_bb.v"); + } run(stringf("hierarchy -check %s", top_opt.c_str())); } @@ -280,9 +285,19 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("bram", "(skip if '-nobram')")) { - if (!nobram || help_mode) { - run("memory_bram -rules +/xilinx/brams.txt"); - run("techmap -map +/xilinx/brams_map.v"); + if (help_mode) { + run("memory_bram -rules +/xilinx/{family}_brams.txt"); + run("techmap -map +/xilinx/{family}_brams_map.v"); + } else if (!nobram) { + if (family == "xc6s") { + run("memory_bram -rules +/xilinx/xc6s_brams.txt"); + run("techmap -map +/xilinx/xc6s_brams_map.v"); + } else if (family == "xc7") { + run("memory_bram -rules +/xilinx/xc7_brams.txt"); + run("techmap -map +/xilinx/xc7_brams_map.v"); + } else { + log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str()); + } } } diff --git a/techlibs/xilinx/xc6s_brams.txt b/techlibs/xilinx/xc6s_brams.txt new file mode 100644 index 000000000..17cd8e355 --- /dev/null +++ b/techlibs/xilinx/xc6s_brams.txt @@ -0,0 +1,84 @@ + +bram $__XILINX_RAMB8BWER_SDP + init 1 + abits 8 + dbits 36 + groups 2 + ports 1 1 + wrmode 0 1 + enable 1 4 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB16BWER_TDP + init 1 + abits 9 @a9d36 + dbits 36 @a9d36 + abits 10 @a10d18 + dbits 18 @a10d18 + abits 11 @a11d9 + dbits 9 @a11d9 + abits 12 @a12d4 + dbits 4 @a12d4 + abits 13 @a13d2 + dbits 2 @a13d2 + abits 14 @a14d1 + dbits 1 @a14d1 + groups 2 + ports 1 1 + wrmode 0 1 + enable 1 4 @a9d36 + enable 1 2 @a10d18 + enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB8BWER_TDP + init 1 + abits 9 @a9d18 + dbits 18 @a9d18 + abits 10 @a10d9 + dbits 9 @a10d9 + abits 11 @a11d4 + dbits 4 @a11d4 + abits 12 @a12d2 + dbits 2 @a12d2 + abits 13 @a13d1 + dbits 1 @a13d1 + groups 2 + ports 1 1 + wrmode 0 1 + enable 1 2 @a9d18 + enable 1 1 @a10d9 @a11d4 @a12d2 @a13d1 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +match $__XILINX_RAMB8BWER_SDP + min bits 4096 + min efficiency 5 + shuffle_enable B + make_transp + or_next_if_better +endmatch + +match $__XILINX_RAMB16BWER_TDP + min bits 4096 + min efficiency 5 + shuffle_enable B + make_transp + or_next_if_better +endmatch + +match $__XILINX_RAMB8BWER_TDP + min bits 4096 + min efficiency 5 + shuffle_enable B + make_transp +endmatch + diff --git a/techlibs/xilinx/xc6s_brams_bb.v b/techlibs/xilinx/xc6s_brams_bb.v new file mode 100644 index 000000000..eb1a29579 --- /dev/null +++ b/techlibs/xilinx/xc6s_brams_bb.v @@ -0,0 +1,211 @@ +module RAMB8BWER ( + input CLKAWRCLK, + input CLKBRDCLK, + input ENAWREN, + input ENBRDEN, + input REGCEA, + input REGCEBREGCE, + input RSTA, + input RSTBRST, + + input [12:0] ADDRAWRADDR, + input [12:0] ADDRBRDADDR, + input [15:0] DIADI, + input [15:0] DIBDI, + input [1:0] DIPADIP, + input [1:0] DIPBDIP, + input [1:0] WEAWEL, + input [1:0] WEBWEU, + + 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; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + parameter RAM_MODE = "TDP"; + parameter integer DOA_REG = 0; + parameter integer DOB_REG = 0; + + parameter integer DATA_WIDTH_A = 0; + parameter integer DATA_WIDTH_B = 0; + + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + + parameter EN_RSTRAM_A = "TRUE"; + parameter EN_RSTRAM_B = "TRUE"; + + parameter INIT_A = 18'h000000000; + parameter INIT_B = 18'h000000000; + parameter SRVAL_A = 18'h000000000; + parameter SRVAL_B = 18'h000000000; + + parameter RST_PRIORITY_A = "CE"; + parameter RST_PRIORITY_B = "CE"; + + parameter RSTTYPE = "SYNC"; + + parameter SIM_COLLISION_CHECK = "ALL"; +endmodule + +module RAMB16BWER ( + input CLKA, + input CLKB, + input ENA, + input ENB, + input REGCEA, + input REGCEB, + input RSTA, + input RSTB, + + input [13:0] ADDRA, + input [13:0] ADDRB, + input [31:0] DIA, + input [31:0] DIB, + input [3:0] DIPA, + input [3:0] DIPB, + input [3:0] WEA, + input [3:0] WEB, + + output [31:0] DOA, + output [31:0] DOB, + output [3:0] DOPA, + output [3:0] DOPB +); + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + parameter integer DOA_REG = 0; + parameter integer DOB_REG = 0; + + parameter integer DATA_WIDTH_A = 0; + parameter integer DATA_WIDTH_B = 0; + + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + + parameter EN_RSTRAM_A = "TRUE"; + parameter EN_RSTRAM_B = "TRUE"; + + parameter INIT_A = 36'h000000000; + parameter INIT_B = 36'h000000000; + parameter SRVAL_A = 36'h000000000; + parameter SRVAL_B = 36'h000000000; + + parameter RST_PRIORITY_A = "CE"; + parameter RST_PRIORITY_B = "CE"; + + parameter RSTTYPE = "SYNC"; + + parameter SIM_COLLISION_CHECK = "ALL"; +endmodule + diff --git a/techlibs/xilinx/xc6s_brams_map.v b/techlibs/xilinx/xc6s_brams_map.v new file mode 100644 index 000000000..c9b33af42 --- /dev/null +++ b/techlibs/xilinx/xc6s_brams_map.v @@ -0,0 +1,255 @@ +module \$__XILINX_RAMB8BWER_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [9215:0] INIT = 9216'bx; + + input CLK2; + input CLK3; + + input [7:0] A1ADDR; + output [35:0] A1DATA; + input A1EN; + + input [7:0] B1ADDR; + input [35:0] B1DATA; + input [3:0] B1EN; + + wire [12:0] A1ADDR_13 = {A1ADDR, 5'b0}; + wire [12:0] B1ADDR_13 = {B1ADDR, 5'b0}; + + wire [3:0] DIP, DOP; + wire [31:0] DI, DO; + + assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + RAMB8BWER #( + .RAM_MODE("SDP"), + .DATA_WIDTH_A(36), + .DATA_WIDTH_B(36), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), + `include "brams_init_9.vh" + ) _TECHMAP_REPLACE_ ( + .DOBDO(DO[31:16]), + .DOADO(DO[15:0]), + .DOPBDOP(DOP[3:2]), + .DOPADOP(DOP[1:0]), + .DIBDI(DI[31:16]), + .DIADI(DI[15:0]), + .DIPBDIP(DIP[3:2]), + .DIPADIP(DIP[1:0]), + .WEBWEU(B1EN[3:2]), + .WEAWEL(B1EN[1:0]), + + .ADDRAWRADDR(B1ADDR_13), + .CLKAWRCLK(CLK3 ^ !CLKPOL3), + .ENAWREN(|1), + .REGCEA(|0), + .RSTA(|0), + + .ADDRBRDADDR(A1ADDR_13), + .CLKBRDCLK(CLK2 ^ !CLKPOL2), + .ENBRDEN(A1EN), + .REGCEBREGCE(|1), + .RSTB(|0) + ); +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB16BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 9; + parameter CFG_DBITS = 36; + parameter CFG_ENABLE_B = 4; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [18431:0] INIT = 18432'bx; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + output [CFG_DBITS-1:0] A1DATA; + input A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + input [CFG_DBITS-1:0] B1DATA; + input [CFG_ENABLE_B-1:0] B1EN; + + wire [13:0] A1ADDR_14 = A1ADDR << (14 - CFG_ABITS); + wire [13:0] B1ADDR_14 = B1ADDR << (14 - CFG_ABITS); + wire [3:0] B1EN_4 = {4{B1EN}}; + + wire [3:0] DIP, DOP; + wire [31:0] DI, DO; + + wire [31:0] DOB; + wire [3:0] DOPB; + + assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + generate if (CFG_DBITS > 8) begin + RAMB16BWER #( + .DATA_WIDTH_A(CFG_DBITS), + .DATA_WIDTH_B(CFG_DBITS), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), + `include "brams_init_18.vh" + ) _TECHMAP_REPLACE_ ( + .DIA(32'd0), + .DIPA(4'd0), + .DOA(DO[31:0]), + .DOPA(DOP[3:0]), + .ADDRA(A1ADDR_14), + .CLKA(CLK2 ^ !CLKPOL2), + .ENA(A1EN), + .REGCEA(|1), + .RSTA(|0), + .WEA(4'b0), + + .DIB(DI), + .DIPB(DIP), + .DOB(DOB), + .DOPB(DOPB), + .ADDRB(B1ADDR_14), + .CLKB(CLK3 ^ !CLKPOL3), + .ENB(|1), + .REGCEB(|0), + .RSTB(|0), + .WEB(B1EN_4) + ); + end else begin + RAMB16BWER #( + .DATA_WIDTH_A(CFG_DBITS), + .DATA_WIDTH_B(CFG_DBITS), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), + `include "brams_init_16.vh" + ) _TECHMAP_REPLACE_ ( + .DIA(32'd0), + .DIPA(4'd0), + .DOA(DO[31:0]), + .DOPA(DOP[3:0]), + .ADDRA(A1ADDR_14), + .CLKA(CLK2 ^ !CLKPOL2), + .ENA(A1EN), + .REGCEA(|1), + .RSTA(|0), + .WEA(4'b0), + + .DIB(DI), + .DIPB(DIP), + .DOB(DOB), + .DOPB(DOPB), + .ADDRB(B1ADDR_14), + .CLKB(CLK3 ^ !CLKPOL3), + .ENB(|1), + .REGCEB(|0), + .RSTB(|0), + .WEB(B1EN_4) + ); + end endgenerate +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB8BWER_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 9; + parameter CFG_DBITS = 18; + parameter CFG_ENABLE_B = 2; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [9215:0] INIT = 9216'bx; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + output [CFG_DBITS-1:0] A1DATA; + input A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + input [CFG_DBITS-1:0] B1DATA; + input [CFG_ENABLE_B-1:0] B1EN; + + wire [12:0] A1ADDR_13 = A1ADDR << (13 - CFG_ABITS); + wire [12:0] B1ADDR_13 = B1ADDR << (13 - CFG_ABITS); + wire [1:0] B1EN_2 = {2{B1EN}}; + + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; + + wire [15:0] DOBDO; + wire [1:0] DOPBDOP; + + assign A1DATA = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + generate if (CFG_DBITS > 8) begin + RAMB8BWER #( + .RAM_MODE("TDP"), + .DATA_WIDTH_A(CFG_DBITS), + .DATA_WIDTH_B(CFG_DBITS), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), + `include "brams_init_9.vh" + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO), + .DOPADOP(DOP), + .ADDRAWRADDR(A1ADDR_13), + .CLKAWRCLK(CLK2 ^ !CLKPOL2), + .ENAWREN(A1EN), + .REGCEA(|1), + .RSTA(|0), + .WEAWEL(2'b0), + + .DIBDI(DI), + .DIPBDIP(DIP), + .DOBDO(DOBDO), + .DOPBDOP(DOPBDOP), + .ADDRBRDADDR(B1ADDR_13), + .CLKBRDCLK(CLK3 ^ !CLKPOL3), + .ENBRDEN(|1), + .REGCEBREGCE(|0), + .RSTB(|0), + .WEBWEU(B1EN_2) + ); + end else begin + RAMB8BWER #( + .RAM_MODE("TDP"), + .DATA_WIDTH_A(CFG_DBITS), + .DATA_WIDTH_B(CFG_DBITS), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), + `include "brams_init_8.vh" + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO), + .DOPADOP(DOP), + .ADDRAWRADDR(A1ADDR_13), + .CLKAWRCLK(CLK2 ^ !CLKPOL2), + .ENAWREN(A1EN), + .REGCEA(|1), + .RSTA(|0), + .WEAWEL(2'b0), + + .DIBDI(DI), + .DIPBDIP(DIP), + .DOBDO(DOBDO), + .DOPBDOP(DOPBDOP), + .ADDRBRDADDR(B1ADDR_13), + .CLKBRDCLK(CLK3 ^ !CLKPOL3), + .ENBRDEN(|1), + .REGCEBREGCE(|0), + .RSTB(|0), + .WEBWEU(B1EN_2) + ); + end endgenerate +endmodule diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/xc7_brams.txt similarity index 100% rename from techlibs/xilinx/brams.txt rename to techlibs/xilinx/xc7_brams.txt diff --git a/techlibs/xilinx/brams_bb.v b/techlibs/xilinx/xc7_brams_bb.v similarity index 100% rename from techlibs/xilinx/brams_bb.v rename to techlibs/xilinx/xc7_brams_bb.v diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/xc7_brams_map.v similarity index 100% rename from techlibs/xilinx/brams_map.v rename to techlibs/xilinx/xc7_brams_map.v From c0abd187997a47282a12c869461f9d23dd397f5e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Jul 2019 08:49:06 -0700 Subject: [PATCH 866/927] Enable &mfs for abc9, even if it only currently works for ice40 --- 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 f107f9947..5f448e37a 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; &scorr; &sweep; &dc2; &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 a9efacd01da0feb85000ce62c2769c35eae43505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Thu, 11 Jul 2019 21:13:12 +0200 Subject: [PATCH 867/927] xilinx: Fix the default values for FDPE/FDSE INIT attributes to match ISE/Vivado. --- techlibs/xilinx/cells_sim.v | 4 ++-- techlibs/xilinx/ff_map.v | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3937d3536..05e46b4e7 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -226,7 +226,7 @@ module FDRE (output reg Q, input C, CE, D, R); endmodule module FDSE (output reg Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0; @@ -252,7 +252,7 @@ module FDCE (output reg Q, input C, CE, D, CLR); endmodule module FDPE (output reg Q, input C, CE, D, PRE); - parameter [0:0] INIT = 1'b0; + parameter [0:0] INIT = 1'b1; parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index 13beaa6ae..4571f6d5c 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -33,10 +33,10 @@ module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPL module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule -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 +module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|1)) _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(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule `endif From a8c5f7f41ec0c829c29ae425b0074eb33fa2a30c Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 11 Jul 2019 10:46:45 +0000 Subject: [PATCH 868/927] synth_ice40: fix help text typo. NFC. --- 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 2c75215cb..78c62213e 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -78,7 +78,7 @@ struct SynthIce40Pass : public ScriptPass log("\n"); log(" -dffe_min_ce_use \n"); log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n"); - log(" than min_ce_use SB_DFFE*in output netlist\n"); + log(" than min_ce_use SB_DFFE* in output netlist\n"); log("\n"); log(" -nobram\n"); log(" do not use SB_RAM40_4K* cells in output netlist\n"); From b700a4b1c5dd086874c7024edb10674cf3c3a7c4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 11 Jul 2019 10:46:30 +0000 Subject: [PATCH 869/927] synth_ice40: switch -relut to be always on. --- techlibs/ice40/synth_ice40.cc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 78c62213e..0474e76e9 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -67,9 +67,6 @@ struct SynthIce40Pass : public ScriptPass log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); - log(" -relut\n"); - log(" combine LUTs after synthesis\n"); - log("\n"); log(" -nocarry\n"); log(" do not use SB_CARRY cells in output netlist\n"); log("\n"); @@ -106,7 +103,7 @@ struct SynthIce40Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file, abc, device_opt; - bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr; + bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr; int min_ce_use; void clear_flags() YS_OVERRIDE @@ -122,7 +119,6 @@ struct SynthIce40Pass : public ScriptPass dsp = false; flatten = true; retime = false; - relut = false; noabc = false; abc2 = false; vpr = false; @@ -175,7 +171,7 @@ struct SynthIce40Pass : public ScriptPass continue; } if (args[argidx] == "-relut") { - relut = true; + // removed, opt_lut is always run continue; } if (args[argidx] == "-nocarry") { @@ -347,10 +343,8 @@ struct SynthIce40Pass : public ScriptPass run(abc + " -dress -lut 4", "(skip if -noabc)"); } run("clean"); - if (relut || help_mode) { - run("ice40_unlut", " (only if -relut)"); - run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)"); - } + run("ice40_unlut"); + run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3"); } if (check_label("map_cells")) From fc3d74616f284eaccdc7d105cd77572953602d7f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 00:50:42 -0700 Subject: [PATCH 870/927] Combine SB_CARRY+SB_LUT into one $__ICE40_CARRY_LUT4 box --- techlibs/ice40/abc_hx.box | 12 ++++-------- techlibs/ice40/abc_lp.box | 12 ++++-------- techlibs/ice40/abc_u.box | 14 +++++--------- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index f8e12b527..4b55297dd 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -3,15 +3,11 @@ # NB: Inputs/Outputs must be ordered alphabetically # (with exceptions for carry in/out) -# Inputs: I0 I1 CI -# Outputs: CO +# Inputs: A B CI +# Outputs: O CO # (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 +$__ICE40_CARRY_LUT4 1 1 3 2 +400 379 316 259 231 126 - -# Inputs: I0 I1 I2 I3 -# Outputs: O -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 fbe4c56e6..b85346370 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -3,15 +3,11 @@ # NB: Inputs/Outputs must be ordered alphabetically # (with exceptions for carry in/out) -# Inputs: CI I0 I1 -# Outputs: CO +# Inputs: A B CI +# Outputs: O CO # (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 +$__ICE40_CARRY_LUT4 1 1 3 2 +589 558 465 675 609 186 - -# Inputs: I0 I1 I2 I3 -# Outputs: O -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 f44deabc4..3a71addef 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -3,15 +3,11 @@ # NB: Inputs/Outputs must be ordered alphabetically # (with exceptions for carry in/out) -# Inputs: I0 I1 CI -# Outputs: CO +# Inputs: A B CI +# Outputs: O CO # (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 2 1 4 1 -1285 1231 1205 874 +$__ICE40_CARRY_LUT4 1 1 3 2 +1231 1205 875 +675 609 278 From c6e16e1334dcbd8bb556ab566130cc7936f06a69 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 00:51:37 -0700 Subject: [PATCH 871/927] _ABC macro will map and unmap to this new box --- techlibs/ice40/arith_map.v | 10 ++++++++++ techlibs/ice40/cells_map.v | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 4449fdc1b..6d45e4a6b 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -44,6 +44,15 @@ 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 +`ifdef _ABC + \$__ICE40_CARRY_LUT4 carry ( + .A(AA[i]), + .B(BB[i]), + .CI(C[i]), + .CO(CO[i]), + .O(Y[i]) + ); +`else SB_CARRY carry ( .I0(AA[i]), .I1(BB[i]), @@ -63,6 +72,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); .I3(C[i]), .O(Y[i]) ); +`endif end endgenerate assign X = AA ^ BB; diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 759549e30..5dca63e19 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -61,3 +61,27 @@ module \$lut (A, Y); endgenerate endmodule `endif + +`ifdef _ABC +module \$__ICE40_CARRY_LUT4 (output CO, O, input A, B, CI); + SB_CARRY carry ( + .I0(A), + .I1(B), + .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(A), + .I2(B), + .I3(CI), + .O(O) + ); +endmodule +`endif From a79ff2501e7b73b4af958d23d247951b107bb054 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 00:52:19 -0700 Subject: [PATCH 872/927] Add new box to cells_sim.v --- techlibs/ice40/cells_sim.v | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index b746ba4e5..cf36f5cfb 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -127,7 +127,7 @@ endmodule // SiliconBlue Logic Cells -(* abc_box_id = 2, lib_whitebox *) +(* 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,11 +136,34 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); assign O = I0 ? s1[1] : s1[0]; endmodule -(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *) +(* lib_whitebox *) module SB_CARRY (output CO, input I0, I1, CI); assign CO = (I0 && I1) || ((I0 || I1) && CI); endmodule +(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *) +module \$__ICE40_CARRY_LUT4 (output CO, O, input A, B, CI); + SB_CARRY carry ( + .I0(A), + .I1(B), + .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(A), + .I2(B), + .I3(CI), + .O(O) + ); +endmodule + // Positive Edge SiliconBlue FF Cells module SB_DFF (output `SB_DFF_REG, input C, D); From 0f5bddcd792ed2da2b9a3eb12e775537f394e771 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 00:52:31 -0700 Subject: [PATCH 873/927] ice40_opt to handle this box and opt back to SB_LUT4 --- techlibs/ice40/ice40_opt.cc | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index f528607d6..b22fc83fe 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -83,6 +83,54 @@ static void run_ice40_opts(Module *module) } continue; } + + if (cell->type == "$__ICE40_CARRY_LUT4") + { + SigSpec non_const_inputs, replacement_output; + int count_zeros = 0, count_ones = 0; + + SigBit inbit[3] = { + cell->getPort("\\A"), + cell->getPort("\\B"), + cell->getPort("\\CI") + }; + for (int i = 0; i < 3; i++) + if (inbit[i].wire == nullptr) { + if (inbit[i] == State::S1) + count_ones++; + else + count_zeros++; + } else + non_const_inputs.append(inbit[i]); + + if (count_zeros >= 2) + replacement_output = State::S0; + else if (count_ones >= 2) + replacement_output = State::S1; + else if (GetSize(non_const_inputs) == 1) + replacement_output = non_const_inputs; + + if (GetSize(replacement_output)) { + optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); + module->connect(cell->getPort("\\CO")[0], replacement_output); + module->design->scratchpad_set_bool("opt.did_something", true); + log("Optimized SB_CARRY from $__ICE40_CARRY_LUT4 cell (leaving behind SB_LUT4) %s.%s: CO=%s\n", + log_id(module), log_id(cell), log_signal(replacement_output)); + cell->type = "\\SB_LUT4"; + sb_lut_cells.push_back(cell); + cell->setPort("\\I0", RTLIL::S0); + cell->setPort("\\I1", inbit[0]); + cell->setPort("\\I2", inbit[1]); + cell->setPort("\\I3", inbit[2]); + cell->unsetPort("\\A"); + cell->unsetPort("\\B"); + cell->unsetPort("\\CI"); + cell->unsetPort("\\CO"); + cell->setParam("\\LUT_INIT", std::string("0110100110010110")); + sb_lut_cells.push_back(cell); + } + continue; + } } for (auto cell : sb_lut_cells) From 62ac5ebd02e18add18a11f4c19002f4059b091b7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 00:53:01 -0700 Subject: [PATCH 874/927] Map to and from this box if -abc9 --- techlibs/ice40/synth_ice40.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 2c75215cb..59f6d1863 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -242,7 +242,7 @@ struct SynthIce40Pass : public ScriptPass { if (check_label("begin")) { - run("read_verilog -lib -D_ABC +/ice40/cells_sim.v"); + run("read_verilog -icells -lib -D_ABC +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); run("proc"); } @@ -298,7 +298,7 @@ struct SynthIce40Pass : public ScriptPass if (nocarry) run("techmap"); else - run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); + run("techmap -map +/techmap.v -map +/ice40/arith_map.v" + std::string(abc == "abc9" ? " -D _ABC" : "")); if (retime || help_mode) run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); @@ -342,6 +342,7 @@ struct SynthIce40Pass : public ScriptPass 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)"); + run("techmap -D NO_LUT -D _ABC -map +/ice40/cells_map.v"); } else run(abc + " -dress -lut 4", "(skip if -noabc)"); From 4de03bd5e6cd72b3eb2a70d5735e7526d7a6f8a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 01:08:48 -0700 Subject: [PATCH 875/927] Remove double push --- techlibs/ice40/ice40_opt.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index b22fc83fe..4e50b250e 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -117,7 +117,6 @@ static void run_ice40_opts(Module *module) log("Optimized SB_CARRY from $__ICE40_CARRY_LUT4 cell (leaving behind SB_LUT4) %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); cell->type = "\\SB_LUT4"; - sb_lut_cells.push_back(cell); cell->setPort("\\I0", RTLIL::S0); cell->setPort("\\I1", inbit[0]); cell->setPort("\\I2", inbit[1]); From e0e5d7d68eee0d1a83b048d9d9fde94673ff5673 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 01:15:22 -0700 Subject: [PATCH 876/927] Fix spacing --- techlibs/ice40/arith_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 6d45e4a6b..abba18c37 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -50,7 +50,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO); .B(BB[i]), .CI(C[i]), .CO(CO[i]), - .O(Y[i]) + .O(Y[i]) ); `else SB_CARRY carry ( From 28274dfb09fb48637f82949ce601a417eb3d0b82 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 01:17:53 -0700 Subject: [PATCH 877/927] Off by one --- techlibs/ice40/abc_u.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 3a71addef..95c2c3d81 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -9,5 +9,5 @@ # input/output and have been moved there # overriding the alphabetical ordering) $__ICE40_CARRY_LUT4 1 1 3 2 -1231 1205 875 +1231 1205 874 675 609 278 From 7a912f22b2c3976d72a25ffd605a1cf598b67983 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 01:32:10 -0700 Subject: [PATCH 878/927] Use Const::from_string() not its constructor... --- techlibs/ice40/ice40_opt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index 4e50b250e..67e8771b4 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -125,7 +125,7 @@ static void run_ice40_opts(Module *module) cell->unsetPort("\\B"); cell->unsetPort("\\CI"); cell->unsetPort("\\CO"); - cell->setParam("\\LUT_INIT", std::string("0110100110010110")); + cell->setParam("\\LUT_INIT", RTLIL::Const::from_string("0110100110010110")); sb_lut_cells.push_back(cell); } continue; From 7dc15bdd2dff8493ee5786845a5e39427bf3779d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 08:22:26 -0700 Subject: [PATCH 879/927] Do not double count cells in abc --- passes/techmap/abc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 15e79f9d1..65c7d1bb8 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1172,8 +1172,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin 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; From 58dbb28fd3e1176d9f8a1355897cf4b56b7b46b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:29:04 -0700 Subject: [PATCH 880/927] Cleanup --- passes/techmap/abc9.cc | 122 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 13 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5f448e37a..224a2d504 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -24,12 +24,14 @@ #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" +#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ + "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps -l; &if {W} {D} -v; &mfs; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs -b; &ps -l" +//#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &put -v; dch -f; if {W} {D} -vo; mfs2; &get -vm; &ps -l" #endif @@ -570,13 +572,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } + std::vector> not_gates; + dict> bit2sinks; std::map cell_stats; for (auto c : mapped_mod->cells()) { RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { - RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); - RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); + RTLIL::SigBit a_bit = c->getPort("\\A"); + RTLIL::SigBit y_bit = c->getPort("\\Y"); if (!a_bit.wire) { c->setPort("\\Y", module->addWire(NEW_ID)); RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); @@ -600,14 +604,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } if (!driving_lut) { - // If a driver couldn't be found (could be from PI, - // or from a box) then implement using a LUT + // If a driver couldn't be found (could be from PI or box CI) + // 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); + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort("\\A")].push_back(cell); } else { +#if 0 auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; @@ -620,6 +626,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri driver_a, RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); +#elif 0 + 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), + RTLIL::Const::from_string("01")); + +#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)); + not_gates.emplace_back(cell, driving_lut); +#endif + cell_stats[RTLIL::unescape_id(c->type)]++; } } else { @@ -627,19 +646,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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)]++; + log_abort(); } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; - RTLIL::Cell *existing_cell = nullptr; + RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { - if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { + if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) { 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; + if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; + log_abort(); continue; } cell = module->addCell(remap_name(c->name), c->type); @@ -670,6 +691,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri newsig.append(c); } cell->setPort(conn.first, newsig); + + if (cell->input(conn.first)) + for (auto i : newsig) + bit2sinks[i].push_back(cell); } } @@ -725,6 +750,77 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + for (auto i : not_gates) { + RTLIL::Cell *not_cell = i.first; + auto driving_lut = i.second; + log_assert(driving_lut); + RTLIL::SigBit a_bit = not_cell->getPort("\\A"); + RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); + driving_lut = module->cell(remap_name(driving_lut->name)); + log_assert(driving_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; + } + + auto it = bit2sinks.find(a_bit); + if (it == bit2sinks.end()) + goto duplicate_lut; + + for (auto sink_cell : it->second) + if (sink_cell->type != "$lut") + goto duplicate_lut; + + //static int count = 0; + //log_warning("%d\n", count); + //if (count++ >= 41) + // goto duplicate_lut; + + for (auto sink_cell : it->second) { + SigSpec A = sink_cell->getPort("\\A"); + RTLIL::Const mask = sink_cell->getParam("\\LUT"); + int index = 0; + for (; index < GetSize(A); index++) + if (A[index] == a_bit) + break; + log_assert(index < GetSize(A)); + int i = 0; + while (i < GetSize(mask)) { + for (int j = 0; j < (1 << index); j++) + std::swap(mask[i+j], mask[i+j+(1 << index)]); + i += 1 << (index+1); + } + A[index] = y_bit; + sink_cell->setPort("\\A", A); + sink_cell->setParam("\\LUT", mask); + } + + // FIXME: Since we have rewritten all sink_LUTs, + // we should be able to continue here + // and expect the $_NOT_ gate to be optimised + // away as it will have no sinks... + //continue; + +duplicate_lut: + auto not_cell_name = not_cell->name; + module->remove(not_cell); +#if 0 + auto driver_a = driving_lut->getPort("\\A").chunks(); + for (auto &chunk : driver_a) + chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + module->addLut(not_cell_name, + driver_a, + y_bit, + driver_lut); +#else + module->addLut(not_cell_name, + a_bit, + y_bit, + RTLIL::Const::from_string("01")); +#endif + } + //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 399e1ec87033d44d8d9e55b6a15a06e4412eb81a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:31:02 -0700 Subject: [PATCH 881/927] Cleanup --- passes/techmap/abc9.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 224a2d504..f6592098b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -756,7 +756,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_assert(driving_lut); RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - driving_lut = module->cell(remap_name(driving_lut->name)); log_assert(driving_lut); RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); for (auto &b : driver_lut.bits) { @@ -772,11 +771,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (sink_cell->type != "$lut") goto duplicate_lut; - //static int count = 0; - //log_warning("%d\n", count); - //if (count++ >= 41) - // goto duplicate_lut; - for (auto sink_cell : it->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); @@ -805,7 +799,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri duplicate_lut: auto not_cell_name = not_cell->name; module->remove(not_cell); -#if 0 +#if 1 auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; From 91c07be196c71cc172834dcbddd30f5944972b41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:41:06 -0700 Subject: [PATCH 882/927] Cleanup --- passes/techmap/abc9.cc | 62 +++++++++++------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f6592098b..cdad38c9e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -572,7 +572,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } - std::vector> not_gates; + std::vector> push_inverters; dict> bit2sinks; std::map cell_stats; for (auto c : mapped_mod->cells()) @@ -613,32 +613,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bit2sinks[cell->getPort("\\A")].push_back(cell); } else { -#if 0 - 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); -#elif 0 - 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), - RTLIL::Const::from_string("01")); - -#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)); - not_gates.emplace_back(cell, driving_lut); -#endif - cell_stats[RTLIL::unescape_id(c->type)]++; + push_inverters.emplace_back(c, driving_lut); + continue; } } else { @@ -649,6 +625,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_abort(); } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + cell_stats[RTLIL::unescape_id(c->type)]++; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; @@ -750,18 +727,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto i : not_gates) { + for (auto i : push_inverters) { RTLIL::Cell *not_cell = i.first; - auto driving_lut = i.second; - log_assert(driving_lut); + RTLIL::Cell *driving_lut = i.second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - log_assert(driving_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; - } + + a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); + y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); auto it = bit2sinks.find(a_bit); if (it == bit2sinks.end()) @@ -797,22 +770,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //continue; duplicate_lut: - auto not_cell_name = not_cell->name; - module->remove(not_cell); -#if 1 + 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; + } auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - module->addLut(not_cell_name, + module->addLut(remap_name(not_cell->name), driver_a, y_bit, driver_lut); -#else - module->addLut(not_cell_name, - a_bit, - y_bit, - RTLIL::Const::from_string("01")); -#endif + //mapped_mod->remove(not_cell); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 39a7c7c54c1845ee4d13c33745085318a9a44b96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:43:39 -0700 Subject: [PATCH 883/927] More cleanup --- passes/techmap/abc9.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index cdad38c9e..2b4a5cdba 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -607,8 +607,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // If a driver couldn't be found (could be from PI or box CI) // 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), + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), RTLIL::Const::from_string("01")); bit2sinks[cell->getPort("\\A")].push_back(cell); } @@ -619,8 +619,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } 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->setPort("\\A", RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset)); + cell->setPort("\\Y", RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset)); cell_stats[RTLIL::unescape_id(c->type)]++; log_abort(); } @@ -633,8 +633,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) { - 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)]; + SigSpec my_a = module->wires_.at(remap_name(c->getPort("\\A").as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort("\\Y").as_wire()->name)); module->connect(my_y, my_a); if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; log_abort(); @@ -664,7 +664,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; //log_assert(c.width == 1); if (c.wire) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); newsig.append(c); } cell->setPort(conn.first, newsig); @@ -683,14 +683,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!conn.first.is_fully_const()) { auto chunks = conn.first.chunks(); for (auto &c : chunks) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); conn.first = std::move(chunks); } if (!conn.second.is_fully_const()) { auto chunks = conn.second.chunks(); for (auto &c : chunks) if (c.wire) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); conn.second = std::move(chunks); } module->connect(conn); @@ -777,12 +777,11 @@ duplicate_lut: } auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) - chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); module->addLut(remap_name(not_cell->name), driver_a, y_bit, driver_lut); - //mapped_mod->remove(not_cell); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 1adbfb55338fdb29eae638f988ae361b9e401d8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 16:01:11 -0700 Subject: [PATCH 884/927] Cleanup --- passes/techmap/abc9.cc | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2b4a5cdba..5da5efcdc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -588,11 +588,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1); } else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driving_lut = nullptr; + RTLIL::Cell* driver_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 + // find the driver 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; @@ -600,10 +600,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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); + driver_lut = mapped_mod->cell(driver_name); } - if (!driving_lut) { + if (!driver_lut) { // If a driver couldn't be found (could be from PI or box CI) // then implement using a LUT cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), @@ -613,7 +613,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bit2sinks[cell->getPort("\\A")].push_back(cell); } else { - push_inverters.emplace_back(c, driving_lut); + push_inverters.emplace_back(c, driver_lut); continue; } } @@ -729,13 +729,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto i : push_inverters) { RTLIL::Cell *not_cell = i.first; - RTLIL::Cell *driving_lut = i.second; + RTLIL::Cell *driver_lut = i.second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); + RTLIL::Const driver_mask = driver_lut->getParam("\\LUT"); a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + for (auto &b : driver_mask.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + auto it = bit2sinks.find(a_bit); if (it == bit2sinks.end()) goto duplicate_lut; @@ -744,6 +750,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (sink_cell->type != "$lut") goto duplicate_lut; + // Push downstream LUTs past inverter for (auto sink_cell : it->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); @@ -763,25 +770,27 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } - // FIXME: Since we have rewritten all sink_LUTs, - // we should be able to continue here - // and expect the $_NOT_ gate to be optimised - // away as it will have no sinks... + // FIXME: Since we have rewritten all sinks + // (which we know to be only LUTs) + // to be after the inverter, we can now + // merge the inverter into the driving LUT + // and let the (now dangling) $_NOT_ cell + // from mapped_mod get cleaned away + //driver_lut->setParam("\\INIT", driver_mask); + //driver_lut->setPort("\\Y", y_bit); //continue; - duplicate_lut: - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { + for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - auto driver_a = driving_lut->getPort("\\A").chunks(); + auto driver_a = driver_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); module->addLut(remap_name(not_cell->name), driver_a, y_bit, - driver_lut); + driver_mask); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 83f23a24a880fb3cd40ea16b478540bdbdfe597c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 16:06:14 -0700 Subject: [PATCH 885/927] Cleanup --- passes/techmap/abc9.cc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5da5efcdc..867b06cbe 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -611,21 +611,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), RTLIL::Const::from_string("01")); bit2sinks[cell->getPort("\\A")].push_back(cell); + cell_stats["$lut"]++; } - else { + else push_inverters.emplace_back(c, driver_lut); - continue; - } + continue; } - else { - cell = module->addCell(remap_name(c->name), "$_NOT_"); - cell->setPort("\\A", RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset)); - cell->setPort("\\Y", RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset)); - cell_stats[RTLIL::unescape_id(c->type)]++; + else log_abort(); - } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - cell_stats[RTLIL::unescape_id(c->type)]++; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; From 7d583f9e57dc3feb7e525c5ad120b1ba3959fdcd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:17:32 -0700 Subject: [PATCH 886/927] Cleanup --- passes/techmap/abc9.cc | 82 ++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 867b06cbe..7b1c9f815 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -55,6 +55,7 @@ #endif #include "frontends/aiger/aigerparse.h" +#include "kernel/utils.h" #ifdef YOSYS_LINK_ABC extern "C" int Abc_RealMain(int argc, char *argv[]); @@ -572,15 +573,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } - std::vector> push_inverters; + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; dict> bit2sinks; + std::map cell_stats; for (auto c : mapped_mod->cells()) { + toposort.node(c->name); + RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { RTLIL::SigBit a_bit = c->getPort("\\A"); RTLIL::SigBit y_bit = c->getPort("\\Y"); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + if (!a_bit.wire) { c->setPort("\\Y", module->addWire(NEW_ID)); RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); @@ -614,7 +623,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell_stats["$lut"]++; } else - push_inverters.emplace_back(c, driver_lut); + not2drivers[c] = driver_lut; continue; } else @@ -663,9 +672,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell->setPort(conn.first, newsig); - if (cell->input(conn.first)) + if (cell->input(conn.first)) { for (auto i : newsig) bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(c->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(c->name); } } @@ -721,31 +736,45 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto i : push_inverters) { - RTLIL::Cell *not_cell = i.first; - RTLIL::Cell *driver_lut = i.second; + 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); + bool no_loops = toposort.sort(); + log_assert(no_loops); + + for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { + RTLIL::Cell *not_cell = mapped_mod->cell(*ii); + log_assert(not_cell); + if (not_cell->type != "$_NOT_") + continue; + auto it = not2drivers.find(not_cell); + if (it == not2drivers.end()) + continue; + RTLIL::Cell *driver_lut = it->second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - RTLIL::Const driver_mask = driver_lut->getParam("\\LUT"); + RTLIL::Const driver_mask; + RTLIL::Wire *orig_a_bit_wire = a_bit.wire; + decltype(bit2sinks)::const_iterator jt; a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - for (auto &b : driver_mask.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - - auto it = bit2sinks.find(a_bit); - if (it == bit2sinks.end()) + if (orig_a_bit_wire->port_output) goto duplicate_lut; - for (auto sink_cell : it->second) + jt = bit2sinks.find(a_bit); + if (jt == bit2sinks.end()) + goto duplicate_lut; + + for (auto sink_cell : jt->second) if (sink_cell->type != "$lut") goto duplicate_lut; // Push downstream LUTs past inverter - for (auto sink_cell : it->second) { + for (auto sink_cell : jt->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); int index = 0; @@ -764,27 +793,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } - // FIXME: Since we have rewritten all sinks - // (which we know to be only LUTs) - // to be after the inverter, we can now - // merge the inverter into the driving LUT - // and let the (now dangling) $_NOT_ cell - // from mapped_mod get cleaned away - //driver_lut->setParam("\\INIT", driver_mask); - //driver_lut->setPort("\\Y", y_bit); - //continue; duplicate_lut: + driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - auto driver_a = driver_lut->getPort("\\A").chunks(); - for (auto &chunk : driver_a) - chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); - module->addLut(remap_name(not_cell->name), - driver_a, + auto cell = module->addLut(NEW_ID, + driver_lut->getPort("\\A"), y_bit, driver_mask); + for (auto &bit : cell->connections_.at("\\A")) { + bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit2sinks[bit].push_back(cell); + } } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From be0cb7f4b81af91ce47a8baf57d0aff716eecddc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:21:03 -0700 Subject: [PATCH 887/927] More cleanup --- passes/techmap/abc9.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 7b1c9f815..36f2fafc3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,8 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs -b; &ps -l" -//#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &put -v; dch -f; if {W} {D} -vo; mfs2; &get -vm; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" #endif @@ -756,16 +755,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); RTLIL::Const driver_mask; - RTLIL::Wire *orig_a_bit_wire = a_bit.wire; - decltype(bit2sinks)::const_iterator jt; a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - if (orig_a_bit_wire->port_output) - goto duplicate_lut; - - jt = bit2sinks.find(a_bit); + auto jt = bit2sinks.find(a_bit); if (jt == bit2sinks.end()) goto duplicate_lut; From e9bdc86c0e0ea41d1ee8a610b7f1304c3eaf43e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:33:02 -0700 Subject: [PATCH 888/927] duplicate -> clone --- 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 36f2fafc3..4a6ec3a47 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -761,11 +761,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri auto jt = bit2sinks.find(a_bit); if (jt == bit2sinks.end()) - goto duplicate_lut; + goto clone_lut; for (auto sink_cell : jt->second) if (sink_cell->type != "$lut") - goto duplicate_lut; + goto clone_lut; // Push downstream LUTs past inverter for (auto sink_cell : jt->second) { @@ -787,7 +787,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } -duplicate_lut: +clone_lut: driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; From 41243a53b384a9ecfadd7b424c9e22c7c84fb721 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 21:00:13 -0700 Subject: [PATCH 889/927] Update test with more accurate LUT mask --- tests/various/abc9.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index a84b637d9..5c9a4075d 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -19,6 +19,6 @@ hierarchy -top abc9_test028 proc abc9 -lut 4 -select -assert-count 1 t:$lut r:LUT=1 r:WIDTH=1 %i %i +select -assert-count 1 t:$lut r:LUT=2'b01 r:WIDTH=1 %i %i select -assert-count 1 t:unknown select -assert-none t:$lut t:unknown %% t: %D From fb062c3426e8acb5b3f54dfed7209631208fec81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 13 Jul 2019 00:52:21 -0700 Subject: [PATCH 890/927] Add comment --- passes/techmap/abc9.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 4a6ec3a47..658bb1225 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -787,6 +787,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } + // Since we have rewritten all sinks (which we know + // to be only LUTs) to be after the inverter, we can + // go ahead and clone the LUT with the expectation + // that the original driving LUT will become dangling + // and get cleaned away clone_lut: driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) { From d032198facc05634bd617328e1865e7f0d8d953c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 13 Jul 2019 01:11:00 -0700 Subject: [PATCH 891/927] ice40_opt to $__ICE40_CARRY_LUT4 into $lut not SB_LUT --- techlibs/ice40/ice40_opt.cc | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index 67e8771b4..38910dffa 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -114,19 +114,17 @@ static void run_ice40_opts(Module *module) optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); module->connect(cell->getPort("\\CO")[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); - log("Optimized SB_CARRY from $__ICE40_CARRY_LUT4 cell (leaving behind SB_LUT4) %s.%s: CO=%s\n", + log("Optimized $__ICE40_CARRY_LUT4 cell into $lut (without SB_CARRY) %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); - cell->type = "\\SB_LUT4"; - cell->setPort("\\I0", RTLIL::S0); - cell->setPort("\\I1", inbit[0]); - cell->setPort("\\I2", inbit[1]); - cell->setPort("\\I3", inbit[2]); - cell->unsetPort("\\A"); + cell->type = "$lut"; + cell->setPort("\\A", { RTLIL::S0, inbit[0], inbit[1], inbit[2] }); + cell->setPort("\\Y", cell->getPort("\\O")); cell->unsetPort("\\B"); cell->unsetPort("\\CI"); cell->unsetPort("\\CO"); - cell->setParam("\\LUT_INIT", RTLIL::Const::from_string("0110100110010110")); - sb_lut_cells.push_back(cell); + cell->unsetPort("\\O"); + cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110")); + cell->setParam("\\WIDTH", 4); } continue; } From ab3917d0791874bab845ca74203c5aaa2ec842d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 13 Jul 2019 03:39:23 -0700 Subject: [PATCH 892/927] Error out if enable > dbits --- passes/memory/memory_bram.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index ddc56d9b5..aa8f94149 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -68,6 +68,10 @@ struct rules_t if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp)); if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks)); if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol)); + + int group = 0; + for (auto e : enable) + if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", log_id(name), variant, group, e, dbits); } vector make_portinfos() const From 9b91d815b55343630c3c2d4a5a7d2a593c344f07 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 13 Jul 2019 04:13:57 -0700 Subject: [PATCH 893/927] If ConstEval fails do not log_abort() but return gracefully --- passes/techmap/extract_fa.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc index 9e6dc0d24..8de57e769 100644 --- a/passes/techmap/extract_fa.cc +++ b/passes/techmap/extract_fa.cc @@ -174,8 +174,10 @@ struct ExtractFaWorker SigSpec sig = root; - if (!ce.eval(sig)) - log_abort(); + if (ce.eval(sig)) { + ce.pop(); + return; + } if (sig == State::S1) func |= 1 << i; @@ -214,8 +216,10 @@ struct ExtractFaWorker SigSpec sig = root; - if (!ce.eval(sig)) - log_abort(); + if (ce.eval(sig)) { + ce.pop(); + return; + } if (sig == State::S1) func |= 1 << i; From 2de7e92bb847edef65f418c9034709649f6c1185 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 13 Jul 2019 16:49:56 +0000 Subject: [PATCH 894/927] opt_lut: make less chatty. --- passes/opt/opt_lut.cc | 94 +++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 56 deletions(-) diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 26855fd70..182f63d99 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -105,7 +105,7 @@ struct OptLutWorker SigSpec lut_input = cell->getPort("\\A"); int lut_arity = 0; - log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); luts.insert(cell); // First, find all dedicated logic we're connected to. This results in an overapproximation @@ -147,15 +147,15 @@ struct OptLutWorker { if (lut_width <= dlogic_conn.first) { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] not present.\n", dlogic_conn.first); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; } if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second))) { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); legal = false; break; } @@ -163,7 +163,7 @@ struct OptLutWorker if (legal) { - log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -179,7 +179,7 @@ struct OptLutWorker lut_arity++; } - log(" Cell implements a %d-LUT.\n", lut_arity); + log_debug(" Cell implements a %d-LUT.\n", lut_arity); luts_arity[cell] = lut_arity; luts_dlogics[cell] = lut_legal_dlogics; luts_dlogic_inputs[cell] = lut_dlogic_inputs; @@ -239,28 +239,26 @@ struct OptLutWorker if (const0_match || const1_match || input_match != -1) { - log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); + log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); SigBit value; if (const0_match) { - log(" Cell evaluates constant 0.\n"); + log_debug(" Cell evaluates constant 0.\n"); value = State::S0; } if (const1_match) { - log(" Cell evaluates constant 1.\n"); + log_debug(" Cell evaluates constant 1.\n"); value = State::S1; } if (input_match != -1) { - log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match])); + log_debug(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match])); value = lut_inputs[input_match]; } if (lut_dlogic_inputs.size()) - { - log(" Not eliminating cell (connected to dedicated logic).\n"); - } + log_debug(" Not eliminating cell (connected to dedicated logic).\n"); else { SigSpec lut_output = lut->getPort("\\Y"); @@ -323,11 +321,11 @@ struct OptLutWorker int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; - log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); if (index.query_is_output(lutA->getPort("\\Y"))) { - log(" Not combining LUTs (cascade connection feeds module output).\n"); + log_debug(" Not combining LUTs (cascade connection feeds module output).\n"); continue; } @@ -353,67 +351,51 @@ struct OptLutWorker int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); if (lutA_dlogic_inputs.size()) - log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); + log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); else - log(" Cell A is a %d-LUT. ", lutA_arity); + log_debug(" Cell A is a %d-LUT. ", lutA_arity); if (lutB_dlogic_inputs.size()) - log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); + log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); else - log("Cell B is a %d-LUT.\n", lutB_arity); - log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); + log_debug("Cell B is a %d-LUT.\n", lutB_arity); + log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; int combine_mask = 0; if (lutM_arity > lutA_width) - { - log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); - } + log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); else if (lutB_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); - } + log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); else if (lutB->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); - } + log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); else - { combine_mask |= COMBINE_A; - } if (lutM_arity > lutB_width) - { - log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); - } + log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); else if (lutA_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); - } + log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); else if (lutA->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); - } + log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); else - { combine_mask |= COMBINE_B; - } int combine = combine_mask; if (combine == COMBINE_EITHER) { - log(" Can combine into either cell.\n"); + log_debug(" Can combine into either cell.\n"); if (lutA_arity == 1) { - log(" Cell A is a buffer or inverter, combining into cell B.\n"); + log_debug(" Cell A is a buffer or inverter, combining into cell B.\n"); combine = COMBINE_B; } else if (lutB_arity == 1) { - log(" Cell B is a buffer or inverter, combining into cell A.\n"); + log_debug(" Cell B is a buffer or inverter, combining into cell A.\n"); combine = COMBINE_A; } else { - log(" Arbitrarily combining into cell A.\n"); + log_debug(" Arbitrarily combining into cell A.\n"); combine = COMBINE_A; } } @@ -423,7 +405,7 @@ struct OptLutWorker pool lutM_dlogic_inputs; if (combine == COMBINE_A) { - log(" Combining LUTs into cell A.\n"); + log_debug(" Combining LUTs into cell A.\n"); lutM = lutA; lutM_inputs = lutA_inputs; lutM_dlogic_inputs = lutA_dlogic_inputs; @@ -432,7 +414,7 @@ struct OptLutWorker } else if (combine == COMBINE_B) { - log(" Combining LUTs into cell B.\n"); + log_debug(" Combining LUTs into cell B.\n"); lutM = lutB; lutM_inputs = lutB_inputs; lutM_dlogic_inputs = lutB_dlogic_inputs; @@ -441,7 +423,7 @@ struct OptLutWorker } else { - log(" Cannot combine LUTs.\n"); + log_debug(" Cannot combine LUTs.\n"); continue; } @@ -466,17 +448,17 @@ struct OptLutWorker if (input_unused && lutR_unique.size()) { SigBit new_input = lutR_unique.pop(); - log(" Connecting input %d as %s.\n", i, log_signal(new_input)); + log_debug(" Connecting input %d as %s.\n", i, log_signal(new_input)); lutM_new_inputs.push_back(new_input); } else if (sigmap(lutM_input[i]) == lutA_output) { - log(" Disconnecting cascade input %d.\n", i); + log_debug(" Disconnecting cascade input %d.\n", i); lutM_new_inputs.push_back(SigBit()); } else { - log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); + log_debug(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); lutM_new_inputs.push_back(lutM_input[i]); } } @@ -494,9 +476,9 @@ struct OptLutWorker lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - log(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); - log(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); - log(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); + log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); lutM->setParam("\\LUT", lutM_new_table); lutM->setPort("\\A", lutM_new_inputs); From f7ab7a418cac110834fb7c8b89e29cb4d9a2a1fb Mon Sep 17 00:00:00 2001 From: Roman-Parise Date: Sun, 14 Jul 2019 09:25:07 -0700 Subject: [PATCH 895/927] Updated FreeBSD dependencies in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42f972c8e..9e221be38 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies On FreeBSD use the following command to install all prerequisites: # pkg install bison flex readline gawk libffi\ - git graphviz pkgconfig python3 python36 tcl-wrapper boost-libs + git graphviz pkgconf python3 python36 tcl-wrapper boost-libs On FreeBSD system use gmake instead of make. To run tests use: % MAKE=gmake CC=cc gmake test From da5d64d71e27a1ee182f7c50f240e0adc91a5a07 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 14 Jul 2019 11:57:08 -0400 Subject: [PATCH 896/927] Fix missing semicolon in Windows-specific code in aigerparse.cc. Signed-off-by: William D. Jones --- frontends/aiger/aigerparse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 1ac0f7ba4..03c541b7c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -1062,8 +1062,8 @@ struct AigerFrontend : public Frontend { if (module_name.empty()) { #ifdef _WIN32 char fname[_MAX_FNAME]; - _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */) - module_name = fname; + _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */); + module_name = fname; #else char* bn = strdup(filename.c_str()); module_name = RTLIL::escape_id(bn); From 0e6c83027f24cdf7082606a5631468ad28f41574 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 15 Jul 2019 12:12:21 +0200 Subject: [PATCH 897/927] Add log_checkpoint function and use it in opt_muxtree Signed-off-by: Clifford Wolf --- kernel/log.cc | 7 +++++++ kernel/log.h | 1 + passes/opt/opt_muxtree.cc | 1 + 3 files changed, 9 insertions(+) diff --git a/kernel/log.cc b/kernel/log.cc index a7820950c..1a2c89a9c 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -420,6 +420,13 @@ void log_pop() log_flush(); } +void log_checkpoint() +{ + log_id_cache.clear(); + IdString::checkpoint(); + log_flush(); +} + #if (defined(__linux__) || defined(__FreeBSD__)) && defined(YOSYS_ENABLE_PLUGINS) void log_backtrace(const char *prefix, int levels) { diff --git a/kernel/log.h b/kernel/log.h index 3e1facae8..3328018f3 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -130,6 +130,7 @@ void log_spacer(); void log_push(); void log_pop(); +void log_checkpoint(); void log_backtrace(const char *prefix, int levels); void log_reset_stack(); void log_flush(); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 6511e091b..79f0e9639 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -204,6 +204,7 @@ struct OptMuxtreeWorker log(" Analyzing evaluation results.\n"); log_assert(glob_abort_cnt > 0); + log_checkpoint(); for (auto &mi : mux2info) { From 44fd459c799e393d13d664102cf381264c80649f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 15 Jul 2019 17:10:42 +0200 Subject: [PATCH 898/927] Redesign log_id_cache so that it doesn't keep IdString instances referenced, fixes #1178 Signed-off-by: Clifford Wolf --- kernel/log.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 1a2c89a9c..08ebe7af7 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -61,7 +61,7 @@ int log_force_debug = 0; int log_debug_suppressed = 0; vector header_count; -pool log_id_cache; +vector log_id_cache; vector string_buf; int string_buf_index = -1; @@ -69,6 +69,13 @@ static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; static int log_newline_count = 0; +static void log_id_cache_clear() +{ + for (auto p : log_id_cache) + free(p); + log_id_cache.clear(); +} + #if defined(_WIN32) && !defined(__MINGW32__) // this will get time information and return it in timeval, simulating gettimeofday() int gettimeofday(struct timeval *tv, struct timezone *tz) @@ -414,7 +421,7 @@ void log_push() void log_pop() { header_count.pop_back(); - log_id_cache.clear(); + log_id_cache_clear(); string_buf.clear(); string_buf_index = -1; log_flush(); @@ -422,7 +429,7 @@ void log_pop() void log_checkpoint() { - log_id_cache.clear(); + log_id_cache_clear(); IdString::checkpoint(); log_flush(); } @@ -528,7 +535,7 @@ void log_reset_stack() { while (header_count.size() > 1) header_count.pop_back(); - log_id_cache.clear(); + log_id_cache_clear(); string_buf.clear(); string_buf_index = -1; log_flush(); @@ -587,8 +594,8 @@ const char *log_const(const RTLIL::Const &value, bool autoint) const char *log_id(RTLIL::IdString str) { - log_id_cache.insert(str); - const char *p = str.c_str(); + log_id_cache.push_back(strdup(str.c_str())); + const char *p = log_id_cache.back(); if (p[0] != '\\') return p; if (p[1] == '$' || p[1] == '\\' || p[1] == 0) From 78560aac86b763306798192aa375ed04a5b192a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 08:31:26 -0700 Subject: [PATCH 899/927] Revert "Fix first divergence in #1178" This reverts commit 1122a2e0671ed00b7c03658f5012e34df12f26de. --- passes/opt/wreduce.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 65068238b..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -430,7 +430,6 @@ struct WreduceWorker for (auto w : module->wires()) complete_wires.insert(mi.sigmap(w)); - std::vector> swap_wire_names; for (auto w : module->selected_wires()) { int unused_top_bits = 0; @@ -455,12 +454,9 @@ struct WreduceWorker log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w)); Wire *nw = module->addWire(NEW_ID, GetSize(w) - unused_top_bits); module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); - swap_wire_names.emplace_back(w, nw); + module->swap_names(w, nw); } - for (const auto &i : swap_wire_names) - module->swap_names(i.first, i.second); - if (!remove_init_bits.empty()) { for (auto w : module->wires()) { if (w->attributes.count("\\init")) { From ab4b9e8db481cd24b61cc0dc14bb5bf74d08006d Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Mon, 15 Jul 2019 23:33:18 +0800 Subject: [PATCH 900/927] smt: handle failure of setrlimit syscall --- backends/smt2/smtio.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ae7968a1b..bac68ac70 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -43,7 +43,11 @@ if os.name == "posix": if current_rlimit_stack[1] != resource.RLIM_INFINITY: smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) if current_rlimit_stack[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) + try: + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) + except ValueError: + # couldn't get more stack, just run with what we have + pass # currently running solvers (so we can kill them) From 06f94c92d49a82faad492026f2b0fe6cf0495fcf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 08:35:48 -0700 Subject: [PATCH 901/927] Revert "Add log_checkpoint function and use it in opt_muxtree" This reverts commit 0e6c83027f24cdf7082606a5631468ad28f41574. --- kernel/log.cc | 7 ------- kernel/log.h | 1 - passes/opt/opt_muxtree.cc | 1 - 3 files changed, 9 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 08ebe7af7..e0a60ca12 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -427,13 +427,6 @@ void log_pop() log_flush(); } -void log_checkpoint() -{ - log_id_cache_clear(); - IdString::checkpoint(); - log_flush(); -} - #if (defined(__linux__) || defined(__FreeBSD__)) && defined(YOSYS_ENABLE_PLUGINS) void log_backtrace(const char *prefix, int levels) { diff --git a/kernel/log.h b/kernel/log.h index 3328018f3..3e1facae8 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -130,7 +130,6 @@ void log_spacer(); void log_push(); void log_pop(); -void log_checkpoint(); void log_backtrace(const char *prefix, int levels); void log_reset_stack(); void log_flush(); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 79f0e9639..6511e091b 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -204,7 +204,6 @@ struct OptMuxtreeWorker log(" Analyzing evaluation results.\n"); log_assert(glob_abort_cnt > 0); - log_checkpoint(); for (auto &mi : mux2info) { From 5fb27c071bb072644dbb38cf8a516628c2afe15b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 15 Jul 2019 12:03:51 -0700 Subject: [PATCH 902/927] $__ICE40_CARRY_LUT4 -> $__ICE40_FULL_ADDER as per @whitequark --- techlibs/ice40/abc_hx.box | 2 +- techlibs/ice40/abc_lp.box | 2 +- techlibs/ice40/abc_u.box | 2 +- techlibs/ice40/arith_map.v | 2 +- techlibs/ice40/cells_map.v | 2 +- techlibs/ice40/cells_sim.v | 2 +- techlibs/ice40/ice40_opt.cc | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box index 4b55297dd..c0ea742e2 100644 --- a/techlibs/ice40/abc_hx.box +++ b/techlibs/ice40/abc_hx.box @@ -8,6 +8,6 @@ # (NB: carry chain input/output must be last # input/output and have been moved there # overriding the alphabetical ordering) -$__ICE40_CARRY_LUT4 1 1 3 2 +$__ICE40_FULL_ADDER 1 1 3 2 400 379 316 259 231 126 diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box index b85346370..d73b6d649 100644 --- a/techlibs/ice40/abc_lp.box +++ b/techlibs/ice40/abc_lp.box @@ -8,6 +8,6 @@ # (NB: carry chain input/output must be last # input/output and have been moved there # overriding the alphabetical ordering) -$__ICE40_CARRY_LUT4 1 1 3 2 +$__ICE40_FULL_ADDER 1 1 3 2 589 558 465 675 609 186 diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box index 95c2c3d81..42d666051 100644 --- a/techlibs/ice40/abc_u.box +++ b/techlibs/ice40/abc_u.box @@ -8,6 +8,6 @@ # (NB: carry chain input/output must be last # input/output and have been moved there # overriding the alphabetical ordering) -$__ICE40_CARRY_LUT4 1 1 3 2 +$__ICE40_FULL_ADDER 1 1 3 2 1231 1205 874 675 609 278 diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index abba18c37..fe83a8e38 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -45,7 +45,7 @@ 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 `ifdef _ABC - \$__ICE40_CARRY_LUT4 carry ( + \$__ICE40_FULL_ADDER carry ( .A(AA[i]), .B(BB[i]), .CI(C[i]), diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 5dca63e19..b4b831165 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -63,7 +63,7 @@ endmodule `endif `ifdef _ABC -module \$__ICE40_CARRY_LUT4 (output CO, O, input A, B, CI); +module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI); SB_CARRY carry ( .I0(A), .I1(B), diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index cf36f5cfb..609facc93 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -142,7 +142,7 @@ module SB_CARRY (output CO, input I0, I1, CI); endmodule (* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *) -module \$__ICE40_CARRY_LUT4 (output CO, O, input A, B, CI); +module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI); SB_CARRY carry ( .I0(A), .I1(B), diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index 38910dffa..e492454fb 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -84,7 +84,7 @@ static void run_ice40_opts(Module *module) continue; } - if (cell->type == "$__ICE40_CARRY_LUT4") + if (cell->type == "$__ICE40_FULL_ADDER") { SigSpec non_const_inputs, replacement_output; int count_zeros = 0, count_ones = 0; @@ -114,7 +114,7 @@ static void run_ice40_opts(Module *module) optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); module->connect(cell->getPort("\\CO")[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); - log("Optimized $__ICE40_CARRY_LUT4 cell into $lut (without SB_CARRY) %s.%s: CO=%s\n", + log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", log_id(module), log_id(cell), log_signal(replacement_output)); cell->type = "$lut"; cell->setPort("\\A", { RTLIL::S0, inbit[0], inbit[1], inbit[2] }); From 2b469e82a78aa6bb46dbdc2ea8460e3209d5432b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 16 Jul 2019 10:35:18 +0200 Subject: [PATCH 903/927] Fix check logic in extract_fa --- passes/techmap/extract_fa.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc index 8de57e769..591bc43dd 100644 --- a/passes/techmap/extract_fa.cc +++ b/passes/techmap/extract_fa.cc @@ -174,7 +174,7 @@ struct ExtractFaWorker SigSpec sig = root; - if (ce.eval(sig)) { + if (!ce.eval(sig)) { ce.pop(); return; } @@ -216,7 +216,7 @@ struct ExtractFaWorker SigSpec sig = root; - if (ce.eval(sig)) { + if (!ce.eval(sig)) { ce.pop(); return; } From 6cce679b35d7eab2b620eed7b8b697d10974307a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 16 Jul 2019 11:03:30 +0200 Subject: [PATCH 904/927] Fix typo, double "of" --- frontends/liberty/liberty.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 6e3cffaca..14de95e07 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -551,7 +551,7 @@ struct LibertyFrontend : public Frontend { if (design->has(cell_name)) { Module *existing_mod = design->module(cell_name); if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { - log_error("Re-definition of of cell/module %s!\n", log_id(cell_name)); + log_error("Re-definition of cell/module %s!\n", log_id(cell_name)); } else if (flag_nooverwrite) { log("Ignoring re-definition of module %s.\n", log_id(cell_name)); continue; From dd10d2b00d6760f2d09f55c90591855afcae409e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 12:11:59 -0700 Subject: [PATCH 905/927] Add tests for cmp2lut on LUT6 --- tests/lut/map_cmp.v | 47 ++++++++++++++++++++++--------------------- tests/lut/run-test.sh | 5 +++++ 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/tests/lut/map_cmp.v b/tests/lut/map_cmp.v index 5e413f894..0014eb9ac 100644 --- a/tests/lut/map_cmp.v +++ b/tests/lut/map_cmp.v @@ -1,29 +1,30 @@ module top(...); - input [3:0] a; + parameter LUT_WIDTH = 4; // Multiples of 2 only + input [LUT_WIDTH-1:0] a; - output o1_1 = 4'b1010 <= a; - output o1_2 = 4'b1010 < a; - output o1_3 = 4'b1010 >= a; - output o1_4 = 4'b1010 > a; - output o1_5 = 4'b1010 == a; - output o1_6 = 4'b1010 != a; + output o1_1 = {(LUT_WIDTH/2){2'b10}} <= a; + output o1_2 = {(LUT_WIDTH/2){2'b10}} < a; + output o1_3 = {(LUT_WIDTH/2){2'b10}} >= a; + output o1_4 = {(LUT_WIDTH/2){2'b10}} > a; + output o1_5 = {(LUT_WIDTH/2){2'b10}} == a; + output o1_6 = {(LUT_WIDTH/2){2'b10}} != a; - output o2_1 = a <= 4'b1010; - output o2_2 = a < 4'b1010; - output o2_3 = a >= 4'b1010; - output o2_4 = a > 4'b1010; - output o2_5 = a == 4'b1010; - output o2_6 = a != 4'b1010; + output o2_1 = a <= {(LUT_WIDTH/2){2'b10}}; + output o2_2 = a < {(LUT_WIDTH/2){2'b10}}; + output o2_3 = a >= {(LUT_WIDTH/2){2'b10}}; + output o2_4 = a > {(LUT_WIDTH/2){2'b10}}; + output o2_5 = a == {(LUT_WIDTH/2){2'b10}}; + output o2_6 = a != {(LUT_WIDTH/2){2'b10}}; - output o3_1 = 4'sb0101 <= $signed(a); - output o3_2 = 4'sb0101 < $signed(a); - output o3_3 = 4'sb0101 >= $signed(a); - output o3_4 = 4'sb0101 > $signed(a); - output o3_5 = 4'sb0101 == $signed(a); - output o3_6 = 4'sb0101 != $signed(a); + output o3_1 = {(LUT_WIDTH/2){2'sb01}} <= $signed(a); + output o3_2 = {(LUT_WIDTH/2){2'sb01}} < $signed(a); + output o3_3 = {(LUT_WIDTH/2){2'sb01}} >= $signed(a); + output o3_4 = {(LUT_WIDTH/2){2'sb01}} > $signed(a); + output o3_5 = {(LUT_WIDTH/2){2'sb01}} == $signed(a); + output o3_6 = {(LUT_WIDTH/2){2'sb01}} != $signed(a); - output o4_1 = $signed(a) <= 4'sb0000; - output o4_2 = $signed(a) < 4'sb0000; - output o4_3 = $signed(a) >= 4'sb0000; - output o4_4 = $signed(a) > 4'sb0000; + output o4_1 = $signed(a) <= {LUT_WIDTH{1'sb0}}; + output o4_2 = $signed(a) < {LUT_WIDTH{1'sb0}}; + output o4_3 = $signed(a) >= {LUT_WIDTH{1'sb0}}; + output o4_4 = $signed(a) > {LUT_WIDTH{1'sb0}}; endmodule diff --git a/tests/lut/run-test.sh b/tests/lut/run-test.sh index 207417fa6..f8964f146 100755 --- a/tests/lut/run-test.sh +++ b/tests/lut/run-test.sh @@ -4,3 +4,8 @@ for x in *.v; do echo "Running $x.." ../../yosys -q -s check_map.ys -l ${x%.v}.log $x done + +for x in map_cmp.v; do + echo "Running $x.." + ../../yosys -q -s check_map_lut6.ys -l ${x%.v}_lut6.log $x +done From 8a2a2cd035d5fe931899256711ed972fd1da3a3b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 12:44:26 -0700 Subject: [PATCH 906/927] Forgot to commit --- tests/lut/check_map_lut6.ys | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/lut/check_map_lut6.ys diff --git a/tests/lut/check_map_lut6.ys b/tests/lut/check_map_lut6.ys new file mode 100644 index 000000000..8a32e4d10 --- /dev/null +++ b/tests/lut/check_map_lut6.ys @@ -0,0 +1,7 @@ +chparam -set LUT_WIDTH 6 top +simplemap +equiv_opt -assert techmap -D LUT_WIDTH=6 -map +/cmp2lut.v +design -load postopt +equiv_opt -assert techmap -D LUT_WIDTH=6 -map +/gate2lut.v +design -load postopt +select -assert-count 0 t:* t:$lut %d From 7a58ee78dc8bd2c257498dc947081a1bba7bb54f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Jul 2019 12:45:29 -0700 Subject: [PATCH 907/927] gen_lut to return correctly sized LUT mask --- techlibs/common/cmp2lut.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index 8aa1eb957..0d0757767 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -27,7 +27,7 @@ parameter _TECHMAP_CONSTVAL_A_ = 0; parameter _TECHMAP_CONSTMSK_B_ = 0; parameter _TECHMAP_CONSTVAL_B_ = 0; -function automatic integer gen_lut; +function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut; input integer width; input integer operation; input integer swap; From ba099bfe9befccc42df99d2930fdbc686152187c Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 11 Jul 2019 10:56:59 +0000 Subject: [PATCH 908/927] synth_{ice40,ecp5}: more sensible pass label naming. --- techlibs/ecp5/synth_ecp5.cc | 10 +++++++--- techlibs/ice40/synth_ice40.cc | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 9f409ca51..3d189a9f1 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -231,23 +231,27 @@ struct SynthEcp5Pass : public ScriptPass run("synth -run coarse"); } - if (!nobram && check_label("bram", "(skip if -nobram)")) + if (!nobram && check_label("map_bram", "(skip if -nobram)")) { run("memory_bram -rules +/ecp5/bram.txt"); run("techmap -map +/ecp5/brams_map.v"); } - if (!nodram && check_label("dram", "(skip if -nodram)")) + if (!nodram && check_label("map_dram", "(skip if -nodram)")) { run("memory_bram -rules +/ecp5/dram.txt"); run("techmap -map +/ecp5/drams_map.v"); } - if (check_label("fine")) + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); run("opt -undriven -fine"); + } + + if (check_label("map_gates")) + { if (noccu2) run("techmap"); else diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 0474e76e9..1a20f7049 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -275,14 +275,14 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); } - if (!nobram && check_label("bram", "(skip if -nobram)")) + if (!nobram && check_label("map_bram", "(skip if -nobram)")) { run("memory_bram -rules +/ice40/brams.txt"); run("techmap -map +/ice40/brams_map.v"); run("ice40_braminit"); } - if (check_label("map")) + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine"); run("memory_map"); From 698ab9beeed7ee585117cc1e5f5126a9092942df Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 16 Jul 2019 20:44:55 +0000 Subject: [PATCH 909/927] synth_ecp5: rename dram to lutram everywhere. --- techlibs/ecp5/Makefile.inc | 4 ++-- techlibs/ecp5/{dram.txt => lutram.txt} | 0 techlibs/ecp5/{drams_map.v => lutrams_map.v} | 0 techlibs/ecp5/synth_ecp5.cc | 22 ++++++++++---------- 4 files changed, 13 insertions(+), 13 deletions(-) rename techlibs/ecp5/{dram.txt => lutram.txt} (100%) rename techlibs/ecp5/{drams_map.v => lutrams_map.v} (100%) diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index ff39ba4fe..73e18112f 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -4,8 +4,8 @@ OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) diff --git a/techlibs/ecp5/dram.txt b/techlibs/ecp5/lutram.txt similarity index 100% rename from techlibs/ecp5/dram.txt rename to techlibs/ecp5/lutram.txt diff --git a/techlibs/ecp5/drams_map.v b/techlibs/ecp5/lutrams_map.v similarity index 100% rename from techlibs/ecp5/drams_map.v rename to techlibs/ecp5/lutrams_map.v diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 3d189a9f1..143d1f95c 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -71,10 +71,10 @@ struct SynthEcp5Pass : public ScriptPass log(" do not use flipflops with CE in output netlist\n"); log("\n"); log(" -nobram\n"); - log(" do not use BRAM cells in output netlist\n"); + log(" do not use block RAM cells in output netlist\n"); log("\n"); - log(" -nodram\n"); - log(" do not use distributed RAM cells in output netlist\n"); + log(" -nolutram\n"); + log(" do not use LUT RAM cells in output netlist\n"); log("\n"); log(" -nowidelut\n"); log(" do not use PFU muxes to implement LUTs larger than LUT4s\n"); @@ -96,7 +96,7 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nodram, nowidelut, flatten, retime, abc2, abc9, vpr; + bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, vpr; void clear_flags() YS_OVERRIDE { @@ -107,7 +107,7 @@ struct SynthEcp5Pass : public ScriptPass noccu2 = false; nodffe = false; nobram = false; - nodram = false; + nolutram = false; nowidelut = false; flatten = true; retime = false; @@ -172,11 +172,11 @@ struct SynthEcp5Pass : public ScriptPass nobram = true; continue; } - if (args[argidx] == "-nodram") { - nodram = true; + if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") { + nolutram = true; continue; } - if (args[argidx] == "-nowidelut" || args[argidx] == "-nomux") { + if (args[argidx] == "-nowidelut" || /*deprecated alias*/ args[argidx] == "-nomux") { nowidelut = true; continue; } @@ -237,10 +237,10 @@ struct SynthEcp5Pass : public ScriptPass run("techmap -map +/ecp5/brams_map.v"); } - if (!nodram && check_label("map_dram", "(skip if -nodram)")) + if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { - run("memory_bram -rules +/ecp5/dram.txt"); - run("techmap -map +/ecp5/drams_map.v"); + run("memory_bram -rules +/ecp5/lutram.txt"); + run("techmap -map +/ecp5/lutrams_map.v"); } if (check_label("map_ffram")) From 4ff44d85a5cb63c7b3f67c2f2398e62db7f199eb Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 16 Jul 2019 20:57:05 +0000 Subject: [PATCH 910/927] write_verilog: dump zero width constants correctly. Before this commit, zero width constants were dumped as "" (empty string). Unfortunately, 1364-2005 5.2.3.3 indicates that an empty string is equivalent to "\0", and is 8 bits wide, so that's wrong. After this commit, a replication operation with a count of zero is used instead, which is explicitly permitted per 1364-2005 5.1.14, and is defined to have size zero. (Its operand has to have a non-zero size for it to be legal, though.) Fixes #948 (again). --- backends/verilog/verilog_backend.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a020d82b6..48404b34c 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -189,7 +189,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o if (width < 0) width = data.bits.size() - offset; if (width == 0) { - f << "\"\""; + // See IEEE 1364-2005 Clause 5.1.14. + f << "{0{1'b0}}"; return; } if (nostr) From f28e38de9994151ea4e22608441dbc9e116d7b8c Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 16 Jul 2019 23:57:15 +0200 Subject: [PATCH 911/927] ice40: Adapt the relut process passes to the new $lut <=> SB_LUT4 port map The new mapping introduced in 437fec0d88b4a2ad172edf0d1a861a38845f3b1d needed matching adaptation when converting and optimizing LUTs during the relut process Fixes #1187 (Diagnosis of the issue by @daveshah1 on IRC) Signed-off-by: Sylvain Munaut --- techlibs/ice40/ice40_unlut.cc | 6 +++--- techlibs/ice40/synth_ice40.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc index d16e6e6a3..f3f70ac1f 100644 --- a/techlibs/ice40/ice40_unlut.cc +++ b/techlibs/ice40/ice40_unlut.cc @@ -56,10 +56,10 @@ static void run_ice40_unlut(Module *module) cell->unsetParam("\\LUT_INIT"); cell->setPort("\\A", SigSpec({ - get_bit_or_zero(cell->getPort("\\I3")), - get_bit_or_zero(cell->getPort("\\I2")), + get_bit_or_zero(cell->getPort("\\I0")), get_bit_or_zero(cell->getPort("\\I1")), - get_bit_or_zero(cell->getPort("\\I0")) + get_bit_or_zero(cell->getPort("\\I2")), + get_bit_or_zero(cell->getPort("\\I3")) })); cell->setPort("\\Y", cell->getPort("\\O")[0]); cell->unsetPort("\\I0"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index b3d30791a..78ac5ea13 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -345,7 +345,7 @@ struct SynthIce40Pass : public ScriptPass } run("clean"); run("ice40_unlut"); - run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3"); + run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); } if (check_label("map_cells")) From 56c00e871fbb73649d3b6f7ccee31c90942a020c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 Jul 2019 11:49:04 +0200 Subject: [PATCH 912/927] Remove old $pmux_safe code from write_verilog Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index a020d82b6..778f9b855 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -788,7 +788,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == "$pmux" || cell->type == "$pmux_safe") + if (cell->type == "$pmux") { int width = cell->parameters["\\WIDTH"].as_int(); int s_width = cell->getPort("\\S").size(); @@ -800,18 +800,17 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" " input [%d:0] s;\n", indent.c_str(), s_width-1); dump_attributes(f, indent + " ", cell->attributes); - if (cell->type != "$pmux_safe" && !noattr) + if (!noattr) f << stringf("%s" " (* parallel_case *)\n", indent.c_str()); f << stringf("%s" " casez (s)", indent.c_str()); - if (cell->type != "$pmux_safe") - f << stringf(noattr ? " // synopsys parallel_case\n" : "\n"); + f << stringf(noattr ? " // synopsys parallel_case\n" : "\n"); for (int i = 0; i < s_width; i++) { f << stringf("%s" " %d'b", indent.c_str(), s_width); for (int j = s_width-1; j >= 0; j--) - f << stringf("%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?'); + f << stringf("%c", j == i ? '1' : '?'); f << stringf(":\n"); f << stringf("%s" " %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width); From c78ab8ebc53bc78d5f1910e311b1e4305df4ca48 Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Thu, 18 Jul 2019 16:46:21 +0100 Subject: [PATCH 913/927] synth_intel: rename for consistency with #1184 Also fix a typo in the help message. --- techlibs/intel/synth_intel.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 09c9ba3af..4f355ce88 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -62,10 +62,10 @@ struct SynthIntelPass : public ScriptPass { log(" synonymous to the end of the command list.\n"); log("\n"); log(" -noiopads\n"); - log(" do not use altsyncram cells in output netlist\n"); + log(" do not use IO pad cells in output netlist\n"); log("\n"); log(" -nobram\n"); - log(" do not use altsyncram cells in output netlist\n"); + log(" do not use block RAM cells in output netlist\n"); log("\n"); log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); @@ -191,12 +191,12 @@ struct SynthIntelPass : public ScriptPass { run("synth -run coarse"); } - if (!nobram && check_label("bram", "(skip if -nobram)")) { + if (!nobram && check_label("map_bram", "(skip if -nobram)")) { run("memory_bram -rules +/intel/common/brams.txt"); run("techmap -map +/intel/common/brams_map.v"); } - if (check_label("fine")) { + if (check_label("map_ffram")) { run("opt -fast -mux_undef -undriven -fine -full"); run("memory_map"); run("opt -undriven -fine"); From 060e77c09b51aabe712315d5fd655f62a765d62f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 8 Jul 2019 12:03:00 -0700 Subject: [PATCH 914/927] intel_synth: Minor code cleanups Signed-off-by: Ben Widawsky --- techlibs/intel/synth_intel.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 09c9ba3af..69f3b6334 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -147,8 +147,12 @@ 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") + 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_header(design, "Executing SYNTH_INTEL pass.\n"); From 809b94a67b0b666018b35536d4de327e99378a6f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 8 Jul 2019 12:24:24 -0700 Subject: [PATCH 915/927] intel_synth: Make family explicit and match The help and code default to MAX10 for the family, however the couple of if ladders defaulted to cycloneive. Fix this inconsistency and the next patch will clean it up. Signed-off-by: Ben Widawsky --- techlibs/intel/synth_intel.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 69f3b6334..9d5d593a4 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -176,8 +176,10 @@ struct SynthIntelPass : public ScriptPass { run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v"); else if (check_label("family") && family_opt == "cycloneiv") run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v"); - else + else if (check_label("family") && family_opt == "cycloneive") run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v"); + else + log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str()); // Misc and common cells run("read_verilog -sv -lib +/intel/common/m9k_bb.v"); run("read_verilog -sv -lib +/intel/common/altpll_bb.v"); @@ -236,8 +238,10 @@ struct SynthIntelPass : public ScriptPass { run("techmap -map +/intel/cyclone10/cells_map.v"); else if (family_opt == "cycloneiv") run("techmap -map +/intel/cycloneiv/cells_map.v"); - else + else if (family_opt == "cycloneive") run("techmap -map +/intel/cycloneive/cells_map.v"); + else + log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str()); run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); } From f950a7a75d4353e0e31c523365a10926bc6180af Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 8 Jul 2019 12:37:24 -0700 Subject: [PATCH 916/927] intel_synth: Small code cleanup to remove if ladder Signed-off-by: Ben Widawsky --- examples/intel/MAX10/run_max10 | 2 +- techlibs/intel/synth_intel.cc | 38 +++++++++------------------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/examples/intel/MAX10/run_max10 b/examples/intel/MAX10/run_max10 index 0378e4fa7..5bf4fc141 100644 --- a/examples/intel/MAX10/run_max10 +++ b/examples/intel/MAX10/run_max10 @@ -1 +1 @@ -yosys -p "synth_intel -family max10 -top top -vqm top.vqm" top.v sevenseg.v +../../../yosys -p "synth_intel -family max10 -top top -vqm top.vqm" top.v sevenseg.v diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 9d5d593a4..5d6254ff6 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -166,20 +166,12 @@ struct SynthIntelPass : public ScriptPass { void script() YS_OVERRIDE { if (check_label("begin")) { - if (check_label("family") && family_opt == "max10") - run("read_verilog -sv -lib +/intel/max10/cells_sim.v"); - else if (check_label("family") && family_opt == "a10gx") - run("read_verilog -sv -lib +/intel/a10gx/cells_sim.v"); - else if (check_label("family") && family_opt == "cyclonev") - run("read_verilog -sv -lib +/intel/cyclonev/cells_sim.v"); - else if (check_label("family") && family_opt == "cyclone10") - run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v"); - else if (check_label("family") && family_opt == "cycloneiv") - run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v"); - else if (check_label("family") && family_opt == "cycloneive") - run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v"); - else - log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str()); + string cmd = "read_verilog -sv -lib +/intel/FAMILY/cells_sim.v"; + cmd.replace(cmd.find("FAMILY"), 6, family_opt); + + if (check_label("family")) + run(cmd); + // Misc and common cells run("read_verilog -sv -lib +/intel/common/m9k_bb.v"); run("read_verilog -sv -lib +/intel/common/altpll_bb.v"); @@ -228,20 +220,10 @@ struct SynthIntelPass : public ScriptPass { if (check_label("map_cells")) { if (!noiopads) run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)"); - if (family_opt == "max10") - run("techmap -map +/intel/max10/cells_map.v"); - else if (family_opt == "a10gx") - run("techmap -map +/intel/a10gx/cells_map.v"); - else if (family_opt == "cyclonev") - run("techmap -map +/intel/cyclonev/cells_map.v"); - else if (family_opt == "cyclone10") - run("techmap -map +/intel/cyclone10/cells_map.v"); - else if (family_opt == "cycloneiv") - run("techmap -map +/intel/cycloneiv/cells_map.v"); - else if (family_opt == "cycloneive") - run("techmap -map +/intel/cycloneive/cells_map.v"); - else - log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str()); + string cmd = "techmap -map +/intel/FAMILY/cells_map.v"; + cmd.replace(cmd.find("FAMILY"), 6, family_opt); + run(cmd); + run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); } From 999811572a652a60003b98b120a5e2da20aad059 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 8 Jul 2019 12:41:22 -0700 Subject: [PATCH 917/927] intel_synth: Fix help message cyclonev has been a "supported" family since the initial commit. The old commit message suggested to use a10gx which is incorrect. Aside from the obvious lack of functional change due to this just being a help message, users who were previously using "a10gx" for "cyclonev" will also have no functional change by using "cyclonev" instead. Signed-off-by: Ben Widawsky --- techlibs/intel/synth_intel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 5d6254ff6..0b44a835f 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -40,7 +40,7 @@ struct SynthIntelPass : public ScriptPass { log(" generate the synthesis netlist for the specified family.\n"); log(" MAX10 is the default target if not 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(" Cyclone V and Arria 10 GX devices are experimental.\n"); log("\n"); log(" -top \n"); log(" use the specified module as top module (default='top')\n"); From d5b3b3bc6f9461fcdbad3dce849b4ab8988515db Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Thu, 18 Jul 2019 17:08:52 +0100 Subject: [PATCH 918/927] synth_intel: revert change to run_max10 --- examples/intel/MAX10/run_max10 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/intel/MAX10/run_max10 b/examples/intel/MAX10/run_max10 index 5bf4fc141..0378e4fa7 100644 --- a/examples/intel/MAX10/run_max10 +++ b/examples/intel/MAX10/run_max10 @@ -1 +1 @@ -../../../yosys -p "synth_intel -family max10 -top top -vqm top.vqm" top.v sevenseg.v +yosys -p "synth_intel -family max10 -top top -vqm top.vqm" top.v sevenseg.v From 50f5e29724bb6ea7f19279be7613ce693b7ea2da Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Thu, 18 Jul 2019 17:28:21 +0100 Subject: [PATCH 919/927] synth_intel: s/not family/no family/ --- 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 0b44a835f..9a6df8c45 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.\n"); log("\n"); @@ -153,7 +153,7 @@ struct SynthIntelPass : public ScriptPass { 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 0c999ac2c4379273d560319d28591627de345a6a Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Thu, 18 Jul 2019 18:41:34 +0100 Subject: [PATCH 920/927] synth_intel: Use stringf --- techlibs/intel/synth_intel.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 9a6df8c45..58ef25e17 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -166,11 +166,8 @@ struct SynthIntelPass : public ScriptPass { void script() YS_OVERRIDE { if (check_label("begin")) { - string cmd = "read_verilog -sv -lib +/intel/FAMILY/cells_sim.v"; - cmd.replace(cmd.find("FAMILY"), 6, family_opt); - if (check_label("family")) - run(cmd); + run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str())); // Misc and common cells run("read_verilog -sv -lib +/intel/common/m9k_bb.v"); @@ -220,9 +217,7 @@ struct SynthIntelPass : public ScriptPass { if (check_label("map_cells")) { if (!noiopads) run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)"); - string cmd = "techmap -map +/intel/FAMILY/cells_map.v"; - cmd.replace(cmd.find("FAMILY"), 6, family_opt); - run(cmd); + run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str())); run("dffinit -highlow -ff dffeas q power_up"); run("clean -purge"); From f7753720feaf466a089f4b96fca27ed4130b5be8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 08:45:35 -0700 Subject: [PATCH 921/927] Don't copy ref if exists already --- techlibs/ice40/tests/test_dsp_model.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/ice40/tests/test_dsp_model.sh b/techlibs/ice40/tests/test_dsp_model.sh index 1bc0cc688..2d42c23ad 100644 --- a/techlibs/ice40/tests/test_dsp_model.sh +++ b/techlibs/ice40/tests/test_dsp_model.sh @@ -1,7 +1,9 @@ #!/bin/bash set -ex sed 's/SB_MAC16/SB_MAC16_UUT/; /SB_MAC16_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v -cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v +if [ ! -f "test_dsp_model_ref.v" ]; then + cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v +fi for tb in testbench \ testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \ testbench_seq_16x16_A testbench_seq_16x16_B From 171cd2ff738cdb8027b9b6efb988bab8744264a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 08:52:49 -0700 Subject: [PATCH 922/927] Add tests for all combinations of A and B signedness for comb mul --- techlibs/ice40/tests/test_dsp_model.sh | 5 +- techlibs/ice40/tests/test_dsp_model.v | 225 +++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 1 deletion(-) diff --git a/techlibs/ice40/tests/test_dsp_model.sh b/techlibs/ice40/tests/test_dsp_model.sh index 2d42c23ad..75f95ab29 100644 --- a/techlibs/ice40/tests/test_dsp_model.sh +++ b/techlibs/ice40/tests/test_dsp_model.sh @@ -6,7 +6,10 @@ if [ ! -f "test_dsp_model_ref.v" ]; then fi for tb in testbench \ testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \ - testbench_seq_16x16_A testbench_seq_16x16_B + testbench_seq_16x16_A testbench_seq_16x16_B \ + testbench_comb_8x8_A_signedA testbench_comb_8x8_A_signedB testbench_comb_8x8_A_signedAB \ + testbench_comb_8x8_B_signedA testbench_comb_8x8_B_signedB testbench_comb_8x8_B_signedAB \ + testbench_comb_16x16_B_signedA testbench_comb_16x16_B_signedB testbench_comb_16x16_B_signedAB do iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v vvp -N ./test_dsp_model diff --git a/techlibs/ice40/tests/test_dsp_model.v b/techlibs/ice40/tests/test_dsp_model.v index 594bd4ad3..f4f6858f0 100644 --- a/techlibs/ice40/tests/test_dsp_model.v +++ b/techlibs/ice40/tests/test_dsp_model.v @@ -241,6 +241,81 @@ module testbench_comb_8x8_A; ) testbench (); endmodule +module testbench_comb_8x8_A_signedA; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (0) + ) testbench (); +endmodule + +module testbench_comb_8x8_A_signedB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (0), + .B_SIGNED (1) + ) testbench (); +endmodule + +module testbench_comb_8x8_A_signedAB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (1) + ) testbench (); +endmodule + module testbench_comb_8x8_B; testbench #( .NEG_TRIGGER (0), @@ -266,6 +341,81 @@ module testbench_comb_8x8_B; ) testbench (); endmodule +module testbench_comb_8x8_B_signedA; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (0) + ) testbench (); +endmodule + +module testbench_comb_8x8_B_signedB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (0), + .B_SIGNED (1) + ) testbench (); +endmodule + +module testbench_comb_8x8_B_signedAB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (1) + ) testbench (); +endmodule + module testbench_comb_16x16; testbench #( .NEG_TRIGGER (0), @@ -291,6 +441,81 @@ module testbench_comb_16x16; ) testbench (); endmodule +module testbench_comb_16x16_signedA; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (0) + ) testbench (); +endmodule + +module testbench_comb_16x16_signedB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (0), + .B_SIGNED (1) + ) testbench (); +endmodule + +module testbench_comb_16x16_signedAB; + testbench #( + .NEG_TRIGGER (0), + .C_REG (0), + .A_REG (0), + .B_REG (0), + .D_REG (0), + .TOP_8x8_MULT_REG (0), + .BOT_8x8_MULT_REG (0), + .PIPELINE_16x16_MULT_REG1 (0), + .PIPELINE_16x16_MULT_REG2 (0), + .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16 + .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT + .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C + .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16 + .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT + .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D + .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI + .MODE_8x8 (0), + .A_SIGNED (1), + .B_SIGNED (1) + ) testbench (); +endmodule + module testbench_seq_16x16_A; testbench #( .NEG_TRIGGER (0), From 3c84271543379a5a3845d5dcdb49a5e6fbafbc66 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 19 Jul 2019 17:13:34 +0100 Subject: [PATCH 923/927] ice40/cells_sim.v: LSB of A/B only signed in 8x8 mode Signed-off-by: David Shah --- techlibs/ice40/cells_sim.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 609facc93..4402f8d36 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -1363,9 +1363,9 @@ module SB_MAC16 ( wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl; wire [15:0] Ah, Al, Bh, Bl; assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]}; - assign Al = {A_SIGNED ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; + assign Al = {A_SIGNED && MODE_8x8 ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]}; - assign Bl = {B_SIGNED ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; + assign Bl = {B_SIGNED && MODE_8x8 ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; assign p_Ah_Bh = Ah * Bh; assign p_Al_Bh = Al * Bh; assign p_Ah_Bl = Ah * Bl; From 79f14c751417685e7405855a96fc7a37f5bc7fbf Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 19 Jul 2019 17:33:41 +0100 Subject: [PATCH 924/927] ice40/cells_sim.v: Fix sign of J and K partial products Signed-off-by: David Shah --- techlibs/ice40/cells_sim.v | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 4402f8d36..2205be27d 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -1366,10 +1366,10 @@ module SB_MAC16 ( assign Al = {A_SIGNED && MODE_8x8 ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]}; assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]}; assign Bl = {B_SIGNED && MODE_8x8 ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]}; - assign p_Ah_Bh = Ah * Bh; - assign p_Al_Bh = Al * Bh; - assign p_Ah_Bl = Ah * Bl; - assign p_Al_Bl = Al * Bl; + assign p_Ah_Bh = Ah * Bh; // F + assign p_Al_Bh = {8'b0, Al[7:0]} * Bh; // J + assign p_Ah_Bl = Ah * {8'b0, Bl[7:0]}; // K + assign p_Al_Bl = Al * Bl; // G // Regs F and J reg [15:0] rF, rJ; @@ -1400,7 +1400,9 @@ module SB_MAC16 ( assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl; // Adder Stage - assign iL = iG + (iK << 8) + (iJ << 8) + (iF << 16); + wire [23:0] iK_e = {A_SIGNED ? {8{iK[15]}} : 8'b0, iK}; + wire [23:0] iJ_e = {B_SIGNED ? {8{iJ[15]}} : 8'b0, iJ}; + assign iL = iG + (iK_e << 8) + (iJ_e << 8) + (iF << 16); // Reg H reg [31:0] rH; From 80884d6f7bd10d79e89ad3893ae557aa64af9742 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 19 Jul 2019 17:33:57 +0100 Subject: [PATCH 925/927] ice40: Fix test_dsp_model.sh Signed-off-by: David Shah --- techlibs/ice40/tests/test_dsp_model.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/tests/test_dsp_model.sh b/techlibs/ice40/tests/test_dsp_model.sh index 75f95ab29..1e564d1b2 100644 --- a/techlibs/ice40/tests/test_dsp_model.sh +++ b/techlibs/ice40/tests/test_dsp_model.sh @@ -9,7 +9,7 @@ for tb in testbench \ testbench_seq_16x16_A testbench_seq_16x16_B \ testbench_comb_8x8_A_signedA testbench_comb_8x8_A_signedB testbench_comb_8x8_A_signedAB \ testbench_comb_8x8_B_signedA testbench_comb_8x8_B_signedB testbench_comb_8x8_B_signedAB \ - testbench_comb_16x16_B_signedA testbench_comb_16x16_B_signedB testbench_comb_16x16_B_signedAB + testbench_comb_16x16_signedA testbench_comb_16x16_signedB testbench_comb_16x16_signedAB do iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v vvp -N ./test_dsp_model From c6d8692c9711e4b65aa89ad60986c9df7e053fc7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Jul 2019 15:06:28 +0200 Subject: [PATCH 926/927] Add "stat -tech cmos" Signed-off-by: Clifford Wolf --- passes/cmds/stat.cc | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 27c5fb60c..80b400e0c 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -223,6 +223,33 @@ struct statdata_t log("\n"); log(" Estimated number of LCs: %10d\n", lc_cnt); } + + if (tech == "cmos") + { + int tran_cnt = 0; + bool tran_cnt_exact = true; + + for (auto it : num_cells_by_type) { + auto ctype = it.first; + auto cnum = it.second; + + if (ctype == "$_NOT_") + tran_cnt += 2*cnum; + else if (ctype.in("$_NAND_", "$_NOR_")) + tran_cnt += 4*cnum; + else if (ctype.in("$_AOI3_", "$_OAI3_")) + tran_cnt += 6*cnum; + else if (ctype.in("$_AOI4_", "$_OAI4_")) + tran_cnt += 8*cnum; + else if (ctype.in("$_DFF_P_", "$_DFF_N_")) + tran_cnt += 16*cnum; + else + tran_cnt_exact = false; + } + + log("\n"); + log(" Estimated number of transistors: %10d%s\n", tran_cnt, tran_cnt_exact ? "" : "+"); + } } }; @@ -286,7 +313,7 @@ struct StatPass : public Pass { log("\n"); log(" -tech \n"); log(" print area estemate for the specified technology. Currently supported\n"); - log(" values for : xilinx\n"); + log(" values for : xilinx, cmos\n"); log("\n"); log(" -width\n"); log(" annotate internal cell types with their word width.\n"); @@ -330,7 +357,7 @@ struct StatPass : public Pass { } extra_args(args, argidx, design); - if (techname != "" && techname != "xilinx") + if (techname != "" && techname != "xilinx" && techname != "cmos") log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); for (auto mod : design->selected_modules()) From e2fe8e0a4fd3108de8b7db556be45efc8122173d Mon Sep 17 00:00:00 2001 From: Jakob Wenzel Date: Mon, 22 Jul 2019 10:37:40 +0200 Subject: [PATCH 927/927] initialize noblackbox and nowb in AstModule::clone --- frontends/ast/ast.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 3d066af53..943466ee3 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1551,7 +1551,9 @@ RTLIL::Module *AstModule::clone() const new_mod->nomeminit = nomeminit; new_mod->nomem2reg = nomem2reg; new_mod->mem2reg = mem2reg; + new_mod->noblackbox = noblackbox; new_mod->lib = lib; + new_mod->nowb = nowb; new_mod->noopt = noopt; new_mod->icells = icells; new_mod->pwires = pwires;