From d855683917b42555c1e3472e71c957335574655c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 26 Apr 2019 16:53:16 -0700 Subject: [PATCH 1/6] Revert synth_xilinx 'fine' label more to how it used to be... --- techlibs/xilinx/synth_xilinx.cc | 61 +++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 58dd928a0..45ad1c465 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -108,23 +108,23 @@ struct SynthXilinxPass : public Pass log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); log(" fine:\n"); - log(" opt -fast\n"); + log(" opt -fast -full\n"); log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" techmap -map +/xilinx/arith_map.v\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt -full\n"); + log(" techmap\n"); + log(" opt -fast\n"); + log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); - log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); - log(" pmux2shiftx (without '-nosrl' only)\n"); - log(" opt_expr -mux_undef (without '-nosrl' only)\n"); - log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/xilinx/cells_map.v\n"); log(" clean\n"); log("\n"); log(" map_luts:\n"); - log(" opt -full\n"); log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); log(" clean\n"); @@ -262,9 +262,30 @@ struct SynthXilinxPass : public Pass } } + log(" fine:\n"); + log(" opt -fast -full\n"); + log(" memory_map\n"); + log(" dffsr2dff\n"); + log(" dff2dffe\n"); + log(" techmap -map +/xilinx/arith_map.v\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt -full\n"); + log(" techmap\n"); + log(" opt -fast\n"); + log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); + log(" opt -fast\n"); + log("\n"); + log(" map_cells:\n"); + log(" techmap -map +/xilinx/cells_map.v\n"); + log(" clean\n"); + log("\n"); + log(" map_luts:\n"); + log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); + + if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "opt -fast"); + Pass::call(design, "opt -fast -full"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); @@ -275,25 +296,24 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/xilinx/arith_map.v"); } + Pass::call(design, "opt -full"); + Pass::call(design, "techmap"); + Pass::call(design, "opt -fast"); + + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifiying variable-length shift registers, + // so attempt to convert $pmux-es to the former + if (!nosrl) + Pass::call(design, "pmux2shiftx"); + Pass::call(design, "opt -fast"); } if (check_label(active, run_from, run_to, "map_cells")) { - if (!nosrl) { - // shregmap operates on bit-level flops, not word-level, - // so break those down here - Pass::call(design, "simplemap t:$dff t:$dffe"); - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifiying variable-length shift registers, - // so attempt to convert $pmux-es to the former - Pass::call(design, "pmux2shiftx"); - // pmux2shiftx can leave behind a $pmux with a single entry - // -- need this to clean that up before shregmap - Pass::call(design, "opt_expr -mux_undef"); - // shregmap with '-tech xilinx' infers variable length shift regs + // shregmap with '-tech xilinx' infers variable length shift regs + if (!nosrl) Pass::call(design, "shregmap -tech xilinx -minlen 3"); - } Pass::call(design, "techmap -map +/xilinx/cells_map.v"); Pass::call(design, "clean"); @@ -301,7 +321,6 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); From af840bbc63a9a82a9c4e2c24476c70659efee63f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 28 Apr 2019 12:36:04 -0700 Subject: [PATCH 2/6] Move neg-pol to pos-pol mapping from ff_map to cells_map.v --- techlibs/xilinx/cells_map.v | 8 ++++++++ techlibs/xilinx/ff_map.v | 13 ++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 704ab21b1..b29238a12 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -17,6 +17,14 @@ * */ +// Convert negative-polarity reset to positive-polarity +module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + + module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index c61fd7070..13beaa6ae 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -22,26 +22,21 @@ `ifndef _NO_FFS -`ifndef _NO_POS_SR module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule +module \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule -`endif - -module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule - -module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule -`endif `endif From e97178a888cebc6acacb8f8f2c68d4f9743a9284 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 28 Apr 2019 12:51:00 -0700 Subject: [PATCH 3/6] WIP --- techlibs/xilinx/synth_xilinx.cc | 60 +++++++++++++-------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 45ad1c465..ba9efc658 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -113,12 +113,14 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" techmap -map +/xilinx/arith_map.v\n"); - log(" pmux2shiftx (without '-nosrl' only)\n"); log(" opt -full\n"); - log(" techmap\n"); - log(" opt -fast\n"); + log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" opt -fast\n"); + log(" techmap\n"); + log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); log(" techmap -map +/xilinx/cells_map.v\n"); @@ -262,29 +264,15 @@ struct SynthXilinxPass : public Pass } } - log(" fine:\n"); - log(" opt -fast -full\n"); - log(" memory_map\n"); - log(" dffsr2dff\n"); - log(" dff2dffe\n"); - log(" techmap -map +/xilinx/arith_map.v\n"); - log(" pmux2shiftx (without '-nosrl' only)\n"); - log(" opt -full\n"); - log(" techmap\n"); - log(" opt -fast\n"); - log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); - log(" opt -fast\n"); - log("\n"); - log(" map_cells:\n"); - log(" techmap -map +/xilinx/cells_map.v\n"); - log(" clean\n"); - log("\n"); - log(" map_luts:\n"); - log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); - - if (check_label(active, run_from, run_to, "fine")) { + if (!nosrl) { + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifiying variable-length shift registers, + // so attempt to convert $pmux-es to the former + Pass::call(design, "pmux2shiftx"); + } + Pass::call(design, "opt -fast -full"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); @@ -297,31 +285,29 @@ struct SynthXilinxPass : public Pass } Pass::call(design, "opt -full"); + + if (!nosrl) { + // shregmap operates on bit-level flops, not word-level, + // so break those down here + Pass::call(design, "simplemap t:$dff t:$dffe"); + Pass::call(design, "show -format pdf -prefix show *depth=3*"); + // shregmap with '-tech xilinx' infers variable length shift regs + Pass::call(design, "shregmap -tech xilinx -minlen 3"); + Pass::call(design, "opt -fast"); + } + Pass::call(design, "techmap"); Pass::call(design, "opt -fast"); - - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifiying variable-length shift registers, - // so attempt to convert $pmux-es to the former - if (!nosrl) - Pass::call(design, "pmux2shiftx"); - - Pass::call(design, "opt -fast"); } if (check_label(active, run_from, run_to, "map_cells")) { - // shregmap with '-tech xilinx' infers variable length shift regs - if (!nosrl) - Pass::call(design, "shregmap -tech xilinx -minlen 3"); - Pass::call(design, "techmap -map +/xilinx/cells_map.v"); Pass::call(design, "clean"); } if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); // This shregmap call infers fixed length shift registers after abc From acafcdc94dc148b2bf9c8faef173e5b2b54e1ac5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 28 Apr 2019 13:04:34 -0700 Subject: [PATCH 4/6] Copy with 1'bx padding in $shiftx --- passes/techmap/shregmap.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a541b33be..75eedfbcc 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -178,7 +178,17 @@ struct ShregmapTechXilinx7 : ShregmapTech // Only map if $shiftx exclusively covers the shift register if (shiftx->type == "$shiftx") { - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + if (GetSize(taps) > shiftx->getParam("\\A_WIDTH").as_int()) + return false; + // Due to padding the most significant bits of A may be 1'bx, + // and if so, discount them + if (GetSize(taps) < shiftx->getParam("\\A_WIDTH").as_int()) { + const SigSpec A = shiftx->getPort("\\A"); + const int A_width = shiftx->getParam("\\A_WIDTH").as_int(); + for (int i = GetSize(taps); i < A_width; ++i) + if (A[i] != RTLIL::Sx) return false; + } + else if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } else if (shiftx->type == "$mux") { From 6ea09caf01cf06ad7f93eb62fa85ec9361b7e5a1 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 1 May 2019 16:21:13 -0700 Subject: [PATCH 5/6] Re-indent firrtl.cc:struct memory - no functional change. --- backends/firrtl/firrtl.cc | 50 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index a8a1bb078..9feff71c6 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -163,20 +163,20 @@ struct FirrtlWorker } }; /* Memories defined within this module. */ - struct memory { - Cell *pCell; // for error reporting - string name; // memory name - int abits; // number of address bits - int size; // size (in units) of the memory - int width; // size (in bits) of each element - int read_latency; - int write_latency; - vector read_ports; - vector write_ports; - std::string init_file; - std::string init_file_srcFileSpec; - string srcLine; - memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { + struct memory { + Cell *pCell; // for error reporting + string name; // memory name + int abits; // number of address bits + int size; // size (in units) of the memory + int width; // size (in bits) of each element + int read_latency; + int write_latency; + vector read_ports; + vector write_ports; + std::string init_file; + std::string init_file_srcFileSpec; + string srcLine; + memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { // Provide defaults for abits or size if one (but not the other) is specified. if (this->abits == 0 && this->size != 0) { this->abits = ceil_log2(this->size); @@ -206,18 +206,18 @@ struct FirrtlWorker } return srcLine.c_str(); } - void add_memory_read_port(read_port &rp) { - read_ports.push_back(rp); - } - void add_memory_write_port(write_port &wp) { - write_ports.push_back(wp); - } - void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { - this->init_file = init_file; - this->init_file_srcFileSpec = init_file_srcFileSpec; - } + void add_memory_read_port(read_port &rp) { + read_ports.push_back(rp); + } + void add_memory_write_port(write_port &wp) { + write_ports.push_back(wp); + } + void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { + this->init_file = init_file; + this->init_file_srcFileSpec = init_file_srcFileSpec; + } - }; + }; dict memories; void register_memory(memory &m) From d394b9301b2619b8cb64f9faea4c112bf2a07925 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 1 May 2019 18:23:21 -0700 Subject: [PATCH 6/6] Back to passing all xc7srl tests! --- techlibs/xilinx/synth_xilinx.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index dbafec301..8aa7b508e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -205,17 +205,16 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("fine")) { - run("opt -fast"); - run("memory_map"); - run("dffsr2dff"); - run("dff2dffe"); - // shregmap -tech xilinx can cope with $shiftx and $mux // cells for identifiying variable-length shift registers, // so attempt to convert $pmux-es to the former if (!nosrl || help_mode) run("pmux2shiftx", "(skip if '-nosrl')"); + run("opt -fast -full"); + run("memory_map"); + run("dffsr2dff"); + run("dff2dffe"); run("opt -full"); if (!vpr || help_mode)