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 001/195] 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 9a468f81c412f8b63d25e739f28932815c6882fb Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 28 May 2019 08:48:21 +0200 Subject: [PATCH 002/195] 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 003/195] 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 0f6e914ef63d06ae77b54d246b61118c19647f26 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 08:34:58 -0700 Subject: [PATCH 004/195] 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 5ab59cd59ee90abc4b6991486854dbe4c3f4d0a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:36:19 -0700 Subject: [PATCH 005/195] 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 006/195] 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 007/195] 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 008/195] 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 9b408838f191bb0390b6edff55770cab8e8ca15d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 14:18:17 -0700 Subject: [PATCH 009/195] 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 010/195] 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 011/195] 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 012/195] 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 5b999ae68decef5646ef0ccac53463f22fe18d8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 10:32:19 -0700 Subject: [PATCH 013/195] 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 014/195] 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 4b56f6646dbf819da9fa1fdd47bb4bbdf943be7f Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 11 Jun 2019 02:52:06 +0300 Subject: [PATCH 015/195] 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 016/195] 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 6cdea93724b69695938ca021fd3841f644b478bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 16:05:42 -0700 Subject: [PATCH 017/195] 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 45c2a5f87694a83e0cf96477ede02567a93b32a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:34:06 -0700 Subject: [PATCH 018/195] 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 d69989b8d27eea16d793600b1779661f31161c6c Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Wed, 12 Jun 2019 19:35:05 +0200 Subject: [PATCH 019/195] 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 4912567cbff3c24e9cddea0b59287ec53321af7a Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 13 Jun 2019 15:42:45 +0200 Subject: [PATCH 020/195] 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 8665f48879526f8f3ed79629f28a8686ed78a8ad Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 13 Jun 2019 19:35:37 +0200 Subject: [PATCH 021/195] 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 291b36afeb1075b7c6329d1e57594ed3e6b71581 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 11:35:45 +0200 Subject: [PATCH 022/195] 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 023/195] 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 024/195] 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 c23bbc429103ca84cb8a9cfb674aacf7d14109c6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 16 Jun 2019 23:12:03 +0200 Subject: [PATCH 025/195] 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 75f8b4cf10e45e9064ddac10ff0b088b863fd361 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 17 Jun 2019 19:14:41 -0700 Subject: [PATCH 026/195] 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 027/195] 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 028/195] 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 029/195] 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 030/195] 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 031/195] 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 032/195] 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 468c41d997477aa6c67a8b97bc4d9dcff185b815 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 17 Jun 2019 14:45:11 -0700 Subject: [PATCH 033/195] 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 034/195] 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 035/195] 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 036/195] 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 037/195] 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 038/195] 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 039/195] 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 040/195] 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 041/195] 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 042/195] 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 043/195] 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 044/195] 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 045/195] 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 046/195] 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 047/195] 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 048/195] 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 049/195] 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 050/195] 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 051/195] 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 052/195] 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 053/195] 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 054/195] 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 055/195] 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 8767ec3fbdc0986854107de9cf178953ef09f1db Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 20 Jun 2019 10:27:59 -0700 Subject: [PATCH 056/195] 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 e33cbb0dde72b292002a9fc7158857b19803effe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 12:40:05 -0700 Subject: [PATCH 057/195] 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 058/195] 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 059/195] 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 060/195] 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 061/195] 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 062/195] 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 9c61fb0e0c23f00bacf316f7efd358c66f2f6397 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:57:54 -0700 Subject: [PATCH 063/195] 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 064/195] 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 f2d541962e92fedce0fbb34d4cf5c1985c7cda40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: [PATCH 065/195] 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 066/195] 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 067/195] 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 068/195] 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 069/195] Fix issue with part of PI being 1'bx --- frontends/aiger/aigerparse.cc | 10 ++++++---- tests/simple_abc9/abc9.v | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3b53b0086..ea3315267 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -947,11 +947,13 @@ void AigerReader::post_process() if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i)); - else - module->connect(SigSpec(wire, i), other_wire); } + if (wire->port_input && other_wire) + module->connect(other_wire, SigSpec(wire, i)); + else + // Since we skip POs that are connected to Sx, + // re-connect them here + module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); } } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 0b83c34a3..64b625efe 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -262,3 +262,8 @@ endmodule module abc9_test025(input [3:0] i, output [3:0] o); abc9_test024_sub a(i[2:1], o[2:1]); endmodule + +module abc9_test026(output [3:0] o, p); +assign o = { 1'b1, 1'bx }; +assign p = { 1'b1, 1'bx, 1'b0 }; +endmodule From eb09ea6d54738b82924e33c26f47fe35fbdd24cd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:06:51 -0700 Subject: [PATCH 070/195] 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 071/195] 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 072/195] 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 073/195] 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 074/195] 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 075/195] 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 076/195] 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 077/195] 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 078/195] 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 c4ea6fff65d6b2e69a31649af7e10b129c6ae0f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: [PATCH 079/195] 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 54f3237720709f7c59f4e440ebfdbc61a63c926a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:53:27 -0700 Subject: [PATCH 080/195] 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 081/195] 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 082/195] 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 083/195] Refactor bit2aig for less lookups --- backends/aiger/xaiger.cc | 53 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32c3f9045..48e902666 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,33 +86,36 @@ struct XAigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } - - if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = aig_map.at(State::S0); - } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + a = aig_map.at(State::S0); + } + + log_assert(a >= 0); + aig_map[bit] = a; + return a; } XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) From cbbd96aae9d847279628191d73d5307f3d832097 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:28:55 -0700 Subject: [PATCH 084/195] 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 085/195] 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 086/195] 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 087/195] 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 088/195] 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 089/195] 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 090/195] 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 50e72210772f3a1c34f5fe80b19c65f6d304b71a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 19:47:25 +0200 Subject: [PATCH 091/195] 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 092/195] 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 641b86d25f5baa898bf5fca3d1a8f2fd4f5954e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:45:31 -0700 Subject: [PATCH 093/195] 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 094/195] 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 095/195] 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 096/195] 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 097/195] 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 098/195] 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 099/195] 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 70c93ea0c4ce023d61553df11198aa0b7e518455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: [PATCH 100/195] 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 101/195] 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 102/195] Workaround issues exposed by gcc-4.8 --- frontends/aiger/aigerparse.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a98ea8314..221e3edfc 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -117,13 +117,20 @@ struct ConstEvalAig RTLIL::Cell *cell = sig2driver.at(output); RTLIL::SigBit sig_a = cell->getPort("\\A"); + sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); if (cell->type == "$_AND_") { RTLIL::SigSpec sig_b = cell->getPort("\\B"); + sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_b)) compute_deps(sig_b, inputs); } From 65c1199acd52f90de86106652dbbca86d4ac5ebc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: [PATCH 103/195] One more workaround for gcc-4.8 --- backends/aiger/xaiger.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6718e4f2c..637c54ff9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -429,12 +429,13 @@ struct XAigerWriter module->connect(new_bit, bit); if (not_map.count(bit)) not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); + else if (and_map.count(bit)) { + //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 + and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + } else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else - //log_abort(); alias_map[new_bit] = bit; output_bits.erase(bit); output_bits.insert(new_bit); From 7074ec9cd5d5b5c01e3bbaa8ee45dbae1272f185 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: [PATCH 104/195] 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 105/195] 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 106/195] 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 107/195] 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 108/195] 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 fb8fab4a29e5a3978cadf2b1bd8920b772150028 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 20:30:24 -0700 Subject: [PATCH 109/195] 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 110/195] 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 111/195] 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 112/195] 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 113/195] 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 114/195] 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 efd04880dbeb2021c503c82ad962fe8c5d6802d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 16:16:50 -0700 Subject: [PATCH 115/195] 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 116/195] 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 117/195] 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 118/195] 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 119/195] 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 120/195] 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 121/195] 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 122/195] 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 123/195] 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 124/195] 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 125/195] 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 126/195] Fix for abc_scc_break is bus --- passes/techmap/abc9.cc | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6356d4fbf..cd7954427 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -121,31 +121,33 @@ void handle_loops(RTLIL::Design *design) if (it == cell->connections_.end()) log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", jt->second.decode_string().c_str(), log_id(box_module)); log_assert(it != cell->connections_.end()); - auto &c = *it; - SigBit b = cell->getPort(RTLIL::escape_id(jt->second.decode_string())); - Wire *w = b.wire; - if (w->port_output) { - log_assert(w->get_bool_attribute("\\abc_scc_break")); - w = module->wire(stringf("%s.abci", w->name.c_str())); - log_assert(w); - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - else { - log_assert(!w->port_output); - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_input = true; + RTLIL::SigSpec sig; + for (auto b : it->second) { + Wire *w = b.wire; + if (w->port_output) { + log_assert(w->get_bool_attribute("\\abc_scc_break")); + w = module->wire(stringf("%s.abci", w->name.c_str())); + log_assert(w); + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); } else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); + log_assert(!w->port_output); + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + w = module->wire(stringf("%s.abci", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); + w->port_input = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } } + sig.append(RTLIL::SigBit(w, b.offset)); } - c.second = RTLIL::SigBit(w, b.offset); + it->second = sig; } } } From 2f770b7400f6b12ca13e68496977094f92c13680 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:02:53 -0700 Subject: [PATCH 127/195] Use LUT delays for dist RAM delays --- techlibs/xilinx/abc_xc7.box | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 40b92da0c..8c046cdbc 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -34,12 +34,12 @@ CARRY4 3 1 10 8 # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO RAM64X1D 4 0 15 2 -- - - - - - - 124 124 124 124 124 124 - - -124 124 124 124 124 124 - - - - - - 124 - - +- - - - - - - 642 631 472 407 238 127 - - +642 631 472 407 238 127 - - - - - - - - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO RAM128X1D 5 0 17 2 -- - - - - - - - 314 314 314 314 314 314 292 - - -347 347 347 347 347 347 296 - - - - - - - - - - +- - - - - - - - 1009 998 839 774 605 494 450 - - +1047 1036 877 812 643 532 478 - - - - - - - - - - From d2fed0a7f1bb72ee285657b974f4996c77641a23 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:37:01 -0700 Subject: [PATCH 128/195] 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 129/195] 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 130/195] 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 131/195] 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: Mon, 24 Jun 2019 22:54:35 -0700 Subject: [PATCH 132/195] 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 133/195] 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 134/195] 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 135/195] 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 136/195] 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 137/195] 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 138/195] 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 139/195] 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 140/195] 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 141/195] 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 4ce329aefd34c53ab2b96cd79540c3e528661037 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 09:33:48 -0700 Subject: [PATCH 142/195] 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 143/195] 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 144/195] 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 145/195] 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 146/195] 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 147/195] 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 148/195] 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 149/195] 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 1d0be89214466aa5120d6fc0e155c6366ae8e802 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:17:11 -0700 Subject: [PATCH 150/195] 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 151/195] 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 152/195] 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 153/195] 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 154/195] 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 155/195] 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 156/195] 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 69d810e4a831fc1f17d886d7f371d9785e9022e7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 27 Jun 2019 09:42:49 +0200 Subject: [PATCH 157/195] 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 158/195] 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 159/195] 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 07:24:47 -0700 Subject: [PATCH 160/195] 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 161/195] 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 162/195] 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 163/195] 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 164/195] 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 165/195] 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 166/195] 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 167/195] 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 168/195] 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 169/195] 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 170/195] 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 171/195] 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 172/195] 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 173/195] 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 174/195] 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 175/195] 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 176/195] 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 177/195] 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 178/195] 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 179/195] 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 180/195] 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 b9ddee0c87ef3f089995d734ad7f5ea1c65eedce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:45:40 -0700 Subject: [PATCH 181/195] 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 182/195] 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 183/195] 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 184/195] 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 185/195] 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 186/195] 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 187/195] 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 4a2a93aa069db9397175a98a6836953ee71223d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:10:36 -0700 Subject: [PATCH 188/195] 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 b5f1bd0df1a467679a93d05604c6cc72696854ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:16:15 -0700 Subject: [PATCH 189/195] 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 8cb3655ecdf89102213a33c7474fb85f1ad0a033 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Fri, 28 Jun 2019 14:54:58 -0400 Subject: [PATCH 190/195] 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 728839d6caca41ebbd9ae052668057f978a418e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:53:38 -0700 Subject: [PATCH 191/195] 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 192/195] 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 0ec7c09756a84d123745a381881b9e9803da210d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 14:18:56 -0700 Subject: [PATCH 193/195] 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 194/195] 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 0067dc44f3928833eede2b9bb40260be78e11a93 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 09:44:53 -0700 Subject: [PATCH 195/195] 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