From b63b2a0bd4552a7dbe0d2c4a15d4e3a1b0e2022d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:50:24 -0700 Subject: [PATCH 001/160] Revert "Remove wide mux inference" This reverts commit 738fdfe8f55e18ac7f315cd68c117eae370004ca. --- CHANGELOG | 1 + techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/cells_map.v | 120 ++++++++++++++++++++++++++++++++ techlibs/xilinx/mux_map.v | 52 ++++++++++++++ techlibs/xilinx/synth_xilinx.cc | 24 ++++++- 5 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 techlibs/xilinx/mux_map.v diff --git a/CHANGELOG b/CHANGELOG index 44e32c6a8..e74af6b65 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" + - "synth_xilinx" to now infer wide multiplexers Yosys 0.7 .. Yosys 0.8 diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 1a652eb27..59fd61cf0 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,6 +30,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index b5114758c..f139dc5d5 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -154,3 +154,123 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end endgenerate endmodule + +module \$__XILINX_SHIFTX (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + function integer compute_num_leading_X_in_A; + integer i, c; + begin + compute_num_leading_X_in_A = 0; + c = 1; + for (i = A_WIDTH-1; i >= 0; i=i-1) begin + if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx) + c = 0; + compute_num_leading_X_in_A = compute_num_leading_X_in_A + c; + end + end + endfunction + localparam num_leading_X_in_A = compute_num_leading_X_in_A(); + + generate + genvar i, j; + // Bit-blast + if (Y_WIDTH > 1) begin + for (i = 0; i < Y_WIDTH; i++) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); + end + // If the LSB of B is constant zero (and Y_WIDTH is 1) then + // we can optimise by removing every other entry from A + // and popping the constant zero from B + else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin + wire [(A_WIDTH+1)/2-1:0] A_i; + for (i = 0; i < (A_WIDTH+1)/2; i++) + assign A_i[i] = A[i*2]; + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); + end + // Trim off any leading 1'bx -es in A, and resize B accordingly + else if (num_leading_X_in_A > 0) begin + localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; + localparam B_WIDTH_new = $clog2(A_WIDTH_new); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); + end + else if (B_WIDTH < 3 || A_WIDTH <= 4) begin + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + end + else if (B_WIDTH == 3) begin + localparam a_width0 = 2 ** 2; + localparam a_widthN = A_WIDTH - a_width0; + wire T0, T1; + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); + else + assign T1 = A[A_WIDTH-1]; + MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + end + else if (B_WIDTH == 4) begin + localparam a_width0 = 2 ** 2; + localparam num_mux8 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; + wire [4-1:0] T; + wire T0, T1; + for (i = 0; i < 4; i++) + if (i < num_mux8) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + else if (i == num_mux8 && a_widthN > 0) begin + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end + else + assign T[i] = 1'bx; + MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); + MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); + MUXF8 fpga_hard_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); + end + else begin + localparam a_width0 = 2 ** 4; + localparam num_mux16 = A_WIDTH / a_width0; + localparam a_widthN = A_WIDTH - num_mux16*a_width0; + wire [(2**(B_WIDTH-4))-1:0] T; + for (i = 0; i < 2 ** (B_WIDTH-4); i++) + if (i < num_mux16) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + else if (i == num_mux16 && a_widthN > 0) begin + if (a_widthN > 1) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end + else + assign T[i] = 1'bx; + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + end + endgenerate +endmodule + +module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); +input A, B, C, D, E, F, G, H, S, T, U; +output Y; + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); +endmodule + +module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); +input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; +output Y; + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); +endmodule diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v new file mode 100644 index 000000000..0fa8db736 --- /dev/null +++ b/techlibs/xilinx/mux_map.v @@ -0,0 +1,52 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module \$shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; + parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + + generate + genvar i, j; + // TODO: Check if this opt still necessary + if (B_SIGNED) begin + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + end + else if (B_WIDTH < 3 || A_WIDTH <= 4) begin + wire _TECHMAP_FAIL_ = 1; + end + else begin + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + end + endgenerate +endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a11648873..63ede275f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -72,6 +72,9 @@ struct SynthXilinxPass : public ScriptPass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); + log(" -nomux\n"); + log(" disable inference of wide multiplexers\n"); + log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); log(" from label is synonymous to 'begin', and empty to label is\n"); @@ -93,7 +96,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, abc, arch; - bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; + bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl, nomux; void clear_flags() YS_OVERRIDE { @@ -108,6 +111,7 @@ struct SynthXilinxPass : public ScriptPass nobram = false; nodram = false; nosrl = false; + nomux = false; arch = "xc7"; } @@ -171,6 +175,10 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } + if (args[argidx] == "-nomux") { + nomux = true; + continue; + } if (args[argidx] == "-abc9") { abc = "abc9"; continue; @@ -219,11 +227,15 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { run("synth -run coarse"); + //if (!nomux || help_mode) + // run("muxpack", "(skip if '-nomux')"); + // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former - if (!nosrl || help_mode) - run("pmux2shiftx", "(skip if '-nosrl')"); + // Also: wide multiplexer inference benefits from this too + if (!(nosrl && nomux) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); // Run a number of peephole optimisations, including one // that optimises $mul cells driving $shiftx's B input @@ -261,6 +273,10 @@ struct SynthXilinxPass : public ScriptPass } std::string techmap_files = " -map +/techmap.v"; + if (help_mode) + techmap_files += " [-map +/xilinx/mux_map.v]"; + else if (!nomux) + techmap_files += " -map +/xilinx/mux_map.v"; if (help_mode) techmap_files += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { @@ -275,6 +291,8 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { + if (!nomux || help_mode) + run("muxcover -mux8 -mux16", "(skip if '-nomux')"); run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } From 13e2e8df11b4af9ce5512508caad793c659b9479 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:50:30 -0700 Subject: [PATCH 002/160] Update CHANGELOG --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e74af6b65..13cfb812b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,12 +17,13 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "rename -src" - Added "equiv_opt" pass - Added "read_aiger" frontend + - Added "shregmap -tech xilinx" - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs) - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" - - "synth_xilinx" to now infer wide multiplexers + - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) + - "synth_xilinx" to now infer wide multiplexers (-nomux to disable) Yosys 0.7 .. Yosys 0.8 From 4d7516f45956c6dd3647dc235e3a29c0c7ecc816 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: [PATCH 003/160] Revert "Cleanup/optimise toposort in write_xaiger" This reverts commit 1948e7c846ea318d003148974945d917701a4452. Restores old toposort with optimisations --- backends/aiger/xaiger.cc | 84 +++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0c2ae62e6..1d502a748 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,9 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - SigMap topomap; - topomap.database = sigmap.database; - + dict> bit_drivers, bit_users; + TopoSort toposort; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -198,8 +197,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) - topomap.add(Y, A); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -223,12 +225,16 @@ struct XAigerWriter undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); if (!holes_mode) { - topomap.add(Y, A); - topomap.add(Y, B); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); } continue; } + log_assert(!holes_mode); + //if (cell->type == "$initstate") //{ // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); @@ -265,11 +271,26 @@ struct XAigerWriter // } // if (!abc_box_seen) // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); //} /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; + + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } } else { for (const auto &c : cell->connections()) { @@ -309,45 +330,19 @@ struct XAigerWriter } if (abc_box_seen && !holes_mode) { - TopoSort toposort; - dict> bit_drivers, bit_users; - - for (auto cell : module->selected_cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) - continue; - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : topomap(conn.second)) - if (bit.wire) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - //if (inst_module_port->attributes.count("\\abc_flop_q")) - // continue; - for (auto bit : topomap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); -#if 1 + pool abc_carry_modules; + +#if 0 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 1 +#if 0 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -358,14 +353,13 @@ struct XAigerWriter #endif log_assert(no_loops); - pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - log_assert(box_module); - log_assert(box_module->attributes.count("\\abc_box_id")); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; - if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -461,6 +455,8 @@ struct XAigerWriter } box_list.emplace_back(cell); } + + // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { From 1ec450d6bf34a7aec9b0469b6f295847eb658160 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 12:08:03 -0700 Subject: [PATCH 004/160] Try -W 300 --- techlibs/xilinx/synth_xilinx.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 63ede275f..7b20a7132 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,7 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define XC7_WIRE_DELAY "160" +#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) struct SynthXilinxPass : public ScriptPass { From 6a4025b5eef3ea96a8a7cdb0046cb2193cfa08e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 12:37:46 -0700 Subject: [PATCH 005/160] Remove unncessary header --- frontends/aiger/aigerparse.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 3b53b0086..b98b36319 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,9 +22,6 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf -#ifdef _WIN32 -#include -#endif // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include From 7324a4c2cd0132f792f4fade1a77aeceae46bd85 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Jun 2019 12:47:12 -0700 Subject: [PATCH 006/160] Remove iterator based Module::remove as per @cliffordwolf --- kernel/rtlil.cc | 13 +++---------- kernel/rtlil.h | 1 - passes/techmap/abc9.cc | 13 ++++++------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f732b56b0..3990ec283 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1565,21 +1565,14 @@ void RTLIL::Module::remove(const pool &wires) void RTLIL::Module::remove(RTLIL::Cell *cell) { - auto it = cells_.find(cell->name); - log_assert(it != cells_.end()); - remove(it); -} - -dict::iterator RTLIL::Module::remove(dict::iterator it) -{ - RTLIL::Cell *cell = it->second; while (!cell->connections_.empty()) cell->unsetPort(cell->connections_.begin()->first); + auto it = cells_.find(cell->name); + log_assert(it != cells_.end()); log_assert(refcount_cells_ == 0); - it = cells_.erase(it); + cells_.erase(it); delete cell; - return it; } void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 4a0f8b4f8..f4fcf5dcf 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1040,7 +1040,6 @@ public: // Removing wires is expensive. If you have to remove wires, remove them all at once. void remove(const pool &wires); void remove(RTLIL::Cell *cell); - dict::iterator remove(dict::iterator it); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2f670dba2..7b13239f2 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -510,16 +510,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } vector boxes; - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { + RTLIL::Cell *cell = it->second; if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { - it = module->remove(it); + module->remove(cell); continue; } RTLIL::Module* box_module = design->module(cell->type); if (box_module && box_module->attributes.count("\\abc_box_id")) - boxes.emplace_back(it->second); - ++it; + boxes.emplace_back(cell); } std::map cell_stats; @@ -620,8 +619,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto cell : boxes) - module->remove(cell); + for (auto cell : boxes) + module->remove(cell); // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { From efdb057c6ad5ba0fe05a597ba5f080067f061aad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: [PATCH 007/160] write_xaiger to skip POs driven by 1'bx --- backends/aiger/xaiger.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1485e2b0c..12b23cfe9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,9 +152,13 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (bit != RTLIL::Sx) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + else + log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); } } } From f54edf1e78fbcbd8a11c2ffcbdf62a50b93ce909 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:22:14 -0700 Subject: [PATCH 008/160] Do not call "setundef -zero" in abc9 --- passes/techmap/abc9.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 7b13239f2..f652cdf12 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -380,9 +380,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); - // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero - Pass::call(design, "setundef -zero"); - Pass::call(design, "aigmap"); handle_loops(design); @@ -406,7 +403,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri reader.parse_xaiger(); } ifs.close(); - Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v")); + Pass::call(design, stringf("write_verilog -noexpr -norename")); design->remove(design->module("$__abc9__")); #endif @@ -479,7 +476,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri ifs.close(); #if 0 - Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "output.v")); + Pass::call(design, stringf("write_verilog -noexpr -norename")); #endif log_header(design, "Re-integrating ABC9 results.\n"); From 0e3e647596db296e662348625c28b76215b55bcf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:47:20 -0700 Subject: [PATCH 009/160] 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 9faab38e8de1a78b0ce364a1bdefd2a9ee9c2ec6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:45:04 -0700 Subject: [PATCH 010/160] mux_map to drop sign bit, and eliminate 'bx-es --- techlibs/xilinx/mux_map.v | 60 ++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 0fa8db736..6ad83a488 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -29,24 +29,58 @@ module \$shiftx (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; + parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate - genvar i, j; - // TODO: Check if this opt still necessary - if (B_SIGNED) begin - if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y)); + genvar i; + wire [A_WIDTH-1:0] A_forward; + assign A_forward[A_WIDTH-1] = A[A_WIDTH-1]; + for (i = A_WIDTH-2; i >= 0; i = i - 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_forward[i] = A_forward[i+1]; else - wire _TECHMAP_FAIL_ = 1; - end - else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - wire _TECHMAP_FAIL_ = 1; - end - else begin - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + assign A_forward[i] = A[i]; + + wire [A_WIDTH-1:0] A_without_x; + assign A_without_x[0] = A_forward[0]; + for (i = 1; i < A_WIDTH; i = i + 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_without_x[i] = A_without_x[i-1]; + else + assign A_without_x[i] = A[i]; + + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + // Since negative indices are out of the range of A + // and hence return 'bx, drop the sign bit + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(0), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH-1'd1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); + end + else begin + if (B_WIDTH < 3 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B), .Y(Y) + ); end endgenerate endmodule From d1dadfcec8e5fffb1d27f067a86a606591b9c686 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:45:09 -0700 Subject: [PATCH 011/160] Call opt_expr -mux_undef to get rid of 1'bx in muxes prior to abc --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7b20a7132..f1e887df8 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -299,6 +299,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_luts")) { + run("opt_expr -mux_undef"); if (abc == "abc9") run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + XC7_WIRE_DELAY + string(retime ? " -dff" : "")); else if (help_mode) From 7dca8def52fdd3a0e450d3f554c328904636798d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 17:29:45 -0700 Subject: [PATCH 012/160] Fix issue with part of PI being 1'bx --- frontends/aiger/aigerparse.cc | 10 ++++++---- tests/simple_abc9/abc9.v | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b98b36319..1235af142 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -944,11 +944,13 @@ void AigerReader::post_process() if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_input) - module->connect(other_wire, SigSpec(wire, i)); - else - module->connect(SigSpec(wire, i), other_wire); } + if (wire->port_input && other_wire) + module->connect(other_wire, SigSpec(wire, i)); + else + // Since we skip POs that are connected to Sx, + // re-connect them here + module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); } } diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 0b83c34a3..64b625efe 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -262,3 +262,8 @@ endmodule module abc9_test025(input [3:0] i, output [3:0] o); abc9_test024_sub a(i[2:1], o[2:1]); endmodule + +module abc9_test026(output [3:0] o, p); +assign o = { 1'b1, 1'bx }; +assign p = { 1'b1, 1'bx, 1'b0 }; +endmodule From a0566b03ecfb13fba693d35e8af16913b45444c7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:06:51 -0700 Subject: [PATCH 013/160] Run simple_abc9 tests --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index fb0eaf14d..fd4e90c15 100644 --- a/Makefile +++ b/Makefile @@ -681,6 +681,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +cd tests/opt && bash run-test.sh +cd tests/aiger && bash run-test.sh + +cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" From c421d48d6d5519b24b4596d695c3cf7c43b468f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:27:00 -0700 Subject: [PATCH 014/160] Fix broken abc9.v test due to inout being 1'bx --- backends/aiger/xaiger.cc | 13 +++++++++++-- frontends/aiger/aigerparse.cc | 13 ++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42f54209b..f0a9ccdb9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -75,6 +75,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + bool omode = false; int mkgate(int a0, int a1) { @@ -409,9 +410,9 @@ struct XAigerWriter // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(input_bits.count(bit) && output_bits.count(bit)); + log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) @@ -486,6 +487,12 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } + + if (output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + omode = true; + } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -741,6 +748,8 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + if (omode && output_bits.empty()) + f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 1235af142..d50a38b7a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -836,6 +836,10 @@ void AigerReader::post_process() RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); + if (escaped_s == "$__dummy__") { + wire->port_output = false; + continue; + } if (index == 0) { // Cope with the fact that a CO might be identical @@ -945,12 +949,15 @@ void AigerReader::post_process() other_wire->port_input = false; other_wire->port_output = false; } - if (wire->port_input && other_wire) - module->connect(other_wire, SigSpec(wire, i)); - else + if (wire->port_input) { + if (other_wire) + module->connect(other_wire, SigSpec(wire, i)); + } + else { // Since we skip POs that are connected to Sx, // re-connect them here module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx)); + } } } From 494610911ae2a5b2b73d0f5e030f237df56d3fb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:31:22 -0700 Subject: [PATCH 015/160] Fix different abc9 test --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f0a9ccdb9..55a95d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -406,13 +406,14 @@ struct XAigerWriter } for (auto bit : input_bits) { + if (!output_bits.count(bit)) + continue; RTLIL::Wire *wire = bit.wire; // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) From 242b72d4e11b815d0ca4fa80eee2e112333608d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:37:03 -0700 Subject: [PATCH 016/160] Fix simple_abc9/generate test with 1'bx at MSB --- passes/techmap/abc9.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f652cdf12..3f7efa800 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -492,7 +492,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (w->port_output) { RTLIL::Wire *wire = module->wire(w->name); log_assert(wire); - for (int i = 0; i < GetSize(wire); i++) + for (int i = 0; i < GetSize(w); i++) output_bits.insert({wire, i}); } } From b810bf26ab9e40e8d7e5a5001ac3a1708309a30b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:40:17 -0700 Subject: [PATCH 017/160] 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 06bf2ea5621ba5f18aea0fbcb788a041309e0148 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:53:27 -0700 Subject: [PATCH 018/160] Fix gcc warning of potentially uninitialised --- passes/techmap/abc9.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3f7efa800..b904b66c1 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -522,7 +522,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto c : mapped_mod->cells()) { if (c->type == "$_NOT_") { - RTLIL::Cell *cell; + RTLIL::Cell *cell = nullptr; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); if (!a_bit.wire) { @@ -576,7 +576,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); cell_stats[RTLIL::unescape_id(c->type)]++; } - if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; From d2076aa6595b5448bc151a22710822a6fb314c55 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:55:08 -0700 Subject: [PATCH 019/160] Fix gcc error, due to dict invalidation during recursion --- Makefile | 4 ++-- backends/aiger/xaiger.cc | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fd4e90c15..f363be208 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -CONFIG := clang -# CONFIG := gcc +# CONFIG := clang +CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 82f0f24b2..32c3f9045 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -101,12 +101,13 @@ struct XAigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) { log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = 0; + aig_map[bit] = aig_map.at(State::S0); } } From eb13663698aa52593e53fae58bd1dfa01136fe08 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:56:02 -0700 Subject: [PATCH 020/160] 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 a9ce9193a19352e63197984df00c3cf31a4974e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:09:13 -0700 Subject: [PATCH 021/160] Refactor bit2aig for less lookups --- backends/aiger/xaiger.cc | 53 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32c3f9045..48e902666 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,33 +86,36 @@ struct XAigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } - - if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = aig_map.at(State::S0); - } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + int a = -1; + if (not_map.count(bit)) { + a = bit2aig(not_map.at(bit)) ^ 1; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + a = aig_map.at(State::S0); + } + + log_assert(a >= 0); + aig_map[bit] = a; + return a; } XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) From 6f6a7428f2358a4dc94120ebe740dacb67ce06b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:28:55 -0700 Subject: [PATCH 022/160] Revert Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f363be208..fd4e90c15 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -# CONFIG := clang -CONFIG := gcc +CONFIG := clang +# CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc From 531d36336d1fd669ff89159ac5c4519c27761138 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:29:40 -0700 Subject: [PATCH 023/160] 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 21fa8972f3d04f717d0d4afbfa252e842c807619 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 10:40:18 -0700 Subject: [PATCH 024/160] autotest.sh to cat *.err on error --- tests/tools/autotest.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 96d9cdda9..d90abf848 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -226,6 +226,7 @@ do if $warn_iverilog_git; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi + cat ${bn}.err $keeprunning || exit 1 fi done From dd22edcd28f2ef9411dde9a941f1fefe05d7bff1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:12:32 -0700 Subject: [PATCH 025/160] Expand synth -coarse without wreduce, move muxcover --- techlibs/xilinx/synth_xilinx.cc | 36 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f1e887df8..ede2bda10 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -218,15 +218,25 @@ struct SynthXilinxPass : public ScriptPass run(stringf("hierarchy -check %s", top_opt.c_str())); } - if (check_label("flatten", "(with '-flatten' only)")) { - if (flatten || help_mode) { - run("proc"); - run("flatten"); - } - } - if (check_label("coarse")) { - run("synth -run coarse"); + run("proc"); + if (flatten || help_mode) + run("flatten", "(with -flatten only)"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt"); + // FIXME + //run("wreduce"); + run("peepopt"); + run("opt_clean"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); //if (!nomux || help_mode) // run("muxpack", "(skip if '-nomux')"); @@ -259,16 +269,20 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + run("opt -fast"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); + if (!nomux || help_mode) { + run("simplemap t:$mux", " (skip if -nomux)"); + run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); + } run("opt -full"); if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here - run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); + run("simplemap t:$dff t:$dffe", " (skip if '-nosrl')"); // shregmap with '-tech xilinx' infers variable length shift regs run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } @@ -292,8 +306,6 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - if (!nomux || help_mode) - run("muxcover -mux8 -mux16", "(skip if '-nomux')"); run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); run("clean"); } From c6b4653ebe83fc5bacaeb92fe7c63a8d52bd523e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:13:01 -0700 Subject: [PATCH 026/160] Since muxcover uses MUX4s, blast them back to gates here --- techlibs/xilinx/mux_map.v | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 6ad83a488..b7ff6ca90 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -84,3 +84,10 @@ module \$shiftx (A, B, Y); end endgenerate endmodule + +module \$_MUX4_ (A, B, C, D, S, T, Y); +input A, B, C, D, S, T; +output Y; +assign Y = T ? (S ? D : C) : + (S ? B : A); +endmodule From f433a523742350b4bb9291ad65299015e2c81f05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:15:23 -0700 Subject: [PATCH 027/160] Add FIXME about need for -mux4 --- Makefile | 4 ++-- techlibs/xilinx/synth_xilinx.cc | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fd4e90c15..f363be208 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -CONFIG := clang -# CONFIG := gcc +# CONFIG := clang +CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ede2bda10..db3f5b7e4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -275,6 +275,8 @@ struct SynthXilinxPass : public ScriptPass run("dff2dffe"); if (!nomux || help_mode) { run("simplemap t:$mux", " (skip if -nomux)"); + // FIXME: Must specify mux4, even if we don't need it, + // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } run("opt -full"); From 70ee10b650e01b7b262baa5c6fda934fb860dfce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:41:47 -0700 Subject: [PATCH 028/160] Stab in the dark with aig_map from dict -> std::map --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 48e902666..caf292d59 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -71,7 +71,7 @@ struct XAigerWriter vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - dict aig_map; + std::map aig_map; dict ordered_outputs; vector box_list; From 950bb4c2428aa546ee6abc861e7e87fea31a4b20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: [PATCH 029/160] Move comment --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index caf292d59..0e8ea65bf 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,14 +86,15 @@ struct XAigerWriter int bit2aig(SigBit bit) { - // NB: Cannot use iterator returned from aig_map.insert() - // since this function is called recursively auto it = aig_map.find(bit); if (it != aig_map.end()) { log_assert(it->second >= 0); return it->second; } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + int a = -1; if (not_map.count(bit)) { a = bit2aig(not_map.at(bit)) ^ 1; From ea154d5ff472e4e18abc7c6328fb8072b84f6582 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:46:55 -0700 Subject: [PATCH 030/160] No point logging constant bit --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0e8ea65bf..b7a5d5761 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -110,7 +110,7 @@ struct XAigerWriter } if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n"); a = aig_map.at(State::S0); } From 638557de3ec600ebe240e2f25e337028ce453ba2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 13:28:42 -0700 Subject: [PATCH 031/160] Cat more stuff --- tests/tools/autotest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index d90abf848..7b1fb50b9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -227,6 +227,8 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi cat ${bn}.err + cat ${bn}_ref.v + cat ${bn}_syn.v $keeprunning || exit 1 fi done From 8f59afd62d6d28059efb6caad1232254146daddd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 13:47:07 -0700 Subject: [PATCH 032/160] Revert "Stab in the dark with aig_map from dict -> std::map" This reverts commit 70ee10b650e01b7b262baa5c6fda934fb860dfce. --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b7a5d5761..6718e4f2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -71,7 +71,7 @@ struct XAigerWriter vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - std::map aig_map; + dict aig_map; dict ordered_outputs; vector box_list; From 848b023ccccc0cffa70d1aea45e558bdabb207b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:23:39 -0700 Subject: [PATCH 033/160] Workaround issues exposed by gcc-4.8 --- frontends/aiger/aigerparse.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d50a38b7a..5f236992d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -114,13 +114,20 @@ struct ConstEvalAig RTLIL::Cell *cell = sig2driver.at(output); RTLIL::SigBit sig_a = cell->getPort("\\A"); + sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); if (cell->type == "$_AND_") { RTLIL::SigSpec sig_b = cell->getPort("\\B"); + sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation + // that may occur does so here, and + // not mid insertion (below) sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end()); + if (!inputs.count(sig_b)) compute_deps(sig_b, inputs); } From 43659e7c6d15d222553a4b55723aa1e56475d51d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:24:34 -0700 Subject: [PATCH 034/160] Revert "Cat more stuff" This reverts commit 638557de3ec600ebe240e2f25e337028ce453ba2. --- tests/tools/autotest.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 7b1fb50b9..d90abf848 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -227,8 +227,6 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi cat ${bn}.err - cat ${bn}_ref.v - cat ${bn}_syn.v $keeprunning || exit 1 fi done From 1845b762b6e1f91c2a4eeb807089945e7b307fc6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:24:35 -0700 Subject: [PATCH 035/160] Revert "autotest.sh to cat *.err on error" This reverts commit 21fa8972f3d04f717d0d4afbfa252e842c807619. --- tests/tools/autotest.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index d90abf848..96d9cdda9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -226,7 +226,6 @@ do if $warn_iverilog_git; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi - cat ${bn}.err $keeprunning || exit 1 fi done From e581a3e6f4c8763c6a308d1330dbf1ee4bb19499 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: [PATCH 036/160] One more workaround for gcc-4.8 --- backends/aiger/xaiger.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6718e4f2c..637c54ff9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -429,12 +429,13 @@ struct XAigerWriter module->connect(new_bit, bit); if (not_map.count(bit)) not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); + else if (and_map.count(bit)) { + //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 + and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + } else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else - //log_abort(); alias_map[new_bit] = bit; output_bits.erase(bit); output_bits.insert(new_bit); From 7acbea6b2874c40cc1e3dd4dc0dc31a3985d2abf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:38:30 -0700 Subject: [PATCH 037/160] Fix alignment --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index db3f5b7e4..567859f62 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -274,7 +274,7 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); + run("simplemap t:$mux", " (skip if -nomux)"); // FIXME: Must specify mux4, even if we don't need it, // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); From 6a0fb3035ebe7d096a22b13a2fb90de891d6ffe5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:45:51 -0700 Subject: [PATCH 038/160] Replace assert with error message --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 637c54ff9..110d727de 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -244,7 +244,8 @@ struct XAigerWriter if (c.second.is_fully_const()) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); - log_assert(is_input || is_output); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { for (auto b : c.second.bits()) { From cf4ac332e1b0a4c5cb6c795cfa4b27c2bf9c0879 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:46:45 -0700 Subject: [PATCH 039/160] Do not rename non LUT cells in abc9 --- passes/techmap/abc9.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b904b66c1..473c2b936 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -521,8 +521,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri std::map cell_stats; for (auto c : mapped_mod->cells()) { + RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { - RTLIL::Cell *cell = nullptr; RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); if (!a_bit.wire) { @@ -581,6 +581,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell_stats[RTLIL::unescape_id(c->type)]++; + RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; @@ -589,19 +590,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; continue; } + cell = module->addCell(remap_name(c->name), c->type); + } + else { + existing_cell = module->cell(c->name); + cell = module->addCell(remap_name(c->name), c->type); + module->swap_names(cell, existing_cell); } - RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - RTLIL::Cell *existing_cell = module->cell(c->name); - if (existing_cell) { - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; - } - else { - cell->parameters = c->parameters; - cell->attributes = c->attributes; - } + if (existing_cell) { + cell->parameters = existing_cell->parameters; + cell->attributes = existing_cell->attributes; + } + else { + cell->parameters = c->parameters; + cell->attributes = c->attributes; + } for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { From 9abde121103a0b004e9c9fa256951553f9bb4732 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:47:42 -0700 Subject: [PATCH 040/160] Add $__XILINX_MUXF78 to preserve entire box --- techlibs/xilinx/abc_xc7.box | 11 ++++++++--- techlibs/xilinx/cells_map.v | 16 ++++++++++++---- techlibs/xilinx/cells_sim.v | 8 ++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 8a48bad4e..a312646f7 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -1,16 +1,21 @@ # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf -# F7BMUX slower than F7AMUX +# Average across F7[AB]MUX # Inputs: I0 I1 S0 # Outputs: O -F7BMUX 1 1 3 1 -217 223 296 +F7MUX 1 1 3 1 +204 208 286 # Inputs: I0 I1 S0 # Outputs: O MUXF8 2 1 3 1 104 94 273 +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +MUXF78 10 1 6 1 +190 193 217 223 296 273 + # CARRY4 + CARRY4_[ABCD]X # Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI # Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3 diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f139dc5d5..9313df7cc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -226,7 +226,6 @@ module \$__XILINX_SHIFTX (A, B, Y); localparam num_mux8 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux8*a_width0; wire [4-1:0] T; - wire T0, T1; for (i = 0; i < 4; i++) if (i < num_mux8) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); @@ -238,9 +237,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else assign T[i] = 1'bx; - MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0)); - MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1)); - MUXF8 fpga_hard_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; @@ -274,3 +271,14 @@ input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; output Y; \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); endmodule + +`ifndef _ABC +module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); + output O; + input I0, I1, I2, I3, S0, S1; + wire T0, T1; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); +endmodule +`endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index bf7a0ed44..3163d8446 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -169,6 +169,14 @@ module MUXF8(output O, input I0, I1, S); assign O = S ? I1 : I0; endmodule +`ifdef _ABC +(* abc_box_id = 10, lib_whitebox *) +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); + assign O = S1 ? (S0 ? I3 : I2) + : (S0 ? I1 : I0); +endmodule +`endif + module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule From aa0b107afbe800e040886829d43e0b9fcb7219c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:48:20 -0700 Subject: [PATCH 041/160] synth_xilinx to use _ABC macro, and perform muxpack again --- techlibs/xilinx/synth_xilinx.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 567859f62..170b3fb07 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -206,9 +206,9 @@ struct SynthXilinxPass : public ScriptPass { if (check_label("begin")) { if (vpr) - run("read_verilog -lib -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + run("read_verilog -lib -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); else - run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v"); + run("read_verilog -lib -icells -D _ABC +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_xtra.v"); @@ -238,8 +238,8 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - //if (!nomux || help_mode) - // run("muxpack", "(skip if '-nomux')"); + if (!nomux || help_mode) + run("muxpack", " (skip if '-nomux')"); // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, @@ -308,7 +308,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); + run("techmap -map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"); run("clean"); } From 4d6fac019a9a2ca3d2f0a05eb8d08c88e04faad0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:06:13 -0700 Subject: [PATCH 042/160] Fix spacing --- techlibs/xilinx/mux_map.v | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index b7ff6ca90..4c1bb7d05 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -52,21 +52,21 @@ module \$shiftx (A, B, Y); else assign A_without_x[i] = A[i]; - if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else - // Since negative indices are out of the range of A - // and hence return 'bx, drop the sign bit - \$__XILINX_SHIFTX #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(0), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH-1'd1), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) - ); + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + // Since negative indices are out of the range of A + // and hence return 'bx, drop the sign bit + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(0), + .A_WIDTH(A_WIDTH), + .B_WIDTH($clog2(A_WIDTH*B_WIDTH)), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); end else begin if (B_WIDTH < 3 || A_WIDTH <= 4) From 44fc616fc701d698564d68a7facf210947b8bd9e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:18:14 -0700 Subject: [PATCH 043/160] Revert B_SIGNED optimisation, since only works for Y_WIDTH==1 --- techlibs/xilinx/mux_map.v | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 4c1bb7d05..89586d3c3 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -55,14 +55,13 @@ module \$shiftx (A, B, Y); if (B_SIGNED) begin if (B_WIDTH < 4 || A_WIDTH <= 4) wire _TECHMAP_FAIL_ = 1; - else - // Since negative indices are out of the range of A - // and hence return 'bx, drop the sign bit + else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 \$__XILINX_SHIFTX #( .A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), - .B_WIDTH($clog2(A_WIDTH*B_WIDTH)), + .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) From 11886c874c6655bf635655324faa3af31f1c5cf7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:18:29 -0700 Subject: [PATCH 044/160] Restore wreduce to synth_xilinx, after muxcover --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 170b3fb07..174138e6a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,6 +279,7 @@ struct SynthXilinxPass : public ScriptPass // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } + run("wreduce"); // FIXME: Moved until after muxcover from 'coarse' run("opt -full"); if (!nosrl || help_mode) { From 694d40719f7a557bd82fe3d9d245353b19349123 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:47:07 -0700 Subject: [PATCH 045/160] Fix spacing again, A_forward -> A_backward --- techlibs/xilinx/mux_map.v | 78 ++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 89586d3c3..441c02ac2 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -37,49 +37,51 @@ module \$shiftx (A, B, Y); generate genvar i; wire [A_WIDTH-1:0] A_forward; - assign A_forward[A_WIDTH-1] = A[A_WIDTH-1]; + assign A_backward[A_WIDTH-1] = A[A_WIDTH-1]; for (i = A_WIDTH-2; i >= 0; i = i - 1) if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_forward[i] = A_forward[i+1]; + assign A_backward[i] = A_backward[i+1]; else - assign A_forward[i] = A[i]; + assign A_backward[i] = A[i]; - wire [A_WIDTH-1:0] A_without_x; - assign A_without_x[0] = A_forward[0]; - for (i = 1; i < A_WIDTH; i = i + 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_without_x[i] = A_without_x[i-1]; - else - assign A_without_x[i] = A[i]; + wire [A_WIDTH-1:0] A_without_x; + assign A_without_x[0] = A_backward[0]; + for (i = 1; i < A_WIDTH; i = i + 1) + if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) + assign A_without_x[i] = A_without_x[i-1]; + else + assign A_without_x[i] = A[i]; - if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0) - // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_SHIFTX #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(0), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH-1'd1), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) - ); - end - else begin - if (B_WIDTH < 3 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else - \$__XILINX_SHIFTX #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B), .Y(Y) - ); + if (B_SIGNED) begin + if (B_WIDTH < 4 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) + // Optimisation to remove B_SIGNED if sign bit of B is constant-0 + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(0), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH-1'd1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + ); + else + wire _TECHMAP_FAIL_ = 1; + end + else begin + if (B_WIDTH < 3 || A_WIDTH <= 4) + wire _TECHMAP_FAIL_ = 1; + else + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A_without_x), .B(B), .Y(Y) + ); end endgenerate endmodule From 8bce3fb32908fd5c74b57ecb178c4d68151149e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:55:34 -0700 Subject: [PATCH 046/160] Fix spacing --- techlibs/xilinx/cells_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 9313df7cc..18c926336 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -214,7 +214,7 @@ module \$__XILINX_SHIFTX (A, B, Y); localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); if (a_widthN > 1) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); else @@ -228,7 +228,7 @@ module \$__XILINX_SHIFTX (A, B, Y); wire [4-1:0] T; for (i = 0; i < 4; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); else if (i == num_mux8 && a_widthN > 0) begin if (a_widthN > 1) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); @@ -246,7 +246,7 @@ module \$__XILINX_SHIFTX (A, B, Y); wire [(2**(B_WIDTH-4))-1:0] T; for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin if (a_widthN > 1) \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); From 29aee0989fb3a73388d4567409ad6998373edc99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:55:59 -0700 Subject: [PATCH 047/160] mux_map to no longer copy last value into 1'bx --- techlibs/xilinx/mux_map.v | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 441c02ac2..0c6b2b78c 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -35,23 +35,6 @@ module \$shiftx (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate - genvar i; - wire [A_WIDTH-1:0] A_forward; - assign A_backward[A_WIDTH-1] = A[A_WIDTH-1]; - for (i = A_WIDTH-2; i >= 0; i = i - 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_backward[i] = A_backward[i+1]; - else - assign A_backward[i] = A[i]; - - wire [A_WIDTH-1:0] A_without_x; - assign A_without_x[0] = A_backward[0]; - for (i = 1; i < A_WIDTH; i = i + 1) - if (_TECHMAP_CONSTMSK_A_[i] && _TECHMAP_CONSTVAL_A_[i] === 1'bx) - assign A_without_x[i] = A_without_x[i-1]; - else - assign A_without_x[i] = A[i]; - if (B_SIGNED) begin if (B_WIDTH < 4 || A_WIDTH <= 4) wire _TECHMAP_FAIL_ = 1; @@ -64,7 +47,7 @@ module \$shiftx (A, B, Y); .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B[B_WIDTH-2:0]), .Y(Y) + .A(A), .B(B[B_WIDTH-2:0]), .Y(Y) ); else wire _TECHMAP_FAIL_ = 1; @@ -80,7 +63,7 @@ module \$shiftx (A, B, Y); .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_without_x), .B(B), .Y(Y) + .A(A), .B(B), .Y(Y) ); end endgenerate From ed00823b41becc87b52317a82c595c398dd6d10a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 16:56:56 -0700 Subject: [PATCH 048/160] synth_xilinx to now wreduce except $mux, remove extra peepopt --- techlibs/xilinx/synth_xilinx.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 174138e6a..3d39afcde 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -226,8 +226,7 @@ struct SynthXilinxPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - // FIXME - //run("wreduce"); + run("wreduce c:* t:$mux %d"); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -247,11 +246,6 @@ struct SynthXilinxPass : public ScriptPass // Also: wide multiplexer inference benefits from this too if (!(nosrl && nomux) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); - - // Run a number of peephole optimisations, including one - // that optimises $mul cells driving $shiftx's B input - // and that aids wide mux analysis - run("peepopt"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -279,7 +273,6 @@ struct SynthXilinxPass : public ScriptPass // otherwise it will use mux8 as mux4 run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); } - run("wreduce"); // FIXME: Moved until after muxcover from 'coarse' run("opt -full"); if (!nosrl || help_mode) { From aeee9dcad7f6d5fc30f133a89c5dd6f209283c11 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:06:30 -0700 Subject: [PATCH 049/160] Simplify and comment out mux_map.v --- techlibs/xilinx/mux_map.v | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index 0c6b2b78c..c47da155d 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -18,6 +18,11 @@ * */ +// The purpose of these mapping rules is to allow preserve all (sufficiently +// wide) $shiftx cells during 'techmap' so that they can be mapped to hard +// resources, rather than being bit-blasted to gates during 'techmap' +// execution + module \$shiftx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -29,18 +34,14 @@ module \$shiftx (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; - parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; generate if (B_SIGNED) begin - if (B_WIDTH < 4 || A_WIDTH <= 4) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) + if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) // Optimisation to remove B_SIGNED if sign bit of B is constant-0 - \$__XILINX_SHIFTX #( + \$shiftx #( .A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), @@ -69,6 +70,10 @@ module \$shiftx (A, B, Y); endgenerate endmodule +// FIXME: This rule exists only because we can't block muxcover +// from using MUX4s -- if we disable MUX4 it will use MUX8s +// instead + module \$_MUX4_ (A, B, C, D, S, T, Y); input A, B, C, D, S, T; output Y; From faa2d6fc1c4bc10cda96c2dc3721df209d2d2117 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:12:34 -0700 Subject: [PATCH 050/160] Constrain wreduce only if wide mux --- techlibs/xilinx/synth_xilinx.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3d39afcde..882ebe439 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -226,7 +226,10 @@ struct SynthXilinxPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - run("wreduce c:* t:$mux %d"); + if (help_mode) + run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); + else + run("wreduce" + nomux ? "" : " c:* t:$mux %d"); run("peepopt"); run("opt_clean"); run("alumacc"); From 588196c473f79cf2e221e86f1177d363a1849dcc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: [PATCH 051/160] Add log_push()/log_pop() inside write_xaiger --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 110d727de..23132f108 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -665,6 +665,8 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { + log_push(); + // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); holes_module->check(); @@ -701,6 +703,8 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); + + log_pop(); } } From 39e0e006d5a6b1ae45d95d75895284e3c48f47d7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 18:12:07 -0700 Subject: [PATCH 052/160] Fix wreduce call (!!!), tweak muxcover costs --- techlibs/xilinx/synth_xilinx.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 882ebe439..9724dff94 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -229,7 +229,7 @@ struct SynthXilinxPass : public ScriptPass if (help_mode) run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); else - run("wreduce" + nomux ? "" : " c:* t:$mux %d"); + run("wreduce" + std::string(nomux ? "" : " c:* t:$mux %d")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -271,10 +271,11 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); - // FIXME: Must specify mux4, even if we don't need it, - // otherwise it will use mux8 as mux4 - run("muxcover -mux4=150 -mux8=200 -mux16=250 -dmux=0", "(skip if -nomux)"); + run("simplemap t:$mux", " (skip if -nomux)"); + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + run("muxcover -mux8=350 -mux16=400 -dmux=0", "(skip if -nomux)"); } run("opt -full"); From bbf3ad90f59a5b548d263c81ca83ca8f93f1c238 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 18:12:33 -0700 Subject: [PATCH 053/160] Remove $_MUX4_ techmap rule --- techlibs/xilinx/mux_map.v | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index c47da155d..e28070359 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -69,14 +69,3 @@ module \$shiftx (A, B, Y); end endgenerate endmodule - -// FIXME: This rule exists only because we can't block muxcover -// from using MUX4s -- if we disable MUX4 it will use MUX8s -// instead - -module \$_MUX4_ (A, B, C, D, S, T, Y); -input A, B, C, D, S, T; -output Y; -assign Y = T ? (S ? D : C) : - (S ? B : A); -endmodule From 36e6da53964b406ad379a60fc289aa3af9beb8a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 10:04:01 -0700 Subject: [PATCH 054/160] Change synth_xilinx's -nomux to -minmuxf --- techlibs/xilinx/cells_map.v | 66 ++++++++++++++++++++------------ techlibs/xilinx/mux_map.v | 2 +- techlibs/xilinx/synth_xilinx.cc | 68 +++++++++++++++++++-------------- 3 files changed, 82 insertions(+), 54 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 18c926336..2eb84ce04 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -155,6 +155,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o endgenerate endmodule +`ifdef MIN_MUX_INPUTS module \$__XILINX_SHIFTX (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -207,10 +208,10 @@ module \$__XILINX_SHIFTX (A, B, Y); localparam B_WIDTH_new = $clog2(A_WIDTH_new); \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); end - else if (B_WIDTH < 3 || A_WIDTH <= 4) begin - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); + else if (A_WIDTH < `MIN_MUX_INPUTS) begin + wire _TECHMAP_FAIL_ = 1; end - else if (B_WIDTH == 3) begin + else if (A_WIDTH <= 2 ** 3) begin localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; wire T0, T1; @@ -219,47 +220,61 @@ module \$__XILINX_SHIFTX (A, B, Y); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); else assign T1 = A[A_WIDTH-1]; - MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y)); + MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[2]), .O(Y)); end - else if (B_WIDTH == 4) begin + else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux8*a_width0; wire [4-1:0] T; - for (i = 0; i < 4; i++) + for (i = 0; i < num_mux8; i++) if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 0) begin - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); + if (a_widthN > 0) begin + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:num_mux8*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux8])); else - assign T[i] = 1'bx; + assign T[num_mux8] = A[A_WIDTH-1]; + end + else + assign T[num_mux8] = 1'bx; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) - if (i < num_mux16) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - else if (i == num_mux16 && a_widthN > 0) begin - if (a_widthN > 1) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + wire [num_mux16-1:0] T; + for (i = 0; i < num_mux16; i++) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + if (a_widthN > 0) begin + if (a_widthN > 1) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:num_mux16*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); else - assign T[i] = 1'bx; + assign T[num_mux16] = A[A_WIDTH-1]; + end + else + assign T[num_mux16] = 1'bx; \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule +(* techmap_celltype = "$__XILINX_SHIFTX" *) +module _90__XILINX_SHIFTX (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); +endmodule + module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); input A, B, C, D, E, F, G, H, S, T, U; output Y; @@ -271,6 +286,7 @@ input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; output Y; \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); endmodule +`endif `ifndef _ABC module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v index e28070359..91aaf2118 100644 --- a/techlibs/xilinx/mux_map.v +++ b/techlibs/xilinx/mux_map.v @@ -54,7 +54,7 @@ module \$shiftx (A, B, Y); wire _TECHMAP_FAIL_ = 1; end else begin - if (B_WIDTH < 3 || A_WIDTH <= 4) + if (((A_WIDTH + Y_WIDTH - 1) / Y_WIDTH) < `MIN_MUX_INPUTS) wire _TECHMAP_FAIL_ = 1; else \$__XILINX_SHIFTX #( diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 9724dff94..2cf28fce1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -73,8 +73,10 @@ struct SynthXilinxPass : public ScriptPass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); - log(" -nomux\n"); - log(" disable inference of wide multiplexers\n"); + log(" -minmuxf \n"); + log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); + log(" above this number of inputs (minimum value 5).\n"); + log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); @@ -97,7 +99,8 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, abc, arch; - bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl, nomux; + bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; + int minmuxf; void clear_flags() YS_OVERRIDE { @@ -112,8 +115,8 @@ struct SynthXilinxPass : public ScriptPass nobram = false; nodram = false; nosrl = false; - nomux = false; arch = "xc7"; + minmuxf = 0; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -176,8 +179,8 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } - if (args[argidx] == "-nomux") { - nomux = true; + if (args[argidx] == "-minmuxf" && argidx+1 < args.size()) { + minmuxf = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-abc9") { @@ -191,6 +194,9 @@ struct SynthXilinxPass : public ScriptPass if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s") log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str()); + if (minmuxf != 0 && minmuxf < 5) + log_cmd_error("-minmuxf value must be 0 or >= 5.\n"); + if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -227,9 +233,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(no selection if -nomux)"); + run("wreduce [c:* t:$mux %d]", "(selection for '-minmuxf' only)"); else - run("wreduce" + std::string(nomux ? "" : " c:* t:$mux %d")); + run("wreduce" + std::string(minmuxf > 0 ? " c:* t:$mux %d" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -240,15 +246,15 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - if (!nomux || help_mode) - run("muxpack", " (skip if '-nomux')"); + if (minmuxf > 0 || help_mode) + run("muxpack", " ('-minmuxf' only)"); // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!(nosrl && nomux) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')"); + if (!(nosrl && minmuxf == 0) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-minmuxf' < 5)"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -270,12 +276,15 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (!nomux || help_mode) { - run("simplemap t:$mux", " (skip if -nomux)"); - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - run("muxcover -mux8=350 -mux16=400 -dmux=0", "(skip if -nomux)"); + if (minmuxf > 0 || help_mode) { + run("simplemap t:$mux", " ('-minmuxf' only)"); + if (minmuxf > 0 || help_mode) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + std::string muxcover_args = " -dmux=0 -mux8=350 -mux16=400"; + run("muxcover " + muxcover_args, "('-minmuxf' only)"); + } } run("opt -full"); @@ -287,26 +296,29 @@ struct SynthXilinxPass : public ScriptPass run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); } - std::string techmap_files = " -map +/techmap.v"; + std::string techmap_args = " -map +/techmap.v"; if (help_mode) - techmap_files += " [-map +/xilinx/mux_map.v]"; - else if (!nomux) - techmap_files += " -map +/xilinx/mux_map.v"; + techmap_args += " [-map +/xilinx/mux_map.v]"; + else if (minmuxf > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", minmuxf); if (help_mode) - techmap_files += " [-map +/xilinx/arith_map.v]"; + techmap_args += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { - techmap_files += " -map +/xilinx/arith_map.v"; + techmap_args += " -map +/xilinx/arith_map.v"; if (vpr) - techmap_files += " -D _EXPLICIT_CARRY"; + techmap_args += " -D _EXPLICIT_CARRY"; else if (abc == "abc9") - techmap_files += " -D _CLB_CARRY"; + techmap_args += " -D _CLB_CARRY"; } - run("techmap " + techmap_files); + run("techmap " + techmap_args); run("opt -fast"); } if (check_label("map_cells")) { - run("techmap -map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"); + std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; + if (minmuxf > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", minmuxf); + run("techmap " + techmap_args); run("clean"); } From c2387394e32e7a4513076b5d81beb499ceea2542 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 11:50:37 -0700 Subject: [PATCH 055/160] Revert Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f363be208..fd4e90c15 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -# CONFIG := clang -CONFIG := gcc +CONFIG := clang +# CONFIG := gcc # CONFIG := gcc-4.8 # CONFIG := afl-gcc # CONFIG := emcc From aa1eeda567d09e2d2ffd40cd008d0166d2910273 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 11:51:55 -0700 Subject: [PATCH 056/160] Modify costs for muxcover --- techlibs/xilinx/synth_xilinx.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2cf28fce1..a84f54e99 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,7 +282,21 @@ struct SynthXilinxPass : public ScriptPass // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented // out of mux2s - std::string muxcover_args = " -dmux=0 -mux8=350 -mux16=400"; + std::string muxcover_args = " -dmux=0"; + switch (minmuxf) { + case 5: muxcover_args += " -mux8=350 -mux16=400"; break; + case 6: muxcover_args += " -mux8=450 -mux16=500"; break; + case 7: muxcover_args += " -mux8=550 -mux16=600"; break; + case 8: muxcover_args += " -mux8=650 -mux16=700"; break; + case 9: muxcover_args += " -mux16=750"; break; + case 10: muxcover_args += " -mux16=850"; break; + case 11: muxcover_args += " -mux16=950"; break; + case 12: muxcover_args += " -mux16=1050"; break; + case 13: muxcover_args += " -mux16=1150"; break; + case 14: muxcover_args += " -mux16=1250"; break; + case 15: muxcover_args += " -mux16=1350"; break; + default: muxcover_args += " -mux16=1450"; break; + } run("muxcover " + muxcover_args, "('-minmuxf' only)"); } } From 2b4501503d05beaecc0f995d0681ff43e2c6fba4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 12:18:17 -0700 Subject: [PATCH 057/160] Fix mux techmapping --- techlibs/xilinx/cells_map.v | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 2eb84ce04..85f174d3d 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -226,35 +226,36 @@ module \$__XILINX_SHIFTX (A, B, Y); localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux8*a_width0; - wire [4-1:0] T; - for (i = 0; i < num_mux8; i++) + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; i++) if (i < num_mux8) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - if (a_widthN > 0) begin - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1:num_mux8*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux8])); + else if (i == num_mux8 && a_widthN > 0) begin + if (a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end else - assign T[num_mux8] = A[A_WIDTH-1]; - end - else - assign T[num_mux8] = 1'bx; + assign T[i] = 1'bx; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [num_mux16-1:0] T; - for (i = 0; i < num_mux16; i++) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - if (a_widthN > 0) begin - if (a_widthN > 1) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:num_mux16*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; i++) + if (i < num_mux16) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + else if (i == num_mux16 && a_widthN > 0) begin + if (a_widthN > 1) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); + else + assign T[i] = A[A_WIDTH-1]; + end else - assign T[num_mux16] = A[A_WIDTH-1]; - end - else - assign T[num_mux16] = 1'bx; + assign T[i] = 1'bx; \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate From 0aae3b4f4361db6d2c6b9c8d69df041f40519cec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 12:50:48 -0700 Subject: [PATCH 058/160] Fix techmapping muxes some more --- techlibs/xilinx/cells_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 85f174d3d..f4b7888b0 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; + localparam a_widthN = A_WIDTH % a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,9 +243,9 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; i++) + localparam a_widthN = A_WIDTH % a_width0; + wire [(2**(B_WIDTH-4))-1:0] T; + for (i = 0; i < 2 ** (B_WIDTH-4); i++) if (i < num_mux16) \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin From 7fbfcf20d16751f4c1eab0c33848c5c05b970992 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:15:00 -0700 Subject: [PATCH 059/160] Move comment --- techlibs/xilinx/synth_xilinx.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a84f54e99..69b1580b8 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -279,11 +279,11 @@ struct SynthXilinxPass : public ScriptPass if (minmuxf > 0 || help_mode) { run("simplemap t:$mux", " ('-minmuxf' only)"); if (minmuxf > 0 || help_mode) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s std::string muxcover_args = " -dmux=0"; switch (minmuxf) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s case 5: muxcover_args += " -mux8=350 -mux16=400"; break; case 6: muxcover_args += " -mux8=450 -mux16=500"; break; case 7: muxcover_args += " -mux8=550 -mux16=600"; break; From 2e7992efffa1d75cf69c8942d03b53e1b6ec2895 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:15:31 -0700 Subject: [PATCH 060/160] Revert "Fix techmapping muxes some more" This reverts commit 0aae3b4f4361db6d2c6b9c8d69df041f40519cec. --- techlibs/xilinx/cells_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f4b7888b0..85f174d3d 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; + localparam a_widthN = A_WIDTH - num_mux8*a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,9 +243,9 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [(2**(B_WIDTH-4))-1:0] T; - for (i = 0; i < 2 ** (B_WIDTH-4); i++) + localparam a_widthN = A_WIDTH - num_mux16*a_width0; + wire [a_width0-1:0] T; + for (i = 0; i < a_width0; i++) if (i < num_mux16) \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); else if (i == num_mux16 && a_widthN > 0) begin From db6a0b72b24022eacc84dba8b117dfb193b8d4c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 14:28:56 -0700 Subject: [PATCH 061/160] Reduce number of decomposed muxes during techmap --- techlibs/xilinx/cells_map.v | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 85f174d3d..6d9860b95 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -225,7 +225,7 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH <= 2 ** 4) begin localparam a_width0 = 2 ** 2; localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux8*a_width0; + localparam a_widthN = A_WIDTH % a_width0; wire [a_width0-1:0] T; for (i = 0; i < a_width0; i++) if (i < num_mux8) @@ -243,20 +243,17 @@ module \$__XILINX_SHIFTX (A, B, Y); else begin localparam a_width0 = 2 ** 4; localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH - num_mux16*a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; i++) - if (i < num_mux16) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - else if (i == num_mux16 && a_widthN > 0) begin - if (a_widthN > 1) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + localparam a_widthN = A_WIDTH % a_width0; + wire [num_mux16 + (a_widthN > 0 ? 1 : 0) - 1:0] T; + for (i = 0; i < num_mux16; i++) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); + if (a_widthN > 0) begin + if (a_widthN > 1) + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); else - assign T[i] = 1'bx; - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + assign T[num_mux16] = A[A_WIDTH-1]; + end + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(num_mux16 + (a_widthN > 0 ? 1 : 0)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); end endgenerate endmodule From c3df895bf464fd651c4d634ecb58ba78ca572f5f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 15:16:44 -0700 Subject: [PATCH 062/160] Reduce MuxFx resources in mux techmapping --- techlibs/xilinx/cells_map.v | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 6d9860b95..bc0455b0c 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -230,14 +230,10 @@ module \$__XILINX_SHIFTX (A, B, Y); for (i = 0; i < a_width0; i++) if (i < num_mux8) \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 0) begin - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - end + else if (i == num_mux8 && a_widthN > 1) + \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else - assign T[i] = 1'bx; + assign T[i] = A[A_WIDTH-1]; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin @@ -291,8 +287,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); + parameter _TECHMAP_BITS_CONNMAP_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; + else + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; + else + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From e1ba25d79f0fc623006b250e72093199d0804d52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 22:54:35 -0700 Subject: [PATCH 063/160] Add RAM32X1D box info --- techlibs/xilinx/abc_xc7.box | 11 +++++++++-- techlibs/xilinx/cells_sim.v | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index dafef9fef..39c535303 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -35,16 +35,23 @@ CARRY4 3 1 10 8 592 540 520 356 - 512 548 292 - 228 580 526 507 398 385 508 528 378 380 114 +# SLICEM/A6LUT +# Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE +# Outputs: DPO SPO +RAM32X1D 4 0 13 2 +- - - - - - 124 124 124 124 124 - - +124 124 124 124 124 - - - - - - - - + # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO -RAM64X1D 4 0 15 2 +RAM64X1D 5 0 15 2 - - - - - - - 124 124 124 124 124 124 - - 124 124 124 124 124 124 - - - - - - 124 - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO -RAM128X1D 5 0 17 2 +RAM128X1D 6 0 17 2 - - - - - - - - 314 314 314 314 314 314 292 - - 347 347 347 347 347 347 296 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index c6c49c3cd..e3391da40 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -289,6 +289,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule +(* abc_box_id = 4, abc_scc_break="D" *) module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, @@ -306,7 +307,7 @@ module RAM32X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 4, abc_scc_break="D" *) +(* abc_box_id = 5, abc_scc_break="D" *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -324,7 +325,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 5, abc_scc_break="D" *) +(* abc_box_id = 6, abc_scc_break="D" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 158325956e6bf711137e6198fb88e95a1e6250b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:05:28 -0700 Subject: [PATCH 064/160] Realistic delays for RAM32X1D too --- techlibs/xilinx/abc_xc7.box | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index c95ba4969..67d1ffb1e 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -39,8 +39,8 @@ CARRY4 3 1 10 8 # Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE # Outputs: DPO SPO RAM32X1D 4 0 13 2 -- - - - - - 124 124 124 124 124 - - -124 124 124 124 124 - - - - - - - - +- - - - - - 631 472 407 238 127 - - +631 472 407 238 127 - - - - - - - - # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE From 5b89553a1f1a3b3ec1667cadd34dc1939ebe67c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 24 Jun 2019 23:37:01 -0700 Subject: [PATCH 065/160] nullptr check --- passes/techmap/abc9.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f90834aa9..0312e3e1f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -124,6 +124,7 @@ void handle_loops(RTLIL::Design *design) RTLIL::SigSpec sig; for (auto b : it->second) { Wire *w = b.wire; + if (!w) continue; if (w->port_output) { log_assert(w->get_bool_attribute("\\abc_scc_break")); w = module->wire(stringf("%s.abci", w->name.c_str())); From 4238feed81920a21e48c4274f93e5c1b4f009389 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 25 Jun 2019 09:21:46 -0700 Subject: [PATCH 066/160] This optimisation doesn't seem to work... --- techlibs/xilinx/cells_map.v | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index bc0455b0c..61c2c8f94 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -287,32 +287,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; - parameter _TECHMAP_BITS_CONNMAP_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; - parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S0_ = 0; - parameter _TECHMAP_CONSTVAL_S0_ = 0; - parameter _TECHMAP_CONSTMSK_S1_ = 0; - parameter _TECHMAP_CONSTVAL_S1_ = 0; - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T0 = I1; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign T0 = I0; - else +// parameter _TECHMAP_BITS_CONNMAP_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; +// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; +// parameter _TECHMAP_CONSTMSK_S0_ = 0; +// parameter _TECHMAP_CONSTVAL_S0_ = 0; +// parameter _TECHMAP_CONSTMSK_S1_ = 0; +// parameter _TECHMAP_CONSTVAL_S1_ = 0; +// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +// assign T0 = I1; +// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) +// assign T0 = I0; +// else MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T1 = I3; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign T1 = I2; - else +// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +// assign T1 = I3; +// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) +// assign T1 = I2; +// else MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) - assign O = T1; - else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) - assign O = T0; - else +// if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) +// assign O = T1; +// else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) +// assign O = T0; +// else MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From 177c26ca359f85d0804c62f73e1df1665ffd1ec5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 09:16:45 -0700 Subject: [PATCH 067/160] Rename -minmuxf to -widemux --- techlibs/xilinx/synth_xilinx.cc | 46 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 69b1580b8..4367f2b99 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -73,7 +73,7 @@ struct SynthXilinxPass : public ScriptPass log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); - log(" -minmuxf \n"); + log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); log(" above this number of inputs (minimum value 5).\n"); log(" default: 0 (no inference)\n"); @@ -100,7 +100,7 @@ struct SynthXilinxPass : public ScriptPass std::string top_opt, edif_file, blif_file, abc, arch; bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl; - int minmuxf; + int widemux; void clear_flags() YS_OVERRIDE { @@ -116,7 +116,7 @@ struct SynthXilinxPass : public ScriptPass nodram = false; nosrl = false; arch = "xc7"; - minmuxf = 0; + widemux = 0; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -179,8 +179,8 @@ struct SynthXilinxPass : public ScriptPass nosrl = true; continue; } - if (args[argidx] == "-minmuxf" && argidx+1 < args.size()) { - minmuxf = atoi(args[++argidx].c_str()); + if (args[argidx] == "-widemux" && argidx+1 < args.size()) { + widemux = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-abc9") { @@ -194,8 +194,8 @@ struct SynthXilinxPass : public ScriptPass if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s") log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str()); - if (minmuxf != 0 && minmuxf < 5) - log_cmd_error("-minmuxf value must be 0 or >= 5.\n"); + if (widemux != 0 && widemux < 5) + log_cmd_error("-widemux value must be 0 or >= 5.\n"); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -233,9 +233,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(selection for '-minmuxf' only)"); + run("wreduce [c:* t:$mux %d]", "(selection for '-widemux' only)"); else - run("wreduce" + std::string(minmuxf > 0 ? " c:* t:$mux %d" : "")); + run("wreduce" + std::string(widemux > 0 ? " c:* t:$mux %d" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); @@ -246,15 +246,15 @@ struct SynthXilinxPass : public ScriptPass run("memory -nomap"); run("opt_clean"); - if (minmuxf > 0 || help_mode) - run("muxpack", " ('-minmuxf' only)"); + if (widemux > 0 || help_mode) + run("muxpack", " ('-widemux' only)"); // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!(nosrl && minmuxf == 0) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-minmuxf' < 5)"); + if (!(nosrl && widemux == 0) || help_mode) + run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -272,15 +272,15 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast"); + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (minmuxf > 0 || help_mode) { - run("simplemap t:$mux", " ('-minmuxf' only)"); - if (minmuxf > 0 || help_mode) { + if (widemux > 0 || help_mode) { + run("simplemap t:$mux", " ('-widemux' only)"); + if (widemux > 0 || help_mode) { std::string muxcover_args = " -dmux=0"; - switch (minmuxf) { + switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented // out of mux2s @@ -297,7 +297,7 @@ struct SynthXilinxPass : public ScriptPass case 15: muxcover_args += " -mux16=1350"; break; default: muxcover_args += " -mux16=1450"; break; } - run("muxcover " + muxcover_args, "('-minmuxf' only)"); + run("muxcover " + muxcover_args, "('-widemux' only)"); } } run("opt -full"); @@ -313,8 +313,8 @@ struct SynthXilinxPass : public ScriptPass std::string techmap_args = " -map +/techmap.v"; if (help_mode) techmap_args += " [-map +/xilinx/mux_map.v]"; - else if (minmuxf > 0) - techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", minmuxf); + else if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux); if (help_mode) techmap_args += " [-map +/xilinx/arith_map.v]"; else if (!nocarry) { @@ -330,8 +330,8 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_cells")) { std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; - if (minmuxf > 0) - techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", minmuxf); + if (widemux > 0) + techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); run("techmap " + techmap_args); run("clean"); } From 4d0014d1b1a9e747389172b94a45a7dd4af86c6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:23:57 -0700 Subject: [PATCH 068/160] Cleanup abc_box_id --- techlibs/xilinx/abc_xc7.box | 10 +++++----- techlibs/xilinx/cells_sim.v | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 67d1ffb1e..b1c24ed24 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -16,7 +16,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O -MUXF78 10 1 6 1 +MUXF78 3 1 6 1 190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X @@ -25,7 +25,7 @@ MUXF78 10 1 6 1 # (NB: carry chain input/output must be last # input/output and have been moved there # overriding the alphabetical ordering) -CARRY4 3 1 10 8 +CARRY4 4 1 10 8 482 - - - - 223 - - - 222 598 407 - - - 400 205 - - 334 584 556 537 - - 523 558 226 - 239 @@ -38,20 +38,20 @@ CARRY4 3 1 10 8 # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE # Outputs: DPO SPO -RAM32X1D 4 0 13 2 +RAM32X1D 5 0 13 2 - - - - - - 631 472 407 238 127 - - 631 472 407 238 127 - - - - - - - - # SLICEM/A6LUT # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Outputs: DPO SPO -RAM64X1D 5 0 15 2 +RAM64X1D 6 0 15 2 - - - - - - - 642 631 472 407 238 127 - - 642 631 472 407 238 127 - - - - - - - - - # SLICEM/A6LUT + F7[AB]MUX # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE # Outputs: DPO SPO -RAM128X1D 6 0 17 2 +RAM128X1D 7 0 17 2 - - - - - - - - 1009 998 839 774 605 494 450 - - 1047 1036 877 812 643 532 478 - - - - - - - - - - diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index e3391da40..58e9c74d5 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -170,7 +170,7 @@ module MUXF8(output O, input I0, I1, S); endmodule `ifdef _ABC -(* abc_box_id = 10, lib_whitebox *) +(* abc_box_id = 3, lib_whitebox *) module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); assign O = S1 ? (S0 ? I3 : I2) : (S0 ? I1 : I0); @@ -181,7 +181,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, abc_carry, lib_whitebox *) +(* abc_box_id = 4, abc_carry, lib_whitebox *) module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; @@ -289,7 +289,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE); always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule -(* abc_box_id = 4, abc_scc_break="D" *) +(* abc_box_id = 5, abc_scc_break="D" *) module RAM32X1D ( output DPO, SPO, input D, WCLK, WE, @@ -307,7 +307,7 @@ module RAM32X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 5, abc_scc_break="D" *) +(* abc_box_id = 6, abc_scc_break="D" *) module RAM64X1D ( output DPO, SPO, input D, WCLK, WE, @@ -325,7 +325,7 @@ module RAM64X1D ( always @(posedge clk) if (WE) mem[a] <= D; endmodule -(* abc_box_id = 6, abc_scc_break="D" *) +(* abc_box_id = 7, abc_scc_break="D" *) module RAM128X1D ( output DPO, SPO, input D, WCLK, WE, From 8d8261c71fd34de7eb4cb5ae7bdb2592f33ed852 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:38:28 -0700 Subject: [PATCH 069/160] Do not call opt with -full before muxcover --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0372cb43c..efa4d43f0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -288,7 +288,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + run("opt -fast"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From c762be593042ed5d812a3a37d494a82565cbaad0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 11:48:35 -0700 Subject: [PATCH 070/160] Instead of blocking wreduce on $mux, use -keepdc instead #1132 --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index efa4d43f0..278098a58 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -249,9 +249,9 @@ struct SynthXilinxPass : public ScriptPass run("check"); run("opt"); if (help_mode) - run("wreduce [c:* t:$mux %d]", "(selection for '-widemux' only)"); + run("wreduce [-keepdc]", "('-widemux' only)"); else - run("wreduce" + std::string(widemux > 0 ? " c:* t:$mux %d" : "")); + run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); run("alumacc"); From 6d9ba402632b1fd49e2c5ea63268682f126457c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 13:49:51 -0700 Subject: [PATCH 071/160] Add tests --- tests/various/muxcover.ys | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 8ef619b46..55179a991 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -188,3 +188,171 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter +## MUX2 in MUX4 :: https://github.com/YosysHQ/yosys/issues/1132 + +design -reset +read_verilog -formal < Date: Wed, 26 Jun 2019 13:50:19 -0700 Subject: [PATCH 072/160] Rework muxcover decoder gen if more significant muxes are 1'bx --- passes/techmap/muxcover.cc | 98 ++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b0722134e..0f86aeff0 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -324,13 +324,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(G, tree, bit, "BBA"); ok = ok && follow_muxtree(H, tree, bit, "BBB"); - ok = ok && follow_muxtree(S1, tree, bit, "AAS"); - ok = ok && follow_muxtree(S2, tree, bit, "ABS"); - ok = ok && follow_muxtree(S3, tree, bit, "BAS"); - ok = ok && follow_muxtree(S4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4; + ok = ok && follow_muxtree(U1, tree, bit, "S"); ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); @@ -338,7 +332,14 @@ struct MuxcoverWorker if (nodecode) ok = ok && T1 == T2; - ok = ok && follow_muxtree(U1, tree, bit, "S"); + ok = ok && follow_muxtree(S1, tree, bit, "AAS"); + ok = ok && follow_muxtree(S2, tree, bit, "ABS"); + ok = ok && follow_muxtree(S3, tree, bit, "BAS"); + ok = ok && follow_muxtree(S4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4; + // ^^ Should already be checked by T1 == T2 above if (ok) { @@ -353,12 +354,16 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + if (T1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + } + else + S1 = RTLIL::Sx; + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); @@ -397,6 +402,23 @@ struct MuxcoverWorker ok = ok && follow_muxtree(O, tree, bit, "BBBA"); ok = ok && follow_muxtree(P, tree, bit, "BBBB"); + ok = ok && follow_muxtree(V1, tree, bit, "S"); + + ok = ok && follow_muxtree(U1, tree, bit, "AS"); + ok = ok && follow_muxtree(U2, tree, bit, "BS"); + + if (nodecode) + ok = ok && U1 == U2; + + ok = ok && follow_muxtree(T1, tree, bit, "AAS"); + ok = ok && follow_muxtree(T2, tree, bit, "ABS"); + ok = ok && follow_muxtree(T3, tree, bit, "BAS"); + ok = ok && follow_muxtree(T4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && T1 == T2 && /*T2 == T3 &&*/ T3 == T4; + // ^^ Should already be checked by U1 == U2 above + ok = ok && follow_muxtree(S1, tree, bit, "AAAS"); ok = ok && follow_muxtree(S2, tree, bit, "AABS"); ok = ok && follow_muxtree(S3, tree, bit, "ABAS"); @@ -407,23 +429,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; - - ok = ok && follow_muxtree(T1, tree, bit, "AAS"); - ok = ok && follow_muxtree(T2, tree, bit, "ABS"); - ok = ok && follow_muxtree(T3, tree, bit, "BAS"); - ok = ok && follow_muxtree(T4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && T1 == T2 && T2 == T3 && T3 == T4; - - ok = ok && follow_muxtree(U1, tree, bit, "AS"); - ok = ok && follow_muxtree(U2, tree, bit, "BS"); - - if (nodecode) - ok = ok && U1 == U2; - - ok = ok && follow_muxtree(V1, tree, bit, "S"); + ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4 && /*S4 == S5 &&*/ S5 == S6 && /*S6 == S7 &&*/ S7 == S8; if (ok) { @@ -446,20 +452,30 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + if (U1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + + if (T1 != RTLIL::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + } + else + S1 = RTLIL::Sx; + } + else { + T1 = RTLIL::Sx; + S1 = RTLIL::Sx; + } + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From 585e6ddc6c55bcd5911124d58048701ea82da494 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 14:16:44 -0700 Subject: [PATCH 073/160] Let's not go crazy: use nonzero costs --- tests/various/muxcover.ys | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index 55179a991..fb0556675 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -200,7 +200,7 @@ prep design -save gold techmap -muxcover -mux4=0 -nodecode +muxcover -mux4=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -228,7 +228,7 @@ prep design -save gold techmap -muxcover -mux8=0 -nodecode +muxcover -mux8=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -256,7 +256,7 @@ prep design -save gold techmap -muxcover -mux8=0 -nodecode +muxcover -mux8=299 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -284,7 +284,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=99 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -312,7 +312,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=299 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ @@ -341,7 +341,7 @@ prep design -save gold techmap -muxcover -mux16=0 -nodecode +muxcover -mux16=699 -nodecode clean opt_expr -mux_bool select -assert-count 0 t:$_MUX_ From 8ef64a19e795e08fa85c8baf8a7c57067efd8e54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 15:13:25 -0700 Subject: [PATCH 074/160] Revert "Rework muxcover decoder gen if more significant muxes are 1'bx" This reverts commit b2b5cf78e21def63c54c080217d77afefba8e4c7. --- passes/techmap/muxcover.cc | 98 ++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 0f86aeff0..b0722134e 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -324,7 +324,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(G, tree, bit, "BBA"); ok = ok && follow_muxtree(H, tree, bit, "BBB"); - ok = ok && follow_muxtree(U1, tree, bit, "S"); + ok = ok && follow_muxtree(S1, tree, bit, "AAS"); + ok = ok && follow_muxtree(S2, tree, bit, "ABS"); + ok = ok && follow_muxtree(S3, tree, bit, "BAS"); + ok = ok && follow_muxtree(S4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && S1 == S2 && S2 == S3 && S3 == S4; ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); @@ -332,14 +338,7 @@ struct MuxcoverWorker if (nodecode) ok = ok && T1 == T2; - ok = ok && follow_muxtree(S1, tree, bit, "AAS"); - ok = ok && follow_muxtree(S2, tree, bit, "ABS"); - ok = ok && follow_muxtree(S3, tree, bit, "BAS"); - ok = ok && follow_muxtree(S4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4; - // ^^ Should already be checked by T1 == T2 above + ok = ok && follow_muxtree(U1, tree, bit, "S"); if (ok) { @@ -354,15 +353,11 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); - if (T1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - } - else - S1 = RTLIL::Sx; + mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -402,23 +397,6 @@ struct MuxcoverWorker ok = ok && follow_muxtree(O, tree, bit, "BBBA"); ok = ok && follow_muxtree(P, tree, bit, "BBBB"); - ok = ok && follow_muxtree(V1, tree, bit, "S"); - - ok = ok && follow_muxtree(U1, tree, bit, "AS"); - ok = ok && follow_muxtree(U2, tree, bit, "BS"); - - if (nodecode) - ok = ok && U1 == U2; - - ok = ok && follow_muxtree(T1, tree, bit, "AAS"); - ok = ok && follow_muxtree(T2, tree, bit, "ABS"); - ok = ok && follow_muxtree(T3, tree, bit, "BAS"); - ok = ok && follow_muxtree(T4, tree, bit, "BBS"); - - if (nodecode) - ok = ok && T1 == T2 && /*T2 == T3 &&*/ T3 == T4; - // ^^ Should already be checked by U1 == U2 above - ok = ok && follow_muxtree(S1, tree, bit, "AAAS"); ok = ok && follow_muxtree(S2, tree, bit, "AABS"); ok = ok && follow_muxtree(S3, tree, bit, "ABAS"); @@ -429,7 +407,23 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && S1 == S2 && /*S2 == S3 &&*/ S3 == S4 && /*S4 == S5 &&*/ S5 == S6 && /*S6 == S7 &&*/ S7 == S8; + ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; + + ok = ok && follow_muxtree(T1, tree, bit, "AAS"); + ok = ok && follow_muxtree(T2, tree, bit, "ABS"); + ok = ok && follow_muxtree(T3, tree, bit, "BAS"); + ok = ok && follow_muxtree(T4, tree, bit, "BBS"); + + if (nodecode) + ok = ok && T1 == T2 && T2 == T3 && T3 == T4; + + ok = ok && follow_muxtree(U1, tree, bit, "AS"); + ok = ok && follow_muxtree(U2, tree, bit, "BS"); + + if (nodecode) + ok = ok && U1 == U2; + + ok = ok && follow_muxtree(V1, tree, bit, "S"); if (ok) { @@ -452,30 +446,20 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + mux.cost += prepare_decode_mux(U1, U2, V1, bit); - if (U1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - - if (T1 != RTLIL::Sx) { - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - } - else - S1 = RTLIL::Sx; - } - else { - T1 = RTLIL::Sx; - S1 = RTLIL::Sx; - } - mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From 9cba05285b14ffb3433e2e9d9e44b755311562f5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:06:30 -0700 Subject: [PATCH 075/160] muxcover to be undef-sensitive when computing decoders --- passes/techmap/muxcover.cc | 63 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b0722134e..61471e446 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -151,7 +151,7 @@ struct MuxcoverWorker return true; } char port_name[3] = {'\\', *path, 0}; - return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false); + return follow_muxtree(ret_bit, tree, tree.muxes.at(bit)->getPort(port_name), path+1, false); } else { ret_bit = bit; return true; @@ -160,7 +160,7 @@ struct MuxcoverWorker int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit) { - if (A == B || sel == State::Sx) + if (A == B || sel == State::Sx || A == State::Sx || B == State::Sx) return 0; tuple key(A, B, sel); @@ -330,13 +330,15 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S4, tree, bit, "BBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4; + ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && + /*S2 == S3 && */ + (S3 == S4 || S3 == State::Sx || S4 == State::Sx); ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); if (nodecode) - ok = ok && T1 == T2; + ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx); ok = ok && follow_muxtree(U1, tree, bit, "S"); @@ -353,11 +355,12 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) + mux.cost += prepare_decode_mux(S1, S3, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -407,7 +410,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; + ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && + /*S2 == S3 &&*/ + (S3 == S4 || S3 == State::Sx || S4 == State::Sx) && + /*S4 == S5 &&*/ + (S5 == S6 || S5 == State::Sx || S6 == State::Sx) && + /*S6 == S7 &&*/ + (S7 == S8 || S7 == State::Sx || S8 == State::Sx); ok = ok && follow_muxtree(T1, tree, bit, "AAS"); ok = ok && follow_muxtree(T2, tree, bit, "ABS"); @@ -415,13 +424,15 @@ struct MuxcoverWorker ok = ok && follow_muxtree(T4, tree, bit, "BBS"); if (nodecode) - ok = ok && T1 == T2 && T2 == T3 && T3 == T4; + ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx) && + /*T2 == T3 &&*/ + (T3 == T4 || T3 == State::Sx || T4 == State::Sx); ok = ok && follow_muxtree(U1, tree, bit, "AS"); ok = ok && follow_muxtree(U2, tree, bit, "BS"); if (nodecode) - ok = ok && U1 == U2; + ok = ok && (U1 == U2 || U1 == State::Sx || U2 == State::Sx); ok = ok && follow_muxtree(V1, tree, bit, "S"); @@ -446,20 +457,28 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); - mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + if (U1 != State::Sx && U2 != State::Sx) { + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); + } + + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) { + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + } + if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) { + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + } + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx && + T3 != T4 && T3 != State::Sx && T4 != State::Sx) + mux.cost += prepare_decode_mux(S1, S5, V1, bit); + mux.selects.push_back(S1); mux.selects.push_back(T1); mux.selects.push_back(U1); From ca1fac7c4758b54feda24f28c9d46bb44fbd2cb8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:07:07 -0700 Subject: [PATCH 076/160] Add more tests --- tests/various/muxcover.ys | 152 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys index fb0556675..67e9625e6 100644 --- a/tests/various/muxcover.ys +++ b/tests/various/muxcover.ys @@ -356,3 +356,155 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + +## mux_if_bal_5_1 :: https://github.com/YosysHQ/yosys/issues/1132 + +design -reset +read_verilog -formal < Date: Wed, 26 Jun 2019 16:16:44 -0700 Subject: [PATCH 077/160] Restore sigmap wrapper --- passes/techmap/muxcover.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 61471e446..ce9d145d4 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -151,7 +151,7 @@ struct MuxcoverWorker return true; } char port_name[3] = {'\\', *path, 0}; - return follow_muxtree(ret_bit, tree, tree.muxes.at(bit)->getPort(port_name), path+1, false); + return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false); } else { ret_bit = bit; return true; From 5f807a7a5b3f4c1eae7b75ad93d90f3d202e2b6c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 16:25:48 -0700 Subject: [PATCH 078/160] Return to upstream synth_xilinx with opt -full and wreduce --- techlibs/xilinx/synth_xilinx.cc | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 278098a58..c139fb3c4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -241,26 +241,10 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { - run("proc"); - if (flatten || help_mode) - run("flatten", "(with -flatten only)"); - run("opt_expr"); - run("opt_clean"); - run("check"); - run("opt"); if (help_mode) - run("wreduce [-keepdc]", "('-widemux' only)"); + run("synth -run coarse [-flatten]", "(with '-flatten')"); else - run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); - run("peepopt"); - run("opt_clean"); - run("alumacc"); - run("share"); - run("opt"); - run("fsm"); - run("opt -fast"); - run("memory -nomap"); - run("opt_clean"); + run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -288,7 +272,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast"); + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From d7d5ea6e0cc7cc0db7bb510d3d265dafc7aa93ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:13:56 -0700 Subject: [PATCH 079/160] Remove redundant check (done further down) --- passes/techmap/muxcover.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index ce9d145d4..b162fae22 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -160,7 +160,7 @@ struct MuxcoverWorker int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit) { - if (A == B || sel == State::Sx || A == State::Sx || B == State::Sx) + if (A == B || sel == State::Sx) return 0; tuple key(A, B, sel); From dd4667ef2bfc83a45552e43d9252375df4b8fedf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:33:26 -0700 Subject: [PATCH 080/160] Emprically (even if I don't fully understand it) this passes picorv32 tb --- passes/techmap/muxcover.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index b162fae22..5642aeafc 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -459,25 +459,24 @@ struct MuxcoverWorker mux.cost += prepare_decode_mux(U1, U2, V1, bit); - if (U1 != State::Sx && U2 != State::Sx) { - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(T3, T4, U2, bit); + mux.cost += prepare_decode_mux(T1, T2, U1, bit); + mux.cost += prepare_decode_mux(T3, T4, U2, bit); + if (U1 != U2 && U1 != State::Sx && U2 != State::Sx) { mux.cost += prepare_decode_mux(T1, T3, V1, bit); - } - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) { mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - } - if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) { + if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); mux.cost += prepare_decode_mux(S7, S8, T4, bit); - mux.cost += prepare_decode_mux(S5, S7, U2, bit); + if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + + if (T1 != T3 && T1 != State::Sx && T3 != State::Sx) + mux.cost += prepare_decode_mux(S1, S5, V1, bit); } - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx && - T3 != T4 && T3 != State::Sx && T4 != State::Sx) - mux.cost += prepare_decode_mux(S1, S5, V1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); From cae69a3eddda997c04aa7c6bd642f71ee1033477 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:41:21 -0700 Subject: [PATCH 081/160] Rework help_mode for synth_xilinx -widemux --- techlibs/xilinx/synth_xilinx.cc | 45 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c139fb3c4..199d0737d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -276,29 +276,30 @@ struct SynthXilinxPass : public ScriptPass run("memory_map"); run("dffsr2dff"); run("dff2dffe"); - if (widemux > 0 || help_mode) { - run("simplemap t:$mux", " ('-widemux' only)"); - if (widemux > 0 || help_mode) { - std::string muxcover_args = " -dmux=0"; - switch (widemux) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - case 5: muxcover_args += " -mux8=350 -mux16=400"; break; - case 6: muxcover_args += " -mux8=450 -mux16=500"; break; - case 7: muxcover_args += " -mux8=550 -mux16=600"; break; - case 8: muxcover_args += " -mux8=650 -mux16=700"; break; - case 9: muxcover_args += " -mux16=750"; break; - case 10: muxcover_args += " -mux16=850"; break; - case 11: muxcover_args += " -mux16=950"; break; - case 12: muxcover_args += " -mux16=1050"; break; - case 13: muxcover_args += " -mux16=1150"; break; - case 14: muxcover_args += " -mux16=1250"; break; - case 15: muxcover_args += " -mux16=1350"; break; - default: muxcover_args += " -mux16=1450"; break; - } - run("muxcover " + muxcover_args, "('-widemux' only)"); + if (help_mode) { + run("simplemap t:$mux", " ('-widemux' only)"); + run("muxcover -dmux=0 -mux8= -mux16=, ('-widemux' only)"); + } + else if (widemux > 0) { + std::string muxcover_args = " -dmux=0"; + switch (widemux) { + // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 + // of those so that 4:1 muxes and below are implemented + // out of mux2s + case 5: muxcover_args += " -mux8=350 -mux16=400"; break; + case 6: muxcover_args += " -mux8=450 -mux16=500"; break; + case 7: muxcover_args += " -mux8=550 -mux16=600"; break; + case 8: muxcover_args += " -mux8=650 -mux16=700"; break; + case 9: muxcover_args += " -mux16=750"; break; + case 10: muxcover_args += " -mux16=850"; break; + case 11: muxcover_args += " -mux16=950"; break; + case 12: muxcover_args += " -mux16=1050"; break; + case 13: muxcover_args += " -mux16=1150"; break; + case 14: muxcover_args += " -mux16=1250"; break; + case 15: muxcover_args += " -mux16=1350"; break; + default: muxcover_args += " -mux16=1450"; break; } + run("muxcover " + muxcover_args); } run("opt -full"); From 2b104ed6c8f86a62d192b43fe3f73cc6f0b43e27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:42:50 -0700 Subject: [PATCH 082/160] Replace with --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 199d0737d..877694e8a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -277,8 +277,8 @@ struct SynthXilinxPass : public ScriptPass run("dffsr2dff"); run("dff2dffe"); if (help_mode) { - run("simplemap t:$mux", " ('-widemux' only)"); - run("muxcover -dmux=0 -mux8= -mux16=, ('-widemux' only)"); + run("simplemap t:$mux", " ('-widemux' only)"); + run("muxcover , ('-widemux' only)"); } else if (widemux > 0) { std::string muxcover_args = " -dmux=0"; From f0a1726a1ad4e14cdee81769565b80bea6cb48ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:48:49 -0700 Subject: [PATCH 083/160] Accidentally removed "simplemap $mux" --- techlibs/xilinx/synth_xilinx.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 877694e8a..c3f434c51 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -281,6 +281,7 @@ struct SynthXilinxPass : public ScriptPass run("muxcover , ('-widemux' only)"); } else if (widemux > 0) { + run("simplemap t:$mux"); std::string muxcover_args = " -dmux=0"; switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 From b9ff0503f39795a1f749c955b129d9972fe03f0a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 17:57:10 -0700 Subject: [PATCH 084/160] synth_xilinx's muxcover call to be very conservative -- -nodecode --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c3f434c51..2f3dfb012 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,7 +282,7 @@ struct SynthXilinxPass : public ScriptPass } else if (widemux > 0) { run("simplemap t:$mux"); - std::string muxcover_args = " -dmux=0"; + std::string muxcover_args = " -nodecode"; switch (widemux) { // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 // of those so that 4:1 muxes and below are implemented From 593e4a30bb76ac1b64945b7b8090bedbd0bfb228 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:09:28 -0700 Subject: [PATCH 085/160] MUXF78 -> $__MUXF78 to indicate internal --- techlibs/xilinx/abc_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 7fe8a7236..273d36573 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -16,7 +16,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O -MUXF78 3 1 6 1 +$__MUXF78 3 1 6 1 190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X From 7e0cde4acd4355bfa0ff23e14757d86d02c39b3e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 06:02:25 -0700 Subject: [PATCH 086/160] Revert muxcover.cc to master --- passes/techmap/muxcover.cc | 52 +++++++++++++------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 5642aeafc..b0722134e 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -330,15 +330,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S4, tree, bit, "BBS"); if (nodecode) - ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && - /*S2 == S3 && */ - (S3 == S4 || S3 == State::Sx || S4 == State::Sx); + ok = ok && S1 == S2 && S2 == S3 && S3 == S4; ok = ok && follow_muxtree(T1, tree, bit, "AS"); ok = ok && follow_muxtree(T2, tree, bit, "BS"); if (nodecode) - ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx); + ok = ok && T1 == T2; ok = ok && follow_muxtree(U1, tree, bit, "S"); @@ -355,12 +353,11 @@ struct MuxcoverWorker mux.inputs.push_back(G); mux.inputs.push_back(H); - mux.cost += prepare_decode_mux(T1, T2, U1, bit); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); mux.cost += prepare_decode_mux(S3, S4, T2, bit); - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) - mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + + mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); @@ -410,13 +407,7 @@ struct MuxcoverWorker ok = ok && follow_muxtree(S8, tree, bit, "BBBS"); if (nodecode) - ok = ok && (S1 == S2 || S1 == State::Sx || S2 == State::Sx) && - /*S2 == S3 &&*/ - (S3 == S4 || S3 == State::Sx || S4 == State::Sx) && - /*S4 == S5 &&*/ - (S5 == S6 || S5 == State::Sx || S6 == State::Sx) && - /*S6 == S7 &&*/ - (S7 == S8 || S7 == State::Sx || S8 == State::Sx); + ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8; ok = ok && follow_muxtree(T1, tree, bit, "AAS"); ok = ok && follow_muxtree(T2, tree, bit, "ABS"); @@ -424,15 +415,13 @@ struct MuxcoverWorker ok = ok && follow_muxtree(T4, tree, bit, "BBS"); if (nodecode) - ok = ok && (T1 == T2 || T1 == State::Sx || T2 == State::Sx) && - /*T2 == T3 &&*/ - (T3 == T4 || T3 == State::Sx || T4 == State::Sx); + ok = ok && T1 == T2 && T2 == T3 && T3 == T4; ok = ok && follow_muxtree(U1, tree, bit, "AS"); ok = ok && follow_muxtree(U2, tree, bit, "BS"); if (nodecode) - ok = ok && (U1 == U2 || U1 == State::Sx || U2 == State::Sx); + ok = ok && U1 == U2; ok = ok && follow_muxtree(V1, tree, bit, "S"); @@ -457,26 +446,19 @@ struct MuxcoverWorker mux.inputs.push_back(O); mux.inputs.push_back(P); - mux.cost += prepare_decode_mux(U1, U2, V1, bit); + mux.cost += prepare_decode_mux(S1, S2, T1, bit); + mux.cost += prepare_decode_mux(S3, S4, T2, bit); + mux.cost += prepare_decode_mux(S5, S6, T3, bit); + mux.cost += prepare_decode_mux(S7, S8, T4, bit); + mux.cost += prepare_decode_mux(S1, S3, U1, bit); + mux.cost += prepare_decode_mux(S5, S7, U2, bit); + mux.cost += prepare_decode_mux(S1, S5, V1, bit); mux.cost += prepare_decode_mux(T1, T2, U1, bit); mux.cost += prepare_decode_mux(T3, T4, U2, bit); - if (U1 != U2 && U1 != State::Sx && U2 != State::Sx) { - mux.cost += prepare_decode_mux(T1, T3, V1, bit); + mux.cost += prepare_decode_mux(T1, T3, V1, bit); - mux.cost += prepare_decode_mux(S1, S2, T1, bit); - mux.cost += prepare_decode_mux(S3, S4, T2, bit); - if (T1 != T2 && T1 != State::Sx && T2 != State::Sx) - mux.cost += prepare_decode_mux(S1, S3, U1, bit); - - mux.cost += prepare_decode_mux(S5, S6, T3, bit); - mux.cost += prepare_decode_mux(S7, S8, T4, bit); - if (T3 != T4 && T3 != State::Sx && T4 != State::Sx) - mux.cost += prepare_decode_mux(S5, S7, U2, bit); - - if (T1 != T3 && T1 != State::Sx && T3 != State::Sx) - mux.cost += prepare_decode_mux(S1, S5, V1, bit); - } + mux.cost += prepare_decode_mux(U1, U2, V1, bit); mux.selects.push_back(S1); mux.selects.push_back(T1); From af744097496702926f4fbff5d6eb889ad82fa6cf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 28 Jun 2019 10:21:16 +0200 Subject: [PATCH 087/160] Improve specify dummy parser, fixes #1144 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index d89b2dc88..dab5b5919 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1068,11 +1068,18 @@ list_of_path_delay_extra_expressions : path_delay_expression ',' path_delay_expression ',' path_delay_expression ; +specify_edge_identifier : + TOK_POSEDGE | TOK_NEGEDGE ; + parallel_path_description : - '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ; + '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' | + '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor opt_polarity_operator ':' ignspec_expr ')' ')' | + '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr ')' ')' ; full_path_description : - '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ; + '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' | + '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs opt_polarity_operator ':' ignspec_expr ')' ')' | + '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs TOK_POS_INDEXED ignspec_expr ')' ')' ; // This was broken into 2 rules to solve shift/reduce conflicts list_of_path_inputs : From dc677c791de438a493ad5e0101987da29c6a6d0f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 10:12:48 -0700 Subject: [PATCH 088/160] Add test from #1144, and try reading without '-specify' flag --- tests/various/specify.v | 14 ++++++++++++++ tests/various/specify.ys | 2 ++ 2 files changed, 16 insertions(+) diff --git a/tests/various/specify.v b/tests/various/specify.v index afc421da8..b1f399267 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -28,3 +28,17 @@ module test2 ( (B => Q) = 1.5; endspecify endmodule + +module issue01144(input clk, d, output q); +specify + // Fails: + (posedge clk => (q +: d)) = (3,1); + (/*posedge*/ clk => (q +: d)) = (3,1); + (posedge clk *> (q +: d)) = (3,1); + (/*posedge*/ clk *> (q +: d)) = (3,1); + + // Works: + (/*posedge*/ clk => q) = (3,1); + (/*posedge*/ clk *> q) = (3,1); +endspecify +endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index a5ca07219..a2b6038e4 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -54,3 +54,5 @@ equiv_struct equiv_induct -seq 5 equiv_status -assert design -reset + +read_verilog specify.v From c5b3830f737310602118851416f9c1931ad91a19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:12:41 -0700 Subject: [PATCH 089/160] Update CHANGELOG with -widemux --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 439870ac8..f10301427 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,7 +29,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - - "synth_xilinx" to now infer wide multiplexers (-nomux to disable) + - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 0d347e17089eb4b23ef444a7c9adf8420aa2c93e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:28:29 -0700 Subject: [PATCH 090/160] Replace log_assert() with meaningful log_error() --- frontends/aiger/aigerparse.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7008d0542..1ac0f7ba4 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -376,7 +376,11 @@ void AigerReader::parse_xaiger() continue; if (m->name.begins_with("$paramod")) continue; - auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name)); + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(id, m->name)); + if (!r.second) + log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); log_assert(r.second); } From cf020befeb99df2296f2efe722410e49becb44dd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 11:28:50 -0700 Subject: [PATCH 091/160] Fix CARRY4 abc_box_id --- techlibs/xilinx/cells_sim.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 94bc3ef86..3937d3536 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -181,7 +181,7 @@ module XORCY(output O, input CI, LI); assign O = CI ^ LI; endmodule -(* abc_box_id = 3, abc_carry="CI,CO", lib_whitebox *) +(* abc_box_id = 4, abc_carry="CI,CO", lib_whitebox *) module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign O = S ^ {CO[2:0], CI | CYINIT}; assign CO[0] = S[0] ? CI | CYINIT : DI[0]; From a193bf27c94153d6cf27848391f1738bacff06b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:03:43 -0700 Subject: [PATCH 092/160] Clean up trimming leading 1'bx in A during techmappnig --- techlibs/xilinx/cells_map.v | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index cce70d69e..c6e734974 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -170,19 +170,14 @@ module \$__XILINX_SHIFTX (A, B, Y); parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; - function integer compute_num_leading_X_in_A; - integer i, c; + function integer A_WIDTH_trimmed; + input integer start; begin - compute_num_leading_X_in_A = 0; - c = 1; - for (i = A_WIDTH-1; i >= 0; i=i-1) begin - if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx) - c = 0; - compute_num_leading_X_in_A = compute_num_leading_X_in_A + c; - end + A_WIDTH_trimmed = start; + while (A_WIDTH_trimmed > 0 && _TECHMAP_CONSTMSK_A_[A_WIDTH_trimmed-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH_trimmed-1] === 1'bx) + A_WIDTH_trimmed = A_WIDTH_trimmed - 1; end endfunction - localparam num_leading_X_in_A = compute_num_leading_X_in_A(); generate genvar i, j; @@ -200,11 +195,10 @@ module \$__XILINX_SHIFTX (A, B, Y); assign A_i[i] = A[i*2]; \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); end - // Trim off any leading 1'bx -es in A, and resize B accordingly - else if (num_leading_X_in_A > 0) begin - localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; - localparam B_WIDTH_new = $clog2(A_WIDTH_new); - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); + // Trim off any leading 1'bx -es in A + else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH-1] === 1'bx) begin + localparam A_WIDTH_new = A_WIDTH_trimmed(A_WIDTH-1); + \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B), .Y(Y)); end else if (A_WIDTH < `MIN_MUX_INPUTS) begin wire _TECHMAP_FAIL_ = 1; From ea0f7c9be9283e927591d1a33c2db663d3bbd82c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 12:12:41 -0700 Subject: [PATCH 093/160] Restore $__XILINX_MUXF78 const optimisation --- techlibs/xilinx/cells_map.v | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index c6e734974..b13f8d1ee 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -279,32 +279,32 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); output O; input I0, I1, I2, I3, S0, S1; wire T0, T1; -// parameter _TECHMAP_BITS_CONNMAP_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; -// parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; -// parameter _TECHMAP_CONSTMSK_S0_ = 0; -// parameter _TECHMAP_CONSTVAL_S0_ = 0; -// parameter _TECHMAP_CONSTMSK_S1_ = 0; -// parameter _TECHMAP_CONSTVAL_S1_ = 0; -// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) -// assign T0 = I1; -// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) -// assign T0 = I0; -// else + parameter _TECHMAP_BITS_CONNMAP_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; + parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; + else MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); -// if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) -// assign T1 = I3; -// else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) -// assign T1 = I2; -// else + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; + else MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); -// if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) -// assign O = T1; -// else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) -// assign O = T0; -// else + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif From dc05613613f9de1360cf21f85251b2389089a56c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 14:18:56 -0700 Subject: [PATCH 094/160] 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 85f1c2dcbe1ebd3fa609f2a9a558810dfcc8484c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 29 Jun 2019 21:42:20 -0700 Subject: [PATCH 095/160] Cleanup SRL inference/make more consistent --- techlibs/xilinx/cells_map.v | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 9a316fc96..89671c0fc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -56,7 +56,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o localparam [DEPTH-1:0] INIT_R = brev(INIT); parameter _TECHMAP_CONSTMSK_L_ = 0; - parameter _TECHMAP_CONSTVAL_L_ = 0; wire CE; generate @@ -129,26 +128,33 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); end end - else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin - // Handle cases where fixed-length depth is - // just 1 over a convenient value - \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + // For fixed length, if just 1 over a convenient value, decompose + else if (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_) begin + wire T; + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(D), .L({32{1'b1}}), .E(E), .Q(T)); + \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(T), .L(L), .E(E), .Q(Q)); end + // For variable length, if just 1 over a convenient value, then bump up one more + else if (DEPTH < 129 && ~&_TECHMAP_CONSTMSK_L_) + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); else begin - localparam lower_clog2 = $clog2((DEPTH+1)/2); - localparam lower_depth = 2 ** lower_clog2; - wire T0, T1, T2, T3; - if (&_TECHMAP_CONSTMSK_L_) begin - \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0)); - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3)); - end - else begin - \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); - assign Q = L[lower_clog2] ? T2 : T0; - end - if (DEPTH == 2 * lower_depth) - assign SO = T3; + localparam depth0 = 128; + localparam num_srl128 = DEPTH / depth0; + localparam depthN = DEPTH % depth0; + wire [num_srl128 + (depthN > 0 ? 1 : 0) - 1:0] T; + wire [num_srl128 + (depthN > 0 ? 1 : 0) :0] S; + assign S[0] = D; + genvar i; + for (i = 0; i < num_srl128; i++) + \$__XILINX_SHREG_ #(.DEPTH(depth0), .INIT(INIT[DEPTH-1-i*depth0-:depth0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(S[i]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[i]), .SO(S[i+1])); + + if (depthN > 0) + \$__XILINX_SHREG_ #(.DEPTH(depthN), .INIT(INIT[depthN-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(S[num_srl128]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[num_srl128])); + + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T[num_srl128 + (depthN > 0 ? 1 : 0) - 1]; + else + assign Q = T[L[DEPTH-1:$clog2(depth0)]]; end endgenerate endmodule From 04459cb30aff2341d6de43f7eefe5acaa4bb1db1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 30 Jun 2019 11:48:01 -0700 Subject: [PATCH 096/160] Comment out invalid syntax --- tests/various/specify.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/various/specify.v b/tests/various/specify.v index b1f399267..985879f85 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -33,9 +33,9 @@ module issue01144(input clk, d, output q); specify // Fails: (posedge clk => (q +: d)) = (3,1); - (/*posedge*/ clk => (q +: d)) = (3,1); + //(/*posedge*/ clk => (q +: d)) = (3,1); // Invalid syntax (posedge clk *> (q +: d)) = (3,1); - (/*posedge*/ clk *> (q +: d)) = (3,1); + //(/*posedge*/ clk *> (q +: d)) = (3,1); // Invalid syntax // Works: (/*posedge*/ clk => q) = (3,1); From 62fb3d5d15cedf84f6b977bf107cce56d36913af Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 09:45:51 -0700 Subject: [PATCH 097/160] Move wide mux from yosys-0.8 to 0.9 --- CHANGELOG | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7ac418160..29dc05ac0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,13 +2,6 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.9 .. Yosys 0.9-dev --------------------------- - - * Various - - Added "script -select" - - Yosys 0.9 .. Yosys 0.9-dev -------------------------- @@ -18,6 +11,8 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) + - Added "script -select" + - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) Yosys 0.8 .. Yosys 0.8-dev @@ -44,7 +39,6 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "synth_xilinx -nowidelut" - Added "synth_ecp5 -nowidelut" - "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - - "synth_xilinx" to now infer wide multiplexers (-widemux to enable) - Fixed sign extension of unsized constants with 'bx and 'bz MSB From 603fe9cda9ea6c18374ae4c5545d55b97cfa4c81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:58:41 -0700 Subject: [PATCH 098/160] Space --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 29dc05ac0..ae11b8f3c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ List of major changes and improvements between releases ======================================================= + Yosys 0.9 .. Yosys 0.9-dev -------------------------- From a9a140aa6c84e71edc1a244cfe363400c7e09d90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 13:36:27 -0700 Subject: [PATCH 099/160] Fix broken MUXFx box, use MUXF7x2 box instead --- techlibs/xilinx/abc_xc7.box | 9 +++--- techlibs/xilinx/cells_map.v | 58 ++++++++++++++++++------------------- techlibs/xilinx/cells_sim.v | 6 ++-- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 273d36573..0f24d6d66 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -14,10 +14,11 @@ F7MUX 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -# Inputs: I0 I1 I2 I3 S0 S1 -# Outputs: O -$__MUXF78 3 1 6 1 -190 193 217 223 296 273 +# Inputs: I0 I1 I2 I3 S +# Outputs: O0 O1 +$__MUXF7x2 3 1 5 2 +190 193 - - 276 +- - 217 223 296 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 27e860801..af4427dcf 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -95,7 +95,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T4; else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux7 (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S(L[5]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); end else if (DEPTH > 97 && DEPTH < 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; @@ -106,7 +108,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; @@ -116,8 +120,11 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; - else - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); + else begin + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(T7), .O1(T8)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + end end else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin // Handle cases where fixed-length depth is @@ -216,7 +223,9 @@ module \$__XILINX_SHIFTX (A, B, Y); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); + wire TA, TB; + \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T[0]), .I1(T[2]), .I2(T[4]), .I3(T[6]), .S(B[2]), .O0(TA), .O1(TB)); + MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(B[3]), .O(Q)); end else begin localparam a_width0 = 2 ** 4; @@ -265,36 +274,27 @@ endmodule `endif `ifndef _ABC -module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); - output O; - input I0, I1, I2, I3, S0, S1; - wire T0, T1; +module \$__XILINX_MUXF7x2 (O0, O1, I0, I1, I2, I3, S); + output O0, O1; + input I0, I1, I2, I3, S; parameter _TECHMAP_BITS_CONNMAP_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S0_ = 0; - parameter _TECHMAP_CONSTVAL_S0_ = 0; - parameter _TECHMAP_CONSTMSK_S1_ = 0; - parameter _TECHMAP_CONSTVAL_S1_ = 0; - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T0 = I1; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign T0 = I0; + parameter _TECHMAP_CONSTMSK_S_ = 0; + parameter _TECHMAP_CONSTVAL_S_ = 0; + if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) + assign O0 = I1; + else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign O0 = I0; else - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); - if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) - assign T1 = I3; - else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign T1 = I2; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S), .O(O0)); + if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) + assign O1 = I3; + else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign O1 = I2; else - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); - if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) - assign O = T1; - else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) - assign O = T0; - else - MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S), .O(O1)); endmodule `endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3937d3536..d1877cf1a 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -171,9 +171,9 @@ endmodule `ifdef _ABC (* abc_box_id = 3, lib_whitebox *) -module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); - assign O = S1 ? (S0 ? I3 : I2) - : (S0 ? I1 : I0); +module \$__XILINX_MUXF7x2 (output O0, O1, input I0, I1, I2, I3, S); + assign O0 = S ? I1 : I0; + assign O1 = S ? I3 : I2; endmodule `endif From 09ac27471667d1316b09984624dde981e860a94e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 14:01:09 -0700 Subject: [PATCH 100/160] Revert "Fix broken MUXFx box, use MUXF7x2 box instead" This reverts commit a9a140aa6c84e71edc1a244cfe363400c7e09d90. --- techlibs/xilinx/abc_xc7.box | 9 +++--- techlibs/xilinx/cells_map.v | 58 ++++++++++++++++++------------------- techlibs/xilinx/cells_sim.v | 6 ++-- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 0f24d6d66..273d36573 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -14,11 +14,10 @@ F7MUX 1 1 3 1 MUXF8 2 1 3 1 104 94 273 -# Inputs: I0 I1 I2 I3 S -# Outputs: O0 O1 -$__MUXF7x2 3 1 5 2 -190 193 - - 276 -- - 217 223 296 +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +$__MUXF78 3 1 6 1 +190 193 217 223 296 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index af4427dcf..27e860801 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -95,9 +95,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T4; else - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux7 (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S(L[5]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH > 97 && DEPTH < 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; @@ -108,9 +106,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; else - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; @@ -120,11 +116,8 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); if (&_TECHMAP_CONSTMSK_L_) assign Q = T6; - else begin - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S(L[5]), .O0(T7), .O1(T8)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(L[6]), .O(Q)); - end + else + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q)); end else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin // Handle cases where fixed-length depth is @@ -223,9 +216,7 @@ module \$__XILINX_SHIFTX (A, B, Y); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); else assign T[i] = A[A_WIDTH-1]; - wire TA, TB; - \$__XILINX_MUXF7x2 fpga_hard_mux (.I0(T[0]), .I1(T[2]), .I2(T[4]), .I3(T[6]), .S(B[2]), .O0(TA), .O1(TB)); - MUXF8 fpga_hard_mux8 (.I0(TA), .I1(TB), .S(B[3]), .O(Q)); + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin localparam a_width0 = 2 ** 4; @@ -274,27 +265,36 @@ endmodule `endif `ifndef _ABC -module \$__XILINX_MUXF7x2 (O0, O1, I0, I1, I2, I3, S); - output O0, O1; - input I0, I1, I2, I3, S; +module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); + output O; + input I0, I1, I2, I3, S0, S1; + wire T0, T1; parameter _TECHMAP_BITS_CONNMAP_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; - parameter _TECHMAP_CONSTMSK_S_ = 0; - parameter _TECHMAP_CONSTVAL_S_ = 0; - if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) - assign O0 = I1; - else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) - assign O0 = I0; + parameter _TECHMAP_CONSTMSK_S0_ = 0; + parameter _TECHMAP_CONSTVAL_S0_ = 0; + parameter _TECHMAP_CONSTMSK_S1_ = 0; + parameter _TECHMAP_CONSTVAL_S1_ = 0; + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T0 = I1; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) + assign T0 = I0; else - MUXF7 mux7a (.I0(I0), .I1(I1), .S(S), .O(O0)); - if (_TECHMAP_CONSTMSK_S_ && _TECHMAP_CONSTVAL_S_ === 1'b1) - assign O1 = I3; - else if (_TECHMAP_CONSTMSK_S_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) - assign O1 = I2; + MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); + if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) + assign T1 = I3; + else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) + assign T1 = I2; else - MUXF7 mux7b (.I0(I2), .I1(I3), .S(S), .O(O1)); + MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); + if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) + assign O = T1; + else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) + assign O = T0; + else + MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index d1877cf1a..3937d3536 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -171,9 +171,9 @@ endmodule `ifdef _ABC (* abc_box_id = 3, lib_whitebox *) -module \$__XILINX_MUXF7x2 (output O0, O1, input I0, I1, I2, I3, S); - assign O0 = S ? I1 : I0; - assign O1 = S ? I3 : I2; +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); + assign O = S1 ? (S0 ? I3 : I2) + : (S0 ? I1 : I0); endmodule `endif From 2ea6083b7ecea979838c2be40f5f7ef907f553d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 14:04:06 -0700 Subject: [PATCH 101/160] Fix $__XILINX_MUXF78 box timing --- techlibs/xilinx/abc_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 273d36573..3789ff350 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -17,7 +17,7 @@ MUXF8 2 1 3 1 # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O $__MUXF78 3 1 6 1 -190 193 217 223 296 273 +294 297 311 317 390 273 # CARRY4 + CARRY4_[ABCD]X # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI From 9251c000e86c1d7e757c89720f729ac984aaf901 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 2 Jul 2019 17:10:13 +0000 Subject: [PATCH 102/160] manual: explain the purpose of `sync always`. --- manual/CHAPTER_Overview.tex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 1a25c477f..3009bf2c0 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -331,8 +331,9 @@ to update {\tt \textbackslash{}q}. An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and exactly one RTLIL::CaseRule object, which is called the {\it root case}. -An RTLIL::SyncRule object contains an (optional) synchronization condition -(signal and edge-type) and zero or more assignments (RTLIL::SigSig). +An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and zero or +more assignments (RTLIL::SigSig). The {\tt always} synchronization condition is used to break combinatorial +loops when a latch should be inferred instead. An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig) and zero or more RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a From 9c556e3c02a8b25fbcd764e019e3870d021684ec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:13:40 -0700 Subject: [PATCH 103/160] Add test --- tests/various/abc9.v | 4 ++++ tests/various/abc9.ys | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/various/abc9.v b/tests/various/abc9.v index 8271cd249..a08b613a8 100644 --- a/tests/various/abc9.v +++ b/tests/various/abc9.v @@ -3,3 +3,7 @@ initial o = 1'b0; always @* o <= ~o; endmodule + +module abc9_test028(input i, output o); +unknown u(~i, o); +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 922f7005d..a84b637d9 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -1,4 +1,6 @@ read_verilog abc9.v +design -save read +hierarchy -top abc9_test027 proc design -save gold @@ -12,3 +14,11 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter +design -load read +hierarchy -top abc9_test028 +proc + +abc9 -lut 4 +select -assert-count 1 t:$lut r:LUT=1 r:WIDTH=1 %i %i +select -assert-count 1 t:unknown +select -assert-none t:$lut t:unknown %% t: %D From 10524064e94b9fe21483092e2733b1b71ae60b4e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:14:30 -0700 Subject: [PATCH 104/160] write_xaiger to treat unknown cell connections as keep-s --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index eb3d47569..869b741a6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -138,6 +138,7 @@ struct XAigerWriter { pool undriven_bits; pool unused_bits; + pool keep_bits; // promote public wires for (auto wire : module->wires()) @@ -168,6 +169,9 @@ struct XAigerWriter unused_bits.insert(bit); } + if (keep) + keep_bits.insert(bit); + if (wire->port_input || keep) { if (bit != wirebit) alias_map[bit] = wirebit; @@ -235,7 +239,7 @@ struct XAigerWriter log_assert(!holes_mode); RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -255,10 +259,11 @@ struct XAigerWriter } } else { + bool cell_known = cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); + auto is_input = !cell_known || cell->input(c.first); + auto is_output = !cell_known || cell->output(c.first); if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); @@ -266,12 +271,15 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (!w->port_output) { + if (!w->port_output || !cell_known) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; output_bits.insert(b); unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); } } } @@ -424,7 +432,7 @@ struct XAigerWriter auto jt = input_bits.find(b); if (jt != input_bits.end()) { - log_assert(b.wire->attributes.count("\\keep")); + log_assert(keep_bits.count(O)); input_bits.erase(b); } } @@ -444,7 +452,7 @@ struct XAigerWriter // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) - || wire->attributes.count("\\keep")) { + || keep_bits.count(bit)) { RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) From ba365679082cff2b9879eef5349bfdf2b5291449 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 3 Jul 2019 11:22:10 +0200 Subject: [PATCH 105/160] Some cleanups in "ignore specify parser" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 84 ++---------------------------- tests/various/specify.v | 2 +- 2 files changed, 6 insertions(+), 80 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index dab5b5919..0fec445fa 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1021,13 +1021,8 @@ list_of_specparam_assignments: specparam_assignment: ignspec_id '=' constant_mintypmax_expression ; -/* -pulsestyle_declaration : - ; - -showcancelled_declaration : - ; -*/ +ignspec_opt_cond: + TOK_IF '(' ignspec_expr ')' | /* empty */; path_declaration : simple_path_declaration ';' @@ -1036,8 +1031,8 @@ path_declaration : ; simple_path_declaration : - parallel_path_description '=' path_delay_value | - full_path_description '=' path_delay_value + ignspec_opt_cond parallel_path_description '=' path_delay_value | + ignspec_opt_cond full_path_description '=' path_delay_value ; path_delay_value : @@ -1047,26 +1042,7 @@ path_delay_value : ; list_of_path_delay_extra_expressions : -/* - t_path_delay_expression - | trise_path_delay_expression ',' tfall_path_delay_expression - | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression - | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' - tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression - | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' - tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ',' - t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ',' - tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression -*/ - ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression - | ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' - path_delay_expression ',' path_delay_expression ',' path_delay_expression - ; + ',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions; specify_edge_identifier : TOK_POSEDGE | TOK_NEGEDGE ; @@ -1119,56 +1095,6 @@ system_timing_args : system_timing_arg | system_timing_args ',' system_timing_arg ; -/* -t_path_delay_expression : - path_delay_expression; - -trise_path_delay_expression : - path_delay_expression; - -tfall_path_delay_expression : - path_delay_expression; - -tz_path_delay_expression : - path_delay_expression; - -t01_path_delay_expression : - path_delay_expression; - -t10_path_delay_expression : - path_delay_expression; - -t0z_path_delay_expression : - path_delay_expression; - -tz1_path_delay_expression : - path_delay_expression; - -t1z_path_delay_expression : - path_delay_expression; - -tz0_path_delay_expression : - path_delay_expression; - -t0x_path_delay_expression : - path_delay_expression; - -tx1_path_delay_expression : - path_delay_expression; - -t1x_path_delay_expression : - path_delay_expression; - -tx0_path_delay_expression : - path_delay_expression; - -txz_path_delay_expression : - path_delay_expression; - -tzx_path_delay_expression : - path_delay_expression; -*/ - path_delay_expression : ignspec_constant_expression; diff --git a/tests/various/specify.v b/tests/various/specify.v index 985879f85..73a59eb7a 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -7,7 +7,7 @@ module test ( if (EN) Q <= D; specify - if (EN) (CLK *> (Q : D)) = (1, 2:3:4); + if (EN) (posedge CLK *> (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); endspecify From 1f173210ebbf2cd5b5714e351ed40b6141d90b14 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 3 Jul 2019 11:25:05 +0200 Subject: [PATCH 106/160] Fix tests/various/specify.v Signed-off-by: Clifford Wolf --- tests/various/specify.v | 9 ++------- tests/various/specify.ys | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/various/specify.v b/tests/various/specify.v index 73a59eb7a..5d44d78f7 100644 --- a/tests/various/specify.v +++ b/tests/various/specify.v @@ -7,9 +7,11 @@ module test ( if (EN) Q <= D; specify +`ifndef SKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS if (EN) (posedge CLK *> (Q : D)) = (1, 2:3:4); $setup(D, posedge CLK &&& EN, 5); $hold(posedge CLK, D &&& EN, 6); +`endif endspecify endmodule @@ -31,14 +33,7 @@ endmodule module issue01144(input clk, d, output q); specify - // Fails: (posedge clk => (q +: d)) = (3,1); - //(/*posedge*/ clk => (q +: d)) = (3,1); // Invalid syntax (posedge clk *> (q +: d)) = (3,1); - //(/*posedge*/ clk *> (q +: d)) = (3,1); // Invalid syntax - - // Works: - (/*posedge*/ clk => q) = (3,1); - (/*posedge*/ clk *> q) = (3,1); endspecify endmodule diff --git a/tests/various/specify.ys b/tests/various/specify.ys index a2b6038e4..00597e1e2 100644 --- a/tests/various/specify.ys +++ b/tests/various/specify.ys @@ -55,4 +55,4 @@ equiv_induct -seq 5 equiv_status -assert design -reset -read_verilog specify.v +read_verilog -DSKIP_UNSUPPORTED_IGN_PARSER_CONSTRUCTS specify.v From 3a1a41bdb16c9cdf587147f8fb9dc910bcddfd26 Mon Sep 17 00:00:00 2001 From: Benedikt Tutzer Date: Thu, 4 Jul 2019 14:20:13 +0200 Subject: [PATCH 107/160] Throw runtime exception when trying to convert a c++-pointer to a python-object in case the pointer is a nullptr to avoid a segfault. Fixes #1090 --- misc/py_wrap_generator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 9e5727499..66d661fa1 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -779,6 +779,9 @@ class WClass: #if self.link_type != link_types.pointer: text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{" + text += "\n\t\t\tif(ref == nullptr){" + text += "\n\t\t\t\tthrow std::runtime_error(\"" + self.name + " does not exist.\");" + text += "\n\t\t\t}" text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));" if self.link_type == link_types.pointer: text += "\n\t\t\tret->ref_obj = ref;" From 4f798cda9d1b05d141e16a21b9e357de364021de Mon Sep 17 00:00:00 2001 From: Dan Ravensloft Date: Sun, 7 Jul 2019 16:00:38 +0100 Subject: [PATCH 108/160] synth_intel: Warn about untested Quartus backend --- techlibs/intel/synth_intel.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index 639cba2c2..09c9ba3af 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -48,6 +48,8 @@ struct SynthIntelPass : public ScriptPass { log(" -vqm \n"); log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); log(" output file is omitted if this parameter is not specified.\n"); + log(" Note that this backend has not been tested and is likely incompatible\n"); + log(" with recent versions of Quartus.\n"); log("\n"); log(" -vpr \n"); log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n"); @@ -108,6 +110,7 @@ struct SynthIntelPass : public ScriptPass { } if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { vout_file = args[++argidx]; + log_warning("The Quartus backend has not been tested recently and is likely incompatible with modern versions of Quartus.\n"); continue; } if (args[argidx] == "-vpr" && argidx + 1 < args.size()) { From 93bc5affd3fc635dafec3a37bf4c5b94c252036f Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 11:34:58 +0000 Subject: [PATCH 109/160] Allow attributes on individual switch cases in RTLIL. The parser changes are slightly awkward. Consider the following IL: process $0 switch \foo case 1'1 assign \bar \baz ... case end end Before this commit, attributes are valid in , and iff it is immediately followed by a `switch`. (They are essentially attached to the switch.) But, after this commit, and because switch cases do not have an ending delimiter, becomes ambiguous: the attribute could attach to either the following `case`, or to the following `switch`. This isn't expressible in LALR(1) and results in a reduce/reduce conflict. To address this, attributes inside processes are now valid anywhere inside the process: in and a part of case body, and in as a separate rule. As a consequence, attributes can now precede `assign`s, which is made illegal in the same way it is illegal to attach attributes to `connect`. Attributes are tracked separately from the parser state, so this does not affect collection of attributes at all, other than allowing them on `case`s. The grammar change serves purely to allow attributes in more syntactic places. --- backends/ilang/ilang_backend.cc | 5 +++++ frontends/ilang/ilang_parser.y | 13 +++++++++---- kernel/rtlil.h | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index b4ba2b03f..313af7d5c 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -204,6 +204,11 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) { + f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str()); + dump_const(f, ait->second); + f << stringf("\n"); + } f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 44c99906a..b4b9693da 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -282,14 +282,14 @@ proc_stmt: } case_body sync_list TOK_END EOL; switch_stmt: - attr_list TOK_SWITCH sigspec EOL { + TOK_SWITCH sigspec EOL { RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; - rule->signal = *$3; + rule->signal = *$2; rule->attributes = attrbuf; switch_stack.back()->push_back(rule); attrbuf.clear(); - delete $3; - } switch_body TOK_END EOL; + delete $2; + } attr_list switch_body TOK_END EOL; attr_list: /* empty */ | @@ -298,9 +298,11 @@ attr_list: switch_body: switch_body TOK_CASE { RTLIL::CaseRule *rule = new RTLIL::CaseRule; + rule->attributes = attrbuf; switch_stack.back()->back()->cases.push_back(rule); switch_stack.push_back(&rule->switches); case_stack.push_back(rule); + attrbuf.clear(); } compare_list EOL case_body { switch_stack.pop_back(); case_stack.pop_back(); @@ -319,12 +321,15 @@ compare_list: /* empty */; case_body: + case_body attr_stmt | case_body switch_stmt | case_body assign_stmt | /* empty */; assign_stmt: TOK_ASSIGN sigspec sigspec EOL { + if (attrbuf.size() != 0) + rtlil_frontend_ilang_yyerror("dangling attribute"); case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3)); delete $2; delete $3; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f4fcf5dcf..82cbfaf28 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1327,7 +1327,7 @@ public: #endif }; -struct RTLIL::CaseRule +struct RTLIL::CaseRule : public RTLIL::AttrObject { std::vector compare; std::vector actions; From b1f400aeb8de657d5fa28c153df14246378df2b1 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 12:29:08 +0000 Subject: [PATCH 110/160] genrtlil: emit \src attribute on CaseRule. --- frontends/ast/genrtlil.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 079fc11e5..571ddd988 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -504,6 +504,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; current_case = new RTLIL::CaseRule; + current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum); last_generated_case = current_case; addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); for (auto node : child->children) { From 55c1f4027794a89971055b705254832b189a1c83 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 12:48:50 +0000 Subject: [PATCH 111/160] verilog_backend: dump attributes on CaseRule, as comments. Attributes are not permitted in that position by Verilog grammar. --- backends/verilog/verilog_backend.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 827af5d85..18c92521f 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -364,20 +364,22 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) } } -void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false) +void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false, bool as_comment = false) { if (noattr) return; + if (attr2comment) + as_comment = true; for (auto it = attributes.begin(); it != attributes.end(); ++it) { - f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str()); + f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); f << stringf(" = "); if (modattr && (it->second == Const(0, 1) || it->second == Const(0))) f << stringf(" 0 "); else if (modattr && (it->second == Const(1, 1) || it->second == Const(1))) f << stringf(" 1 "); else - dump_const(f, it->second, -1, 0, false, attr2comment); - f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); + dump_const(f, it->second, -1, 0, false, as_comment); + f << stringf(" %s%c", as_comment ? "*/" : "*)", term); } } @@ -1511,7 +1513,9 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":\n"); + f << stringf(":"); + dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); + f << stringf("\n"); dump_case_body(f, indent + " ", *it); } @@ -1662,7 +1666,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } } - dump_attributes(f, indent, module->attributes, '\n', true); + dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true); f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { From 48655dfb8b4dda7607ed7a790eb5f6bce5c27d38 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 13:18:18 +0000 Subject: [PATCH 112/160] proc_mux: consider \src attribute on CaseRule. --- passes/proc/proc_mux.cc | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index aac0b121c..d029282fd 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -144,7 +144,13 @@ struct SnippetSwCache } }; -RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw, bool ifxmode) +void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs) +{ + cell->attributes = sw->attributes; + cell->add_strpool_attribute("\\src", cs->get_strpool_attribute("\\src")); +} + +RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { std::stringstream sstr; sstr << "$procmux$" << (autoidx++); @@ -173,7 +179,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s { // create compare cell RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? "$eqx" : "$eq"); - eq_cell->attributes = sw->attributes; + apply_attrs(eq_cell, sw, cs); eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(0); @@ -199,7 +205,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s // reduce cmp vector to one logic signal RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", "$reduce_or"); - any_cell->attributes = sw->attributes; + apply_attrs(any_cell, sw, cs); any_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); any_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cmp_wire->width); @@ -212,7 +218,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return RTLIL::SigSpec(ctrl_wire); } -RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode) +RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { log_assert(when_signal.size() == else_signal.size()); @@ -224,7 +230,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return when_signal; // compare results - RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode); + RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode); if (ctrl_sig.size() == 0) return when_signal; log_assert(ctrl_sig.size() == 1); @@ -234,7 +240,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s // create the multiplexer itself RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), "$mux"); - mux_cell->attributes = sw->attributes; + apply_attrs(mux_cell, sw, cs); mux_cell->parameters["\\WIDTH"] = RTLIL::Const(when_signal.size()); mux_cell->setPort("\\A", else_signal); @@ -246,7 +252,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s return RTLIL::SigSpec(result_wire); } -void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode) +void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode) { log_assert(last_mux_cell != NULL); log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size()); @@ -254,7 +260,7 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve if (when_signal == last_mux_cell->getPort("\\A")) return; - RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode); + RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode); log_assert(ctrl_sig.size() == 1); last_mux_cell->type = "$pmux"; @@ -395,9 +401,9 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d RTLIL::CaseRule *cs2 = sw->cases[case_idx]; RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val, ifxmode); if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1]) - append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode); + append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, cs2, ifxmode); else - result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode); + result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, cs2, ifxmode); } } From 628437b01cd37b95c020b2f4c4e2f2d8f0e9bf8b Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 15:11:29 +0000 Subject: [PATCH 113/160] verilog_backend: dump attributes on SwitchRule. This appears to be an omission. --- backends/verilog/verilog_backend.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 18c92521f..6288502a5 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1494,6 +1494,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw return; } + dump_attributes(f, indent, sw->attributes); f << stringf("%s" "casez (", indent.c_str()); dump_sigspec(f, sw->signal); f << stringf(")\n"); From c58998a7d2c1066ea28cabe9bc6e1e52bb6668f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 10:48:10 -0700 Subject: [PATCH 114/160] atoi -> stoi as per @daveshah1 --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0a30848aa..c18c3918f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -194,7 +194,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-widemux" && argidx+1 < args.size()) { - widemux = atoi(args[++argidx].c_str()); + widemux = std::stoi(args[++argidx]); continue; } if (args[argidx] == "-abc9") { From a34c5612e702d481798fa7fc27cf2fef06a2b544 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 10:59:12 -0700 Subject: [PATCH 115/160] Add muxcover -mux2=cost option --- passes/techmap/muxcover.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index c84cfc39a..4d9c111e7 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -631,7 +631,7 @@ struct MuxcoverPass : public Pass { log("\n"); log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); log("\n"); - log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); + log(" -mux2=cost, -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); log(" Use the specified types of MUXes (with optional integer costs). If none\n"); log(" of these options are given, the effect is the same as if all of them are.\n"); log(" Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4); @@ -661,6 +661,7 @@ struct MuxcoverPass : public Pass { bool nodecode = false; bool nopartial = false; int cost_dmux = COST_DMUX; + int cost_mux2 = COST_MUX2; int cost_mux4 = COST_MUX4; int cost_mux8 = COST_MUX8; int cost_mux16 = COST_MUX16; @@ -669,6 +670,10 @@ struct MuxcoverPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { const auto &arg = args[argidx]; + if (arg.size() >= 6 && arg.substr(0,6) == "-mux2=") { + cost_mux2 = atoi(arg.substr(6).c_str()); + continue; + } if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") { use_mux4 = true; if (arg.size() > 5) { @@ -722,6 +727,7 @@ struct MuxcoverPass : public Pass { worker.use_mux8 = use_mux8; worker.use_mux16 = use_mux16; worker.cost_dmux = cost_dmux; + worker.cost_mux2 = cost_mux2; worker.cost_mux4 = cost_mux4; worker.cost_mux8 = cost_mux8; worker.cost_mux16 = cost_mux16; From 3681162c8d6826cf5ccf5de485ba14b4200a5221 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:00:06 -0700 Subject: [PATCH 116/160] atoi -> stoi --- passes/techmap/muxcover.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 4d9c111e7..fa97239f5 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -671,14 +671,14 @@ struct MuxcoverPass : public Pass { { const auto &arg = args[argidx]; if (arg.size() >= 6 && arg.substr(0,6) == "-mux2=") { - cost_mux2 = atoi(arg.substr(6).c_str()); + cost_mux2 = std::stoi(arg.substr(6)); continue; } if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") { use_mux4 = true; if (arg.size() > 5) { if (arg[5] != '=') break; - cost_mux4 = atoi(arg.substr(6).c_str()); + cost_mux4 = std::stoi(arg.substr(6)); } continue; } @@ -686,7 +686,7 @@ struct MuxcoverPass : public Pass { use_mux8 = true; if (arg.size() > 5) { if (arg[5] != '=') break; - cost_mux8 = atoi(arg.substr(6).c_str()); + cost_mux8 = std::stoi(arg.substr(6)); } continue; } @@ -694,12 +694,12 @@ struct MuxcoverPass : public Pass { use_mux16 = true; if (arg.size() > 6) { if (arg[6] != '=') break; - cost_mux16 = atoi(arg.substr(7).c_str()); + cost_mux16 = std::stoi(arg.substr(7)); } continue; } if (arg.size() >= 6 && arg.substr(0,6) == "-dmux=") { - cost_dmux = atoi(arg.substr(6).c_str()); + cost_dmux = std::stoi(arg.substr(6)); continue; } if (arg == "-nodecode") { From dbe1326573e878f4f9d4fc80ce1afcd0f7d84ec6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:08:20 -0700 Subject: [PATCH 117/160] Parametric muxcover costs as per @daveshah1 --- techlibs/xilinx/synth_xilinx.cc | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c18c3918f..f43923afb 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -280,23 +280,21 @@ struct SynthXilinxPass : public ScriptPass } else if (widemux > 0) { run("simplemap t:$mux"); - std::string muxcover_args = " -nodecode"; + constexpr int cost_mux2 = 100; + std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - // NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 - // of those so that 4:1 muxes and below are implemented - // out of mux2s - case 5: muxcover_args += " -mux8=350 -mux16=400"; break; - case 6: muxcover_args += " -mux8=450 -mux16=500"; break; - case 7: muxcover_args += " -mux8=550 -mux16=600"; break; - case 8: muxcover_args += " -mux8=650 -mux16=700"; break; - case 9: muxcover_args += " -mux16=750"; break; - case 10: muxcover_args += " -mux16=850"; break; - case 11: muxcover_args += " -mux16=950"; break; - case 12: muxcover_args += " -mux16=1050"; break; - case 13: muxcover_args += " -mux16=1150"; break; - case 14: muxcover_args += " -mux16=1250"; break; - case 15: muxcover_args += " -mux16=1350"; break; - default: muxcover_args += " -mux16=1450"; break; + case 5: + case 6: + case 7: + case 8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break; } run("muxcover " + muxcover_args); } From 0944acf3affd8c6b161a2381b37eed3931c801a5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 11:29:21 -0700 Subject: [PATCH 118/160] synth_xilinx -widemux=2 is minimum now --- techlibs/xilinx/synth_xilinx.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f43923afb..4f597de4d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -79,7 +79,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); - log(" above this number of inputs (minimum value 5).\n"); + log(" above this number of inputs (minimum value 2).\n"); log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); @@ -208,8 +208,8 @@ struct SynthXilinxPass : public ScriptPass if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s") log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); - if (widemux != 0 && widemux < 5) - log_cmd_error("-widemux value must be 0 or >= 5.\n"); + if (widemux != 0 && widemux < 2) + log_cmd_error("-widemux value must be 0 or >= 2.\n"); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -252,7 +252,7 @@ struct SynthXilinxPass : public ScriptPass // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) - run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)"); + run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -283,6 +283,9 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { + case 2: + case 3: + case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: case 6: case 7: From 895ca501734d2f33b61f118a288832b55a366bd2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 12:03:38 -0700 Subject: [PATCH 119/160] Fixes for 2:1 muxes --- techlibs/xilinx/cells_map.v | 33 +++++++++++++++++++++++++++++---- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 27e860801..e12dd2833 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -193,6 +193,14 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH < `MIN_MUX_INPUTS) begin wire _TECHMAP_FAIL_ = 1; end + else if (A_WIDTH == 2) begin + MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); + end + else if (A_WIDTH <= 2 ** 2) begin + wire [4-1:0] T; + assign T = {{(4-A_WIDTH){1'bx}}, A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + end else if (A_WIDTH <= 2 ** 3) begin localparam a_width0 = 2 ** 2; localparam a_widthN = A_WIDTH - a_width0; @@ -251,15 +259,32 @@ module _90__XILINX_SHIFTX (A, B, Y); \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); endmodule +module \$_MUX_ (A, B, S, Y); + input A, B, S; + output Y; + generate + if (`MIN_MUX_INPUTS == 2) + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(2), .B_WIDTH(1), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({B,A}), .B(S), .Y(Y)); + else + wire _TECHMAP_FAIL_ = 1; + endgenerate +endmodule + +module \$_MUX4_ (A, B, C, D, S, T, Y); + input A, B, C, D, S, T; + output Y; + \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({D,C,B,A}), .B({T,S}), .Y(Y)); +endmodule + module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); -input A, B, C, D, E, F, G, H, S, T, U; -output Y; + input A, B, C, D, E, F, G, H, S, T, U; + output Y; \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); endmodule module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); -input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; -output Y; + input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; + output Y; \$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); endmodule `endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4f597de4d..62bfaaaf1 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -283,7 +283,7 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - case 2: + case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; case 3: case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: From b5072256f2c6b94423adb0ac1e2aec965230afe3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 12:50:59 -0700 Subject: [PATCH 120/160] Update muxcover doc as per @ZirconiumX --- passes/techmap/muxcover.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index fa97239f5..d53378a29 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -631,11 +631,16 @@ struct MuxcoverPass : public Pass { log("\n"); log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); log("\n"); - log(" -mux2=cost, -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); - log(" Use the specified types of MUXes (with optional integer costs). If none\n"); - log(" of these options are given, the effect is the same as if all of them are.\n"); - log(" Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4); - log(" $_MUX8_ = %d, $_MUX16_ = %d\n", COST_MUX8, COST_MUX16); + log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); + log(" Cover $_MUX_ trees using the specified types of MUXes (with optional\n"); + log(" integer costs). If none of these options are given, the effect is the\n"); + log(" same as if all of them are.\n"); + log(" Default costs: $_MUX4_ = %d, $_MUX8_ = %d, \n", COST_MUX4, COST_MUX8); + log(" $_MUX16_ = %d\n", COST_MUX16); + log("\n"); + log(" -mux2=cost\n"); + log(" Use the specified cost for $_MUX_ cells when making covering decisions.\n"); + log(" Default cost: $_MUX_ = %d\n", COST_MUX2); log("\n"); log(" -dmux=cost\n"); log(" Use the specified cost for $_MUX_ cells used in decoders.\n"); From baf47e496f35cb90e5c7181079d38c04907c42da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:04:39 -0700 Subject: [PATCH 121/160] Add synth_xilinx -widemux recommended value --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 62bfaaaf1..7836f9f3e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -79,7 +79,7 @@ struct SynthXilinxPass : public ScriptPass log("\n"); log(" -widemux \n"); log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); - log(" above this number of inputs (minimum value 2).\n"); + log(" above this number of inputs (minimum value 2, recommended value >= 5).\n"); log(" default: 0 (no inference)\n"); log("\n"); log(" -run :\n"); From 78914e2e0e0a92e65cb1594c4858bc2225322ade Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:06:22 -0700 Subject: [PATCH 122/160] Capitalisation --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7836f9f3e..b404dc8e7 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -78,7 +78,7 @@ struct SynthXilinxPass : public ScriptPass log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n"); log("\n"); log(" -widemux \n"); - log(" enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); + log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n"); log(" above this number of inputs (minimum value 2, recommended value >= 5).\n"); log(" default: 0 (no inference)\n"); log("\n"); From 3f86407cc32e20a8885c73f959082c5c0449bf9a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 17:06:35 -0700 Subject: [PATCH 123/160] Map $__XILINX_SHIFTX in a more balanced manner --- techlibs/xilinx/cells_map.v | 85 +++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e12dd2833..d48a3f15c 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -197,49 +197,62 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 2 ** 2) begin - wire [4-1:0] T; - assign T = {{(4-A_WIDTH){1'bx}}, A}; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end else if (A_WIDTH <= 2 ** 3) begin - localparam a_width0 = 2 ** 2; - localparam a_widthN = A_WIDTH - a_width0; - wire T0, T1; - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); - if (a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); - else - assign T1 = A[A_WIDTH-1]; - MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[2]), .O(Y)); + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" state to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 + wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; + wire T0 = B[0] ? Ax[1] : Ax[0]; + wire T1 = B[0] ? Ax[3] : Ax[2]; + wire T2 = B[0] ? Ax[5] : Ax[4]; + wire T3 = B[0] ? Ax[7] : Ax[6]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); end else if (A_WIDTH <= 2 ** 4) begin - localparam a_width0 = 2 ** 2; - localparam num_mux8 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [a_width0-1:0] T; - for (i = 0; i < a_width0; i++) - if (i < num_mux8) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); - else if (i == num_mux8 && a_widthN > 1) - \$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); - else - assign T[i] = A[A_WIDTH-1]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" state to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 + wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; + wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] + : B[0] ? Ax[ 1] : Ax[ 0]; + wire T1 = B[1] ? B[0] ? Ax[ 7] : Ax[ 6] + : B[0] ? Ax[ 5] : Ax[ 4]; + wire T2 = B[1] ? B[0] ? Ax[11] : Ax[10] + : B[0] ? Ax[ 9] : Ax[ 8]; + wire T3 = B[1] ? B[0] ? Ax[15] : Ax[14] + : B[0] ? Ax[13] : Ax[12]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[2]), .S1(B[3]), .O(Y)); end else begin - localparam a_width0 = 2 ** 4; - localparam num_mux16 = A_WIDTH / a_width0; - localparam a_widthN = A_WIDTH % a_width0; - wire [num_mux16 + (a_widthN > 0 ? 1 : 0) - 1:0] T; + localparam num_mux16 = (A_WIDTH+15) / 16; + localparam clog2_num_mux16 = $clog2(num_mux16); + wire [num_mux16-1:0] T; + wire [num_mux16*16-1:0] Ax = {{(num_mux16*16-A_WIDTH){1'bx}}, A}; for (i = 0; i < num_mux16; i++) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); - if (a_widthN > 0) begin - if (a_widthN > 1) - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); - else - assign T[num_mux16] = A[A_WIDTH-1]; - end - \$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(num_mux16 + (a_widthN > 0 ? 1 : 0)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(16), + .B_WIDTH(4), + .Y_WIDTH(Y_WIDTH) + ) fpga_mux ( + .A(Ax[i*16+:16]), + .B(B[3:0]), + .Y(T[i]) + ); + \$__XILINX_SHIFTX #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(num_mux16), + .B_WIDTH(clog2_num_mux16), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(T), + .B(B[B_WIDTH-1-:clog2_num_mux16]), + .Y(Y)); end endgenerate endmodule From dd9771cbcdc14366c6acc501833c6050c39251de Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:14:54 -0700 Subject: [PATCH 124/160] Add synth -keepdc option --- techlibs/common/synth.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 555de9fba..af70cc498 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -78,6 +78,9 @@ struct SynthPass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); + log(" -keepdc\n"); + log(" do not optimize explicit don't-care values on $mux cells.\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -85,7 +88,7 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, keepdc; int lut; void clear_flags() YS_OVERRIDE @@ -102,6 +105,7 @@ struct SynthPass : public ScriptPass noabc = false; noshare = false; abc = "abc"; + keepdc = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -167,6 +171,10 @@ struct SynthPass : public ScriptPass abc = "abc9"; continue; } + if (args[argidx] == "-keepdc") { + keepdc = true; + continue; + } break; } extra_args(args, argidx, design); @@ -211,7 +219,10 @@ struct SynthPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - run("wreduce"); + if (help_mode) + run("wreduce [-keepdc]"); + else + run("wreduce" + std::string(keepdc ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); if (help_mode) From 37b58f43242086de13fb2966d11b71efa29e7bfd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:15:07 -0700 Subject: [PATCH 125/160] Clarify 'wreduce -keepdc' doc --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..f749c8249 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values.\n"); + log(" Do not optimize explicit don't-care values on $mux cells.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE From fccabd09436aae780875fae2d833f58549f38418 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:15:37 -0700 Subject: [PATCH 126/160] Add synth -keepdc to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index ae7d28236..646d63a63 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) + - Added "synth -keepdc" - Added "script -scriptwire From 41d7d9d24b8ba7fd84dd72b27eb9aede10b8ef15 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:21:21 -0700 Subject: [PATCH 127/160] Clarify script -scriptwire doc --- kernel/yosys.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index f95c0127b..a42a7c0b8 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1273,6 +1273,10 @@ struct ScriptCmdPass : public Pass { log("If only one label is specified (without ':') then only the block\n"); log("marked with that label (until the next label) is executed.\n"); log("\n"); + log("In \"-scriptwire\" mode, the commands on the selected wire(s) will be executed\n"); + log("in the scope of (and thus, relative to) the wires' owning module(s). This\n"); + log("'-module' mode can be exited by using the 'cd' command.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { From 7f964859ec99500e471853f5914b6e5b7c35a031 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:23:24 -0700 Subject: [PATCH 128/160] synth_xilinx to call "synth -run coarse" with "-keepdc" --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b404dc8e7..15a37a439 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -240,9 +240,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { if (help_mode) - run("synth -run coarse [-flatten]", "(with '-flatten')"); + run("synth -keepdc -run coarse [-flatten]", "(with '-flatten')"); else - run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("synth -keepdc -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); From de404535538fe4d2548be82724515961e6e92519 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 22:56:19 -0700 Subject: [PATCH 129/160] Reword --- techlibs/xilinx/cells_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index d48a3f15c..63095880e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -202,7 +202,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 2 ** 3) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" state to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; wire T0 = B[0] ? Ax[1] : Ax[0]; @@ -213,7 +213,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 2 ** 4) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" state to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] From 939a225f921efc4276121fe957f545a98d252fa0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:02:57 -0700 Subject: [PATCH 130/160] Less thinking --- techlibs/xilinx/cells_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 63095880e..7c67c7a79 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -196,11 +196,11 @@ module \$__XILINX_SHIFTX (A, B, Y); else if (A_WIDTH == 2) begin MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end - else if (A_WIDTH <= 2 ** 2) begin + else if (A_WIDTH <= 4) begin wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end - else if (A_WIDTH <= 2 ** 3) begin + else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 @@ -211,7 +211,7 @@ module \$__XILINX_SHIFTX (A, B, Y); wire T3 = B[0] ? Ax[7] : Ax[6]; \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); end - else if (A_WIDTH <= 2 ** 4) begin + else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 From d4ab43d9403899dcae74a24e71385fd959de98f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:05:48 -0700 Subject: [PATCH 131/160] Add one more comment --- techlibs/xilinx/cells_map.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 7c67c7a79..39427cc90 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -197,6 +197,9 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" status to get lost, extend with MSB + // so that we can recognise again later when mapping MUXF78 wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); end From 45da3ada7babc8f2b23a8b23ce25430a98e2e58e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:49:16 -0700 Subject: [PATCH 132/160] Do not call opt -mux_undef (part of -full) before muxcover --- techlibs/xilinx/synth_xilinx.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 15a37a439..6eab74a21 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -270,7 +270,11 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast -full"); + if (widemux > 0) + run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover + // performs less efficiently + else + run("opt -fast -full"); run("memory_map"); run("dffsr2dff"); run("dff2dffe"); From 6951e3207063f66814e765d7d72e553b8b8eace1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 23:51:13 -0700 Subject: [PATCH 133/160] Decompose mux inputs in delay-orientated (rather than area) fashion --- techlibs/xilinx/cells_map.v | 48 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 39427cc90..35eea9858 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -200,34 +200,46 @@ module \$__XILINX_SHIFTX (A, B, Y); // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [4-1:0] Ax = {{(4-A_WIDTH){A[A_WIDTH-1]}}, A}; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[1]), .I2(Ax[2]), .I3(Ax[3]), .S0(B[0]), .S1(B[1]), .O(Y)); + wire [4-1:0] Ax; + if (A_WIDTH == 4) + assign Ax = A; + else + assign Ax = {A[1-:4-A_WIDTH], A}; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [8-1:0] Ax = {{(8-A_WIDTH){A[A_WIDTH-1]}}, A}; - wire T0 = B[0] ? Ax[1] : Ax[0]; - wire T1 = B[0] ? Ax[3] : Ax[2]; - wire T2 = B[0] ? Ax[5] : Ax[4]; - wire T3 = B[0] ? Ax[7] : Ax[6]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[1]), .S1(B[2]), .O(Y)); + wire [8-1:0] Ax; + if (A_WIDTH == 8) + assign Ax = A; + else + assign Ax = {A[3-:8-A_WIDTH], A}; + wire T0 = B[2] ? Ax[4] : Ax[0]; + wire T1 = B[2] ? Ax[5] : Ax[1]; + wire T2 = B[2] ? Ax[6] : Ax[2]; + wire T3 = B[2] ? Ax[7] : Ax[3]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 // causing the "don't care" status to get lost, extend with MSB // so that we can recognise again later when mapping MUXF78 - wire [16-1:0] Ax = {{(16-A_WIDTH){A[A_WIDTH-1]}}, A}; - wire T0 = B[1] ? B[0] ? Ax[ 3] : Ax[ 2] - : B[0] ? Ax[ 1] : Ax[ 0]; - wire T1 = B[1] ? B[0] ? Ax[ 7] : Ax[ 6] - : B[0] ? Ax[ 5] : Ax[ 4]; - wire T2 = B[1] ? B[0] ? Ax[11] : Ax[10] - : B[0] ? Ax[ 9] : Ax[ 8]; - wire T3 = B[1] ? B[0] ? Ax[15] : Ax[14] - : B[0] ? Ax[13] : Ax[12]; - \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T1), .I2(T2), .I3(T3), .S0(B[2]), .S1(B[3]), .O(Y)); + wire [16-1:0] Ax; + if (A_WIDTH == 16) + assign Ax = A; + else + assign Ax = {A[7-:8-A_WIDTH], A}; + wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] + : B[3] ? Ax[ 8] : Ax[0]; + wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] + : B[3] ? Ax[ 9] : Ax[1]; + wire T2 = B[2] ? B[3] ? Ax[14] : Ax[6] + : B[3] ? Ax[10] : Ax[2]; + wire T3 = B[2] ? B[3] ? Ax[15] : Ax[7] + : B[3] ? Ax[11] : Ax[3]; + \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else begin localparam num_mux16 = (A_WIDTH+15) / 16; From f7a14a56780fedfc38a104f46b801b84fa357d01 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 08:57:57 +0000 Subject: [PATCH 134/160] proc_clean: add -quiet option. This is useful for other passes that call it often, like bugpoint. --- passes/proc/proc_clean.cc | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 52141a8ec..97f4c6573 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -143,7 +143,7 @@ void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int m YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN -void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) +void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool quiet) { int count = 0; bool did_something = true; @@ -160,7 +160,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) did_something = false; proc_clean_case(&proc->root_case, did_something, count, -1); } - if (count > 0) + if (count > 0 && !quiet) log("Found and cleaned up %d empty switch%s in `%s.%s'.\n", count, count == 1 ? "" : "es", mod->name.c_str(), proc->name.c_str()); total_count += count; } @@ -171,7 +171,10 @@ struct ProcCleanPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" proc_clean [selection]\n"); + log(" proc_clean [options] [selection]\n"); + log("\n"); + log(" -quiet\n"); + log(" do not print any messages.\n"); log("\n"); log("This pass removes empty parts of processes and ultimately removes a process\n"); log("if it contains only empty structures.\n"); @@ -180,9 +183,20 @@ struct ProcCleanPass : public Pass { void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_count = 0; - log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n"); + bool quiet = false; - extra_args(args, 1, design); + if (find(args.begin(), args.end(), "-quiet") == args.end()) + log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-quiet") { + quiet = true; + continue; + } + } + extra_args(args, argidx, design); for (auto mod : design->modules()) { std::vector delme; @@ -191,10 +205,11 @@ struct ProcCleanPass : public Pass { for (auto &proc_it : mod->processes) { if (!design->selected(mod, proc_it.second)) continue; - proc_clean(mod, proc_it.second, total_count); + proc_clean(mod, proc_it.second, total_count, quiet); if (proc_it.second->syncs.size() == 0 && proc_it.second->root_case.switches.size() == 0 && proc_it.second->root_case.actions.size() == 0) { - log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); + if (!quiet) + log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); delme.push_back(proc_it.first); } } @@ -204,7 +219,8 @@ struct ProcCleanPass : public Pass { } } - log("Cleaned up %d empty switch%s.\n", total_count, total_count == 1 ? "" : "es"); + if (!quiet) + log("Cleaned up %d empty switch%s.\n", total_count, total_count == 1 ? "" : "es"); } } ProcCleanPass; From f2fb958d44bada70859ef2c4db9076e27da643e7 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 09:08:38 +0000 Subject: [PATCH 135/160] bugpoint: add -assigns and -updates options. --- passes/cmds/bugpoint.cc | 90 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 038ab7c7c..5a47988ec 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -51,14 +51,14 @@ struct BugpointPass : public Pass { log(" only consider crashes that place this string in the log file.\n"); log("\n"); log(" -fast\n"); - log(" run `clean -purge` after each minimization step. converges faster, but\n"); - log(" produces larger testcases, and may fail to produce any testcase at all if\n"); - log(" the crash is related to dangling wires.\n"); + log(" run `proc_clean; clean -purge` after each minimization step. converges\n"); + log(" faster, but produces larger testcases, and may fail to produce any\n"); + log(" testcase at all if the crash is related to dangling wires.\n"); log("\n"); log(" -clean\n"); - log(" run `clean -purge` before checking testcase and after finishing. produces\n"); - log(" smaller and more useful testcases, but may fail to produce any testcase\n"); - log(" at all if the crash is related to dangling wires.\n"); + log(" run `proc_clean; clean -purge` before checking testcase and after\n"); + log(" finishing. produces smaller and more useful testcases, but may fail to\n"); + log(" produce any testcase at all if the crash is related to dangling wires.\n"); log("\n"); log(" -modules\n"); log(" try to remove modules.\n"); @@ -72,6 +72,12 @@ struct BugpointPass : public Pass { log(" -connections\n"); log(" try to reconnect ports to 'x.\n"); log("\n"); + log(" -assigns\n"); + log(" try to remove process assigns from cases.\n"); + log("\n"); + log(" -updates\n"); + log(" try to remove process updates from syncs.\n"); + log("\n"); } bool run_yosys(RTLIL::Design *design, string yosys_cmd, string script) @@ -110,6 +116,7 @@ struct BugpointPass : public Pass { RTLIL::Design *design_copy = new RTLIL::Design; for (auto &it : design->modules_) design_copy->add(it.second->clone()); + Pass::call(design_copy, "proc_clean -quiet"); Pass::call(design_copy, "clean -purge"); if (do_delete) @@ -117,7 +124,7 @@ struct BugpointPass : public Pass { return design_copy; } - RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections) + RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates) { RTLIL::Design *design_copy = new RTLIL::Design; for (auto &it : design->modules_) @@ -225,6 +232,59 @@ struct BugpointPass : public Pass { } } } + if (assigns) + { + for (auto mod : design_copy->modules()) + { + if (mod->get_blackbox_attribute()) + continue; + + for (auto &pr : mod->processes) + { + vector cases = {&pr.second->root_case}; + while (!cases.empty()) + { + RTLIL::CaseRule *cs = cases[0]; + cases.erase(cases.begin()); + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) + { + if (index++ == seed) + { + log("Trying to remove assign %s %s in %s.%s.\n", log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); + cs->actions.erase(it); + return design_copy; + } + } + for (auto &sw : cs->switches) + cases.insert(cases.end(), sw->cases.begin(), sw->cases.end()); + } + } + } + } + if (updates) + { + for (auto mod : design_copy->modules()) + { + if (mod->get_blackbox_attribute()) + continue; + + for (auto &pr : mod->processes) + { + for (auto &sy : pr.second->syncs) + { + for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) + { + if (index++ == seed) + { + log("Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal((*it).first), log_signal((*it).second), mod->name.c_str(), pr.first.c_str()); + sy->actions.erase(it); + return design_copy; + } + } + } + } + } + } return NULL; } @@ -232,7 +292,7 @@ struct BugpointPass : public Pass { { string yosys_cmd = "yosys", script, grep; bool fast = false, clean = false; - bool modules = false, ports = false, cells = false, connections = false, has_part = false; + bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -277,6 +337,16 @@ struct BugpointPass : public Pass { has_part = true; continue; } + if (args[argidx] == "-assigns") { + assigns = true; + has_part = true; + continue; + } + if (args[argidx] == "-updates") { + updates = true; + has_part = true; + continue; + } break; } extra_args(args, argidx, design); @@ -290,6 +360,8 @@ struct BugpointPass : public Pass { ports = true; cells = true; connections = true; + assigns = true; + updates = true; } if (!design->full_selection()) @@ -305,7 +377,7 @@ struct BugpointPass : public Pass { bool found_something = false, stage2 = false; while (true) { - if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections)) + if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, assigns, updates)) { simplified = clean_design(simplified, fast, /*do_delete=*/true); From 5fe0ffe30f315d50b2405c2d436ad8e7ca9ba2f6 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jul 2019 15:19:01 +0000 Subject: [PATCH 136/160] proc_prune: new pass. The proc_prune pass is similar in nature to proc_rmdead pass: while proc_rmdead removes branches that never become active because another branch preempts it, proc_prune removes assignments that never become active because another assignment preempts them. Genrtlil contains logic similar to the proc_prune pass, but their purpose is different: genrtlil has to prune assignments to adapt the semantics of blocking assignments in HDLs (latest assignment wins) to semantics of assignments in RTLIL processes (assignment in the most specific case wins). On the other hand proc_prune is a general purpose RTLIL simplification that benefits all frontends, even those not using the Yosys AST library. The proc_prune pass is added to the proc script after proc_rmdead, since it gives better results with fewer branches. --- passes/proc/Makefile.inc | 2 +- passes/proc/proc.cc | 2 + passes/proc/proc_prune.cc | 135 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 passes/proc/proc_prune.cc diff --git a/passes/proc/Makefile.inc b/passes/proc/Makefile.inc index 397fe46a1..4b56979f8 100644 --- a/passes/proc/Makefile.inc +++ b/passes/proc/Makefile.inc @@ -1,5 +1,6 @@ OBJS += passes/proc/proc.o +OBJS += passes/proc/proc_prune.o OBJS += passes/proc/proc_clean.o OBJS += passes/proc/proc_rmdead.o OBJS += passes/proc/proc_init.o @@ -7,4 +8,3 @@ OBJS += passes/proc/proc_arst.o OBJS += passes/proc/proc_mux.o OBJS += passes/proc/proc_dlatch.o OBJS += passes/proc/proc_dff.o - diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index ef7cb0f71..a5b4a3112 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -37,6 +37,7 @@ struct ProcPass : public Pass { log("\n"); log(" proc_clean\n"); log(" proc_rmdead\n"); + log(" proc_prune\n"); log(" proc_init\n"); log(" proc_arst\n"); log(" proc_mux\n"); @@ -83,6 +84,7 @@ struct ProcPass : public Pass { Pass::call(design, "proc_clean"); if (!ifxmode) Pass::call(design, "proc_rmdead"); + Pass::call(design, "proc_prune"); Pass::call(design, "proc_init"); if (global_arst.empty()) Pass::call(design, "proc_arst"); diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc new file mode 100644 index 000000000..7222d414d --- /dev/null +++ b/passes/proc/proc_prune.cc @@ -0,0 +1,135 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 whitequark + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/log.h" +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct PruneWorker +{ + RTLIL::Module *module; + SigMap sigmap; + + int count = 0; + + PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {} + + pool do_switch(RTLIL::SwitchRule *sw, pool assigned) + { + pool all_assigned; + bool full_case = sw->get_bool_attribute("\\full_case"); + bool first = true; + for (auto it : sw->cases) { + if (it->compare.empty()) + full_case = true; + pool case_assigned = do_case(it, assigned); + if (first) { + first = false; + all_assigned = case_assigned; + } else { + for (auto &bit : all_assigned) + if (!case_assigned[bit]) + all_assigned.erase(bit); + } + } + if (full_case) + assigned.insert(all_assigned.begin(), all_assigned.end()); + return assigned; + } + + pool do_case(RTLIL::CaseRule *cs, pool assigned) + { + for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) { + pool sw_assigned = do_switch((*it), assigned); + assigned.insert(sw_assigned.begin(), sw_assigned.end()); + } + pool remove; + for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) { + RTLIL::SigSpec lhs = sigmap(it->first); + bool redundant = true; + for (auto &bit : lhs) { + if (bit.wire && !assigned[bit]) { + redundant = false; + break; + } + } + if (redundant) + remove.insert(*it); + else { + for (auto &bit : lhs) + if (bit.wire) + assigned.insert(bit); + } + } + for (auto it = cs->actions.begin(); it != cs->actions.end(); ) { + if (remove[*it]) { + it = cs->actions.erase(it); + count++; + } else it++; + } + return assigned; + } + + void do_process(RTLIL::Process *pr) + { + do_case(&pr->root_case, {}); + } +}; + +struct ProcPrunePass : public Pass { + ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" proc_prune [selection]\n"); + log("\n"); + log("This pass identifies assignments in processes that are always overwritten by\n"); + log("a later assignment to the same signal and removes them.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + int total_count = 0; + log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n"); + + extra_args(args, 1, design); + + for (auto mod : design->modules()) { + if (!design->selected(mod)) + continue; + PruneWorker worker(mod); + for (auto &proc_it : mod->processes) { + if (!design->selected(mod, proc_it.second)) + continue; + worker.do_process(proc_it.second); + } + total_count += worker.count; + } + + log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s"); + } +} ProcPrunePass; + +PRIVATE_NAMESPACE_END From 44bcb7a187ffa00921cb14fa50428ce272ce3b6b Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 08:14:52 +0000 Subject: [PATCH 137/160] proc_prune: promote assigns to module connections when legal. This can pave the way for further transformations by exposing identities that were previously hidden in a process to any pass that uses SigMap. Indeed, this commit removes some ad-hoc logic from proc_init that appears to have been tailored to the output of genrtlil in favor of using `SigMap.apply()`. (This removal is not optional, as the ad-hoc logic cannot cope with the result of running proc_prune; a similar issue was fixed in proc_arst.) --- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_init.cc | 26 +++++----------------- passes/proc/proc_prune.cc | 47 +++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index b69eba3f9..d069f152a 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -172,7 +172,7 @@ restart_proc_arst: sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0; } for (auto &action : sync->actions) { - RTLIL::SigSpec rspec = action.second; + RTLIL::SigSpec rspec = assign_map(action.second); RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size()); for (int i = 0; i < GetSize(rspec); i++) if (rspec[i].wire == NULL) diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index e2dc07e53..462a384b7 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -26,21 +26,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) -{ - log_assert(rule.compare.size() == 0); - - while (1) { - RTLIL::SigSpec tmp = sig; - for (auto &it : rule.actions) - tmp.replace(it.first, it.second); - if (tmp == sig) - break; - sig = tmp; - } -} - -void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) +void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) { bool found_init = false; @@ -53,9 +39,7 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) for (auto &action : sync->actions) { RTLIL::SigSpec lhs = action.first; - RTLIL::SigSpec rhs = action.second; - - proc_get_const(rhs, proc->root_case); + RTLIL::SigSpec rhs = sigmap(action.second); if (!rhs.is_fully_const()) log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs)); @@ -120,10 +104,12 @@ struct ProcInitPass : public Pass { extra_args(args, 1, design); for (auto mod : design->modules()) - if (design->selected(mod)) + if (design->selected(mod)) { + SigMap sigmap(mod); for (auto &proc_it : mod->processes) if (design->selected(mod, proc_it.second)) - proc_init(mod, proc_it.second); + proc_init(mod, sigmap, proc_it.second); + } } } ProcInitPass; diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index 7222d414d..9e00b0a8a 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -31,11 +31,11 @@ struct PruneWorker RTLIL::Module *module; SigMap sigmap; - int count = 0; + int removed_count = 0, promoted_count = 0; PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {} - pool do_switch(RTLIL::SwitchRule *sw, pool assigned) + pool do_switch(RTLIL::SwitchRule *sw, pool assigned, pool &affected) { pool all_assigned; bool full_case = sw->get_bool_attribute("\\full_case"); @@ -43,7 +43,7 @@ struct PruneWorker for (auto it : sw->cases) { if (it->compare.empty()) full_case = true; - pool case_assigned = do_case(it, assigned); + pool case_assigned = do_case(it, assigned, affected); if (first) { first = false; all_assigned = case_assigned; @@ -58,10 +58,11 @@ struct PruneWorker return assigned; } - pool do_case(RTLIL::CaseRule *cs, pool assigned) + pool do_case(RTLIL::CaseRule *cs, pool assigned, pool &affected, + bool root = false) { for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) { - pool sw_assigned = do_switch((*it), assigned); + pool sw_assigned = do_switch((*it), assigned, affected); assigned.insert(sw_assigned.begin(), sw_assigned.end()); } pool remove; @@ -74,18 +75,35 @@ struct PruneWorker break; } } - if (redundant) + if (redundant) { + removed_count++; remove.insert(*it); - else { + } else { + if (root) { + bool promotable = true; + for (auto &bit : lhs) { + if (bit.wire && affected[bit]) { + promotable = false; + break; + } + } + if (promotable) { + promoted_count++; + module->connect(*it); + remove.insert(*it); + } + } for (auto &bit : lhs) if (bit.wire) assigned.insert(bit); + for (auto &bit : lhs) + if (bit.wire) + affected.insert(bit); } } for (auto it = cs->actions.begin(); it != cs->actions.end(); ) { if (remove[*it]) { it = cs->actions.erase(it); - count++; } else it++; } return assigned; @@ -93,7 +111,8 @@ struct PruneWorker void do_process(RTLIL::Process *pr) { - do_case(&pr->root_case, {}); + pool affected; + do_case(&pr->root_case, {}, affected, /*root=*/true); } }; @@ -111,7 +130,7 @@ struct ProcPrunePass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - int total_count = 0; + int total_removed_count = 0, total_promoted_count = 0; log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n"); extra_args(args, 1, design); @@ -125,10 +144,14 @@ struct ProcPrunePass : public Pass { continue; worker.do_process(proc_it.second); } - total_count += worker.count; + total_removed_count += worker.removed_count; + total_promoted_count += worker.promoted_count; } - log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s"); + log("Removed %d redundant assignment%s.\n", + total_removed_count, total_removed_count == 1 ? "" : "s"); + log("Promoted %d assignment%s to connection%s.\n", + total_promoted_count, total_promoted_count == 1 ? "" : "s", total_promoted_count == 1 ? "" : "s"); } } ProcPrunePass; From 667199d46013d116bdbeb9be8592a77503a470e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:16:00 -0700 Subject: [PATCH 138/160] Fix spacing --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6eab74a21..abdf7f9cc 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -287,7 +287,7 @@ struct SynthXilinxPass : public ScriptPass constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { - case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; + case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break; case 3: case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break; case 5: From bc84f7dd10ad44118fd6d800cb7a896069fd223d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:22:12 -0700 Subject: [PATCH 139/160] Fix spacing --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index abdf7f9cc..2a77ce397 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -270,7 +270,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - if (widemux > 0) + if (widemux > 0) run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover // performs less efficiently else From 5a0f2e43c796ed91693d60261bd75a489f778a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:35:09 -0700 Subject: [PATCH 140/160] Rename __builtin_bswap32 -> bswap32 --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 869b741a6..69f63486c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -21,13 +21,15 @@ // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include -#define __builtin_bswap32 _byteswap_ulong +#define bswap32 _byteswap_ulong #elif defined(__APPLE__) #include -#define __builtin_bswap32 OSSwapInt32 -#elif !defined(__GNUC__) +#define bswap32 OSSwapInt32 +#elif defined(__GNUC__) +#define bswap32 __builtin_bswap32 +#else #include -inline uint32_t __builtin_bswap32(uint32_t x) +inline static uint32_t bswap32(uint32_t x) { // https://stackoverflow.com/a/27796212 register uint32_t value = number_to_be_reversed; From 713337255e6ab57b0679d64539d5c87d036c067f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:14:23 -0700 Subject: [PATCH 141/160] Revert "Add "synth -keepdc" option" --- CHANGELOG | 1 - passes/opt/wreduce.cc | 2 +- techlibs/common/synth.cc | 15 ++------------- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 646d63a63..ae7d28236 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,7 +12,6 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "synth_xilinx -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental) - Added "synth -abc9" (experimental) - - Added "synth -keepdc" - Added "script -scriptwire diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index f749c8249..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values on $mux cells.\n"); + log(" Do not optimize explicit don't-care values.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index af70cc498..555de9fba 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -78,9 +78,6 @@ struct SynthPass : public ScriptPass log(" -abc9\n"); log(" use new ABC9 flow (EXPERIMENTAL)\n"); log("\n"); - log(" -keepdc\n"); - log(" do not optimize explicit don't-care values on $mux cells.\n"); - log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -88,7 +85,7 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, keepdc; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare; int lut; void clear_flags() YS_OVERRIDE @@ -105,7 +102,6 @@ struct SynthPass : public ScriptPass noabc = false; noshare = false; abc = "abc"; - keepdc = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -171,10 +167,6 @@ struct SynthPass : public ScriptPass abc = "abc9"; continue; } - if (args[argidx] == "-keepdc") { - keepdc = true; - continue; - } break; } extra_args(args, argidx, design); @@ -219,10 +211,7 @@ struct SynthPass : public ScriptPass run("opt_clean"); run("check"); run("opt"); - if (help_mode) - run("wreduce [-keepdc]"); - else - run("wreduce" + std::string(keepdc ? " -keepdc" : "")); + run("wreduce"); run("peepopt"); run("opt_clean"); if (help_mode) From 737340327fd8bae4a3b958d85cb14eecb767ed67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:15:02 -0700 Subject: [PATCH 142/160] Revert "synth_xilinx to call "synth -run coarse" with "-keepdc"" This reverts commit 7f964859ec99500e471853f5914b6e5b7c35a031. --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2a77ce397..8da6df57e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -240,9 +240,9 @@ struct SynthXilinxPass : public ScriptPass if (check_label("coarse")) { if (help_mode) - run("synth -keepdc -run coarse [-flatten]", "(with '-flatten')"); + run("synth -run coarse [-flatten]", "(with '-flatten')"); else - run("synth -keepdc -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); From c68b9092100280dbc059526a88f9d8e2902ff6a3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:21:54 -0700 Subject: [PATCH 143/160] synth_xilinx to call commands of synth -coarse directly --- techlibs/xilinx/synth_xilinx.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8da6df57e..0152af481 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -239,10 +239,25 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { + run("proc"); + if (help_mode || flatten) + run("flatten", "(if -flatten)"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt"); if (help_mode) - run("synth -run coarse [-flatten]", "(with '-flatten')"); + run("wreduce [-keepdc]", "(option for '-widemux')"); else - run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); + run("peepopt"); + run("opt_clean"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -253,6 +268,8 @@ struct SynthXilinxPass : public ScriptPass // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); + + run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { @@ -344,7 +361,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef"); if (help_mode) - run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')"); + run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')"); else if (abc9) { if (family != "xc7") log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); From c8649953431d3789296c4a7c1bd559ec136af6e3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:38:07 -0700 Subject: [PATCH 144/160] Fix typo and comments --- techlibs/xilinx/cells_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index d3f6a60cc..233a56003 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -204,7 +204,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 4) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [4-1:0] Ax; if (A_WIDTH == 4) @@ -215,7 +215,7 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 8) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [8-1:0] Ax; if (A_WIDTH == 8) @@ -230,13 +230,13 @@ module \$__XILINX_SHIFTX (A, B, Y); end else if (A_WIDTH <= 16) begin // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSB + // causing the "don't care" status to get lost, extend with MSBs // so that we can recognise again later when mapping MUXF78 wire [16-1:0] Ax; if (A_WIDTH == 16) assign Ax = A; else - assign Ax = {A[7-:8-A_WIDTH], A}; + assign Ax = {A[7-:16-A_WIDTH], A}; wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] : B[3] ? Ax[ 8] : Ax[0]; wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] From 93522b0ae15466297e45edecf55f7e33c4ebcc1c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:59:37 -0700 Subject: [PATCH 145/160] Extend during mux decomposition with 1'bx --- techlibs/xilinx/cells_map.v | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 233a56003..e81ff8f53 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -203,25 +203,11 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [4-1:0] Ax; - if (A_WIDTH == 4) - assign Ax = A; - else - assign Ax = {A[1-:4-A_WIDTH], A}; + wire [4-1:0] Ax = {{{4-A_WIDTH}{1'bx}}, A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [8-1:0] Ax; - if (A_WIDTH == 8) - assign Ax = A; - else - assign Ax = {A[3-:8-A_WIDTH], A}; + wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? Ax[4] : Ax[0]; wire T1 = B[2] ? Ax[5] : Ax[1]; wire T2 = B[2] ? Ax[6] : Ax[2]; @@ -229,14 +215,7 @@ module \$__XILINX_SHIFTX (A, B, Y); \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 16) begin - // Rather than extend with 1'bx which gets flattened to 1'b0 - // causing the "don't care" status to get lost, extend with MSBs - // so that we can recognise again later when mapping MUXF78 - wire [16-1:0] Ax; - if (A_WIDTH == 16) - assign Ax = A; - else - assign Ax = {A[7-:16-A_WIDTH], A}; + wire [16-1:0] Ax = {{{16-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4] : B[3] ? Ax[ 8] : Ax[0]; wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5] From f8512864cd2b9c0c17d71d4196dbf3f25ec554d1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:01 +0200 Subject: [PATCH 146/160] Add tests/simple_abc9/.gitignore Signed-off-by: Clifford Wolf --- tests/simple_abc9/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/simple_abc9/.gitignore diff --git a/tests/simple_abc9/.gitignore b/tests/simple_abc9/.gitignore new file mode 100644 index 000000000..598951333 --- /dev/null +++ b/tests/simple_abc9/.gitignore @@ -0,0 +1,3 @@ +*.v +*.log +*.out From 3dd92fcd15bc3f1448a97e6bb7c997d36781b55c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:28 +0200 Subject: [PATCH 147/160] Improve tests/various/run-test.sh Signed-off-by: Clifford Wolf --- tests/various/run-test.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh index d49553ede..92b905765 100755 --- a/tests/various/run-test.sh +++ b/tests/various/run-test.sh @@ -4,11 +4,9 @@ for x in *.ys; do echo "Running $x.." ../../yosys -ql ${x%.ys}.log $x done -# Run any .sh files in this directory (with the exception of the file - run-test.sh -shell_tests=$(echo *.sh | sed -e 's/run-test.sh//') -if [ "$shell_tests" ]; then - for s in $shell_tests; do - echo "Running $s.." - bash $s - done -fi +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "Running $s.." + bash $s + fi +done From c18b23f0559f2232186ce3b97b4ffb64877abd5c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 20:58:59 +0200 Subject: [PATCH 148/160] Add tests/various/async.{sh,v} Signed-off-by: Clifford Wolf --- tests/various/async.sh | 6 ++++ tests/various/async.v | 82 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/various/async.sh create mode 100644 tests/various/async.v diff --git a/tests/various/async.sh b/tests/various/async.sh new file mode 100644 index 000000000..423034eb8 --- /dev/null +++ b/tests/various/async.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -ex +../../yosys -q -o async_syn.v -p 'synth; rename uut syn' async.v +iverilog -o async_sim -DTESTBENCH async.v async_syn.v +vvp -N async_sim > async.out +rm -f async_syn.v async_sim async.out async.vcd diff --git a/tests/various/async.v b/tests/various/async.v new file mode 100644 index 000000000..229b5b939 --- /dev/null +++ b/tests/various/async.v @@ -0,0 +1,82 @@ +`define MAXQ 2 +module uut ( + input clk, + input d, r, e, + output [`MAXQ:0] q +); + reg q0; + always @(posedge clk) begin + if (r) + q0 <= 0; + else if (e) + q0 <= d; + end + + reg q1; + always @(posedge clk, posedge r) begin + if (r) + q1 <= 0; + else if (e) + q1 <= d; + end + + reg q2; + always @(posedge clk, negedge r) begin + if (!r) + q2 <= 0; + else if (!e) + q2 <= d; + end + + assign q = {q2, q1, q0}; +endmodule + +`ifdef TESTBENCH +module testbench; + reg clk; + always #5 clk = (clk === 1'b0); + + reg d, r, e; + + wire [`MAXQ:0] q_uut; + uut uut (.clk(clk), .d(d), .r(r), .e(e), .q(q_uut)); + + wire [`MAXQ:0] q_syn; + syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn)); + + task printq; + reg [5*8-1:0] msg; + begin + msg = "OK"; + if (q_uut != q_syn) msg = "SYN"; + $display("%6t %b %b %s", $time, q_uut, q_syn, msg); + if (msg != "OK") $stop; + end + endtask + + initial if(0) begin + $dumpfile("async.vcd"); + $dumpvars(0, testbench); + end + + initial begin + @(posedge clk); + d <= 0; + r <= 0; + e <= 0; + @(posedge clk); + e <= 1; + @(posedge clk); + e <= 0; + repeat (10000) begin + @(posedge clk); + printq; + d <= $random; + r <= $random; + e <= $random; + end + $display("OK"); + $finish; + end +endmodule +`endif From c2db70f41e2697d141439c093813ae48f3b7a5d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 12:14:00 -0700 Subject: [PATCH 149/160] Increment _TECHMAP_BITS_CONNMAP_ by one since counting from zero --- passes/techmap/techmap.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index ab0bd3b54..ceb053825 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -649,10 +649,13 @@ struct TechmapWorker unique_bit_id[bit] = unique_bit_id_counter++; } + // Find highest bit set int bits = 0; for (int i = 0; i < 32; i++) if (((unique_bit_id_counter-1) & (1 << i)) != 0) bits = i; + // Increment index by one to get number of bits + bits++; if (tpl->avail_parameters.count("\\_TECHMAP_BITS_CONNMAP_")) parameters["\\_TECHMAP_BITS_CONNMAP_"] = bits; From 37bb6b5e96fcedc1126c31aac84b8c029e192f5f Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 9 Jul 2019 19:14:03 +0000 Subject: [PATCH 150/160] write_verilog: fix placement of case attributes. NFC. --- backends/verilog/verilog_backend.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6288502a5..087c6fec6 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1501,6 +1501,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw bool got_default = false; for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { + dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true); if ((*it)->compare.size() == 0) { if (got_default) continue; @@ -1514,9 +1515,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, (*it)->compare[i]); } } - f << stringf(":"); - dump_attributes(f, indent, (*it)->attributes, ' ', /*modattr=*/false, /*as_comment=*/true); - f << stringf("\n"); + f << stringf(":\n"); dump_case_body(f, indent + " ", *it); } From b1a048a703b12bc02433d8c2c98b4b35cc799979 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 12:35:41 -0700 Subject: [PATCH 151/160] Extend using A[1] to preserve don't care --- techlibs/xilinx/cells_map.v | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e81ff8f53..f20fe253e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -203,7 +203,15 @@ module \$__XILINX_SHIFTX (A, B, Y); MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .O(Y)); end else if (A_WIDTH <= 4) begin - wire [4-1:0] Ax = {{{4-A_WIDTH}{1'bx}}, A}; + wire [4-1:0] Ax; + if (A_WIDTH == 4) + assign Ax = A; + else + // Rather than extend with 1'bx which gets flattened to 1'b0 + // causing the "don't care" status to get lost, extend with + // the same driver of F7B.I0 so that we can optimise F7B away + // later + assign Ax = {A[1], A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end else if (A_WIDTH <= 8) begin From 513862148211401fe71fb7966c81773042665acd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 22:21:25 +0200 Subject: [PATCH 152/160] Improve tests/various/async, disable failing ffl test Signed-off-by: Clifford Wolf --- tests/various/async.sh | 9 +++++++-- tests/various/async.v | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tests/various/async.sh b/tests/various/async.sh index 423034eb8..7c41d6d94 100644 --- a/tests/various/async.sh +++ b/tests/various/async.sh @@ -1,6 +1,11 @@ #!/bin/bash set -ex ../../yosys -q -o async_syn.v -p 'synth; rename uut syn' async.v -iverilog -o async_sim -DTESTBENCH async.v async_syn.v +../../yosys -q -o async_prp.v -p 'prep; rename uut prp' async.v +../../yosys -q -o async_a2s.v -p 'prep; async2sync; rename uut a2s' async.v +../../yosys -q -o async_ffl.v -p 'prep; clk2fflogic; rename uut ffl' async.v +iverilog -o async_sim -DTESTBENCH async.v async_???.v vvp -N async_sim > async.out -rm -f async_syn.v async_sim async.out async.vcd +tail async.out +grep PASS async.out +rm -f async_???.v async_sim async.out async.vcd diff --git a/tests/various/async.v b/tests/various/async.v index 229b5b939..1e32a06b5 100644 --- a/tests/various/async.v +++ b/tests/various/async.v @@ -32,9 +32,23 @@ module uut ( endmodule `ifdef TESTBENCH +module \$ff #( + parameter integer WIDTH = 1 +) ( + input [WIDTH-1:0] D, + output reg [WIDTH-1:0] Q +); + wire sysclk = testbench.sysclk; + always @(posedge sysclk) + Q <= D; +endmodule + module testbench; + reg sysclk; + always #5 sysclk = (sysclk === 1'b0); + reg clk; - always #5 clk = (clk === 1'b0); + always @(posedge sysclk) clk = (clk === 1'b0); reg d, r, e; @@ -44,13 +58,25 @@ module testbench; wire [`MAXQ:0] q_syn; syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn)); + wire [`MAXQ:0] q_prp; + prp prp (.clk(clk), .d(d), .r(r), .e(e), .q(q_prp)); + + wire [`MAXQ:0] q_a2s; + a2s a2s (.clk(clk), .d(d), .r(r), .e(e), .q(q_a2s)); + + wire [`MAXQ:0] q_ffl; + ffl ffl (.clk(clk), .d(d), .r(r), .e(e), .q(q_ffl)); + task printq; reg [5*8-1:0] msg; begin msg = "OK"; - if (q_uut != q_syn) msg = "SYN"; - $display("%6t %b %b %s", $time, q_uut, q_syn, msg); - if (msg != "OK") $stop; + if (q_uut !== q_syn) msg = "SYN"; + if (q_uut !== q_prp) msg = "PRP"; + if (q_uut !== q_a2s) msg = "A2S"; + // if (q_uut !== q_ffl) msg = "FFL"; + $display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg); + if (msg != "OK") $finish; end endtask @@ -75,7 +101,7 @@ module testbench; r <= $random; e <= $random; end - $display("OK"); + $display("PASS"); $finish; end endmodule From 9546ccdbd348b1dc056884a536246801cdf1c4f1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Jul 2019 22:44:39 +0200 Subject: [PATCH 153/160] Fix tests/various/async FFL test Signed-off-by: Clifford Wolf --- passes/sat/clk2fflogic.cc | 7 +++++++ tests/various/async.v | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index 49ec795d3..4bb4aa047 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -253,6 +253,13 @@ struct Clk2fflogicPass : public Pass { SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge); Const rstval = cell->parameters["\\ARST_VALUE"]; + Wire *past_arst = module->addWire(NEW_ID); + module->addFf(NEW_ID, arst, past_arst); + if (cell->parameters["\\ARST_POLARITY"].as_bool()) + arst = module->LogicOr(NEW_ID, arst, past_arst); + else + arst = module->LogicAnd(NEW_ID, arst, past_arst); + if (cell->parameters["\\ARST_POLARITY"].as_bool()) module->addMux(NEW_ID, qval, rstval, arst, sig_q); else diff --git a/tests/various/async.v b/tests/various/async.v index 1e32a06b5..c27e30c4b 100644 --- a/tests/various/async.v +++ b/tests/various/async.v @@ -74,7 +74,7 @@ module testbench; if (q_uut !== q_syn) msg = "SYN"; if (q_uut !== q_prp) msg = "PRP"; if (q_uut !== q_a2s) msg = "A2S"; - // if (q_uut !== q_ffl) msg = "FFL"; + if (q_uut !== q_ffl) msg = "FFL"; $display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg); if (msg != "OK") $finish; end From 27b27b8781ab8d57aa85a432aba7e914570feffb Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 9 Jul 2019 22:26:10 +0100 Subject: [PATCH 154/160] synth_ecp5: Fix typo in copyright header Signed-off-by: David Shah --- techlibs/ecp5/synth_ecp5.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index f16a47f01..3b0c2ea9e 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 David Shah * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above From 5b48b18d29dabfaa3aa51fc4946f14b0ea8954e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 14:28:54 -0700 Subject: [PATCH 155/160] Restore missing techmap -map +/cmp2lut.v with LUT_WIDTH=6 --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0152af481..7e10a392a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -252,6 +253,7 @@ struct SynthXilinxPass : public ScriptPass run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); run("alumacc"); run("share"); run("opt"); From c55530b90197302e7c27eb106094fa74a178fc67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 14:29:58 -0700 Subject: [PATCH 156/160] Restore opt_clean back to original place --- techlibs/xilinx/synth_xilinx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7e10a392a..c4877c8af 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -260,6 +260,7 @@ struct SynthXilinxPass : public ScriptPass run("fsm"); run("opt -fast"); run("memory -nomap"); + run("opt_clean"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -270,8 +271,6 @@ struct SynthXilinxPass : public ScriptPass // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); - - run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { From e573d024a257a6cf8925784f6f22d192a1f24693 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 21:26:38 -0700 Subject: [PATCH 157/160] Call muxpack and pmux2shiftx before cmp2lut --- techlibs/xilinx/synth_xilinx.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c4877c8af..ef7660288 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -253,14 +253,6 @@ struct SynthXilinxPass : public ScriptPass run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); run("peepopt"); run("opt_clean"); - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); - run("alumacc"); - run("share"); - run("opt"); - run("fsm"); - run("opt -fast"); - run("memory -nomap"); - run("opt_clean"); if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); @@ -269,8 +261,19 @@ struct SynthXilinxPass : public ScriptPass // cells for identifying variable-length shift registers, // so attempt to convert $pmux-es to the former // Also: wide multiplexer inference benefits from this too - if (!(nosrl && widemux == 0) || help_mode) + if (!(nosrl && widemux == 0) || help_mode) { run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); + run("clean", " (skip if '-nosrl' and '-widemux=0')"); + } + + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); + run("alumacc"); + run("share"); + run("opt"); + run("fsm"); + run("opt -fast"); + run("memory -nomap"); + run("opt_clean"); } if (check_label("bram", "(skip if '-nobram')")) { From 521971e32ef54fa64474a8ed1c2748572901aaf5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:20:04 -0700 Subject: [PATCH 158/160] Add some ASCII art explaining mux decomposition --- techlibs/xilinx/cells_map.v | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index f20fe253e..82399be08 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -214,6 +214,27 @@ module \$__XILINX_SHIFTX (A, B, Y); assign Ax = {A[1], A}; \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y)); end + // Note that the following decompositions are 'backwards' in that + // the LSBs are placed on the hard resources, and the soft resources + // are used for MSBs. + // This has the effect of more effectively utilising the hard mux; + // take for example a 5:1 multiplexer, currently this would map as: + // + // A[0] \___ __ A[0] \__ __ + // A[4] / \| \ whereas the more A[1] / \| \ + // A[1] _____| | obvious mapping A[2] \___| | + // A[2] _____| |-- of MSBs to hard A[3] / | |__ + // A[3]______| | resources would A[4] ____| | + // |__/ lead to: 1'bx ____| | + // || |__/ + // || || + // B[1:0] B[1:2] + // + // Expectation would be that the 'forward' mapping (right) is more + // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers + // on its I0 and I1 inputs, and A[8] and 1'bx on its I2 and I3 inputs) + // but that the 'backwards' mapping (left) is more delay efficient + // since smaller LUTs are faster than wider ones. else if (A_WIDTH <= 8) begin wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A}; wire T0 = B[2] ? Ax[4] : Ax[0]; From 58bb84e5b22ba66310fd54fecdbf5817138a5fd1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:32:33 -0700 Subject: [PATCH 159/160] Add some spacing --- techlibs/xilinx/cells_map.v | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 82399be08..2eb9fa2c1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -220,15 +220,15 @@ module \$__XILINX_SHIFTX (A, B, Y); // This has the effect of more effectively utilising the hard mux; // take for example a 5:1 multiplexer, currently this would map as: // - // A[0] \___ __ A[0] \__ __ - // A[4] / \| \ whereas the more A[1] / \| \ - // A[1] _____| | obvious mapping A[2] \___| | - // A[2] _____| |-- of MSBs to hard A[3] / | |__ - // A[3]______| | resources would A[4] ____| | - // |__/ lead to: 1'bx ____| | - // || |__/ - // || || - // B[1:0] B[1:2] + // A[0] \___ __ A[0] \__ __ + // A[4] / \| \ whereas the more A[1] / \| \ + // A[1] _____| | obvious mapping A[2] \___| | + // A[2] _____| |-- of MSBs to hard A[3] / | |__ + // A[3]______| | resources would A[4] ____| | + // |__/ lead to: 1'bx ____| | + // || |__/ + // || || + // B[1:0] B[1:2] // // Expectation would be that the 'forward' mapping (right) is more // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers From 6bbd286e033ed25bb49684316a86d6227dec4cd7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 12:47:48 -0700 Subject: [PATCH 160/160] Error out if -abc9 and -retime specified --- techlibs/ecp5/synth_ecp5.cc | 3 +++ techlibs/ice40/synth_ice40.cc | 5 ++++- techlibs/xilinx/synth_xilinx.cc | 13 ++++++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 3b0c2ea9e..9f409ca51 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -199,6 +199,9 @@ struct SynthEcp5Pass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_ECP5 pass.\n"); log_push(); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 9dd5d81f7..2c75215cb 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -227,6 +227,9 @@ struct SynthIce40Pass : public ScriptPass if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); + if (abc == "abc9" && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_ICE40 pass.\n"); log_push(); @@ -296,7 +299,7 @@ struct SynthIce40Pass : public ScriptPass run("techmap"); else run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); - if ((retime || help_mode) && abc != "abc9") + if (retime || help_mode) run(abc + " -dff", "(only if -retime)"); run("ice40_opt"); } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b7c32d2e0..22c4a1a1b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,8 +25,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate - // to one LUT6 (instead of a LUT5 + LUT2) +#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate + // to one LUT6 (instead of a LUT5 + LUT2) struct SynthXilinxPass : public ScriptPass { @@ -195,11 +195,14 @@ struct SynthXilinxPass : public ScriptPass extra_args(args, argidx, design); if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s") - log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); + log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str()); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + log_header(design, "Executing SYNTH_XILINX pass.\n"); log_push(); @@ -297,9 +300,9 @@ struct SynthXilinxPass : public ScriptPass if (family != "xc7") log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); if (nowidelut) - run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); + run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY)); else - run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : "")); + run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY)); } else { if (nowidelut)