diff options
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r-- | techlibs/xilinx/arith_map.v | 114 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 108 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 44 | ||||
-rw-r--r-- | techlibs/xilinx/xc7_dsp_map.v | 1 |
4 files changed, 80 insertions, 187 deletions
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v index 2fc216908..eb8a04bde 100644 --- a/techlibs/xilinx/arith_map.v +++ b/techlibs/xilinx/arith_map.v @@ -35,13 +35,7 @@ module _80_xilinx_lcu (P, G, CI, CO); genvar i; -`ifdef _EXPLICIT_CARRY - localparam EXPLICIT_CARRY = 1'b1; -`else - localparam EXPLICIT_CARRY = 1'b0; -`endif - -generate if (EXPLICIT_CARRY || `LUT_SIZE == 4) begin +generate if (`LUT_SIZE == 4) begin (* force_downto *) wire [WIDTH-1:0] C = {CO, CI}; @@ -135,12 +129,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); genvar i; -`ifdef _EXPLICIT_CARRY - localparam EXPLICIT_CARRY = 1'b1; -`else - localparam EXPLICIT_CARRY = 1'b0; -`endif - generate if (`LUT_SIZE == 4) begin (* force_downto *) @@ -163,106 +151,6 @@ generate if (`LUT_SIZE == 4) begin ); end endgenerate -end else if (EXPLICIT_CARRY) begin - - (* force_downto *) - wire [Y_WIDTH-1:0] S = AA ^ BB; - - wire CINIT; - // Carry chain. - // - // VPR requires that the carry chain never hit the fabric. The CO input - // to this techmap is the carry outputs for synthesis, e.g. might hit the - // fabric. - // - // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR, - // e.g. off fabric dedicated chain. CO is the carry outputs that are - // available to the fabric. - (* force_downto *) - wire [Y_WIDTH-1:0] CO_CHAIN; - (* force_downto *) - wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT}; - - // If carry chain is being initialized to a constant, techmap the constant - // source. Otherwise techmap the fabric source. - generate for (i = 0; i < 1; i = i + 1) begin:slice - CARRY0 #(.CYINIT_FABRIC(1)) carry( - .CI_INIT(CI), - .DI(AA[0]), - .S(S[0]), - .CO_CHAIN(CO_CHAIN[0]), - .CO_FABRIC(CO[0]), - .O(Y[0]) - ); - end endgenerate - - generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice - if(i % 4 == 0) begin - CARRY0 carry ( - .CI(C[i]), - .DI(AA[i]), - .S(S[i]), - .CO_CHAIN(CO_CHAIN[i]), - .CO_FABRIC(CO[i]), - .O(Y[i]) - ); - end - else - begin - CARRY carry ( - .CI(C[i]), - .DI(AA[i]), - .S(S[i]), - .CO_CHAIN(CO_CHAIN[i]), - .CO_FABRIC(CO[i]), - .O(Y[i]) - ); - end - end endgenerate - - generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice - if(i % 4 == 0) begin - CARRY0 top_of_carry ( - .CI(C[i]), - .DI(AA[i]), - .S(S[i]), - .CO_CHAIN(CO_CHAIN[i]), - .O(Y[i]) - ); - end - else - begin - CARRY top_of_carry ( - .CI(C[i]), - .DI(AA[i]), - .S(S[i]), - .CO_CHAIN(CO_CHAIN[i]), - .O(Y[i]) - ); - end - // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide - // a non-congested path to output the top of the carry chain. - // Registering the output of the CARRY block would solve this, but not - // all designs do that. - if((i+1) % 4 == 0) begin - CARRY0 carry_output ( - .CI(CO_CHAIN[i]), - .DI(0), - .S(0), - .O(CO[i]) - ); - end - else - begin - CARRY carry_output ( - .CI(CO_CHAIN[i]), - .DI(0), - .S(0), - .O(CO[i]) - ); - end - end endgenerate - end else begin localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index f5850d8a2..4162160bb 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -455,29 +455,6 @@ module CARRY8( assign CO[7] = S[7] ? CO[6] : DI[7]; endmodule -`ifdef _EXPLICIT_CARRY - -module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S); - parameter CYINIT_FABRIC = 0; - wire CI_COMBINE; - if(CYINIT_FABRIC) begin - assign CI_COMBINE = CI_INIT; - end else begin - assign CI_COMBINE = CI; - end - assign CO_CHAIN = S ? CI_COMBINE : DI; - assign CO_FABRIC = S ? CI_COMBINE : DI; - assign O = S ^ CI_COMBINE; -endmodule - -module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S); - assign CO_CHAIN = S ? CI : DI; - assign CO_FABRIC = S ? CI : DI; - assign O = S ^ CI; -endmodule - -`endif - module ORCY (output O, input CI, I); assign O = CI | I; endmodule @@ -2358,6 +2335,8 @@ parameter integer PREG = 1; // The multiplier. wire signed [35:0] P_MULT; +wire signed [17:0] A_MULT; +wire signed [17:0] B_MULT; assign P_MULT = A_MULT * B_MULT; // The cascade output. @@ -2396,8 +2375,6 @@ always @(posedge CLK) begin end // The register enables. -wire signed [17:0] A_MULT; -wire signed [17:0] B_MULT; assign A_MULT = (AREG == 1) ? A_REG : A; assign B_MULT = (BREG == 1) ? B_REG : B_MUX; assign P = (PREG == 1) ? P_REG : P_MULT; @@ -3037,8 +3014,12 @@ endmodule // Virtex 6, Series 7. `ifdef YOSYS -(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG), - lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *) +(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) +`ifdef ALLOW_WHITEBOX_DSP48E1 + // Do not make DSP48E1 a whitebox for ABC9 even if fully combinatorial, since it is a big complex block + , lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG || INMODEREG || OPMODEREG || ALUMODEREG || CARRYINREG || CARRYINSELREG) +`endif +*) `endif module DSP48E1 ( output [29:0] ACOUT, @@ -3526,11 +3507,15 @@ module DSP48E1 ( if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); `endif end - 2'b10: begin X = P; + 2'b10: + if (PREG == 1) + X = P; + else begin + X = 48'bx; `ifndef YOSYS - if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); + $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); `endif - end + end 2'b11: X = $signed({Ar2, Br2}); default: X = 48'bx; endcase @@ -3552,20 +3537,36 @@ module DSP48E1 ( case (OPMODEr[6:4]) 3'b000: Z = 48'b0; 3'b001: Z = PCIN; - 3'b010: begin Z = P; + 3'b010: + if (PREG == 1) + Z = P; + else begin + Z = 48'bx; `ifndef YOSYS - if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); + $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b010"); `endif - end + end 3'b011: Z = Cr; - 3'b100: begin Z = P; + 3'b100: + if (PREG == 1 && OPMODEr[3:0] === 4'b1000) + Z = P; + else begin + Z = 48'bx; `ifndef YOSYS - if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); - if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); + if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); + if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); `endif - end + end 3'b101: Z = $signed(PCIN[47:17]); - 3'b110: Z = $signed(P[47:17]); + 3'b110: + if (PREG == 1) + Z = $signed(P[47:17]); + else begin + Z = 48'bx; +`ifndef YOSYS + $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b110"); +`endif + end default: Z = 48'bx; endcase end @@ -3591,10 +3592,34 @@ module DSP48E1 ( 3'b001: cin_muxed = ~PCIN[47]; 3'b010: cin_muxed = CARRYCASCIN; 3'b011: cin_muxed = PCIN[47]; - 3'b100: cin_muxed = CARRYCASCOUT; - 3'b101: cin_muxed = ~P[47]; + 3'b100: + if (PREG == 1) + cin_muxed = CARRYCASCOUT; + else begin + cin_muxed = 1'bx; +`ifndef YOSYS + $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b100"); +`endif + end + 3'b101: + if (PREG == 1) + cin_muxed = ~P[47]; + else begin + cin_muxed = 1'bx; +`ifndef YOSYS + $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b101"); +`endif + end 3'b110: cin_muxed = A24_xnor_B17; - 3'b111: cin_muxed = P[47]; + 3'b111: + if (PREG == 1) + cin_muxed = P[47]; + else begin + cin_muxed = 1'bx; +`ifndef YOSYS + $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b111"); +`endif + end default: cin_muxed = 1'bx; endcase end @@ -4186,4 +4211,3 @@ module RAMB36E1 ( if (|DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 4'bx)) = 882; endspecify endmodule - diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 421602e62..0adec57a2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -77,10 +77,6 @@ struct SynthXilinxPass : public ScriptPass log(" write the design to the specified BLIF file. writing of an output file\n"); log(" is omitted if this parameter is not specified.\n"); log("\n"); - log(" -vpr\n"); - log(" generate an output netlist (and BLIF file) suitable for VPR\n"); - log(" (this feature is experimental and incomplete)\n"); - log("\n"); log(" -ise\n"); log(" generate an output netlist suitable for ISE\n"); log("\n"); @@ -142,7 +138,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; + bool flatten, retime, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; bool abc9, dff; bool flatten_before_abc; int widemux; @@ -157,7 +153,6 @@ struct SynthXilinxPass : public ScriptPass family = "xc7"; flatten = false; retime = false; - vpr = false; ise = false; noiopad = false; noclkbuf = false; @@ -229,10 +224,6 @@ struct SynthXilinxPass : public ScriptPass nowidelut = true; continue; } - if (args[argidx] == "-vpr") { - vpr = true; - continue; - } if (args[argidx] == "-ise") { ise = true; continue; @@ -345,8 +336,6 @@ struct SynthXilinxPass : public ScriptPass if (check_label("begin")) { std::string read_args; - if (vpr) - read_args += " -D_EXPLICIT_CARRY"; read_args += " -lib -specify +/xilinx/cells_sim.v"; run("read_verilog" + read_args); @@ -368,6 +357,8 @@ struct SynthXilinxPass : public ScriptPass run("opt_expr"); run("opt_clean"); run("check"); + run("opt -nodffe -nosdff"); + run("fsm"); run("opt"); if (help_mode) run("wreduce [-keepdc]", "(option for '-widemux')"); @@ -455,8 +446,6 @@ struct SynthXilinxPass : public ScriptPass run("alumacc"); run("share"); run("opt"); - run("fsm"); - run("opt -fast"); run("memory -nomap"); run("opt_clean"); } @@ -515,28 +504,21 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_ffram")) { - // Required for dff2dffs to work. - run("simplemap t:$dff t:$adff t:$mux"); - // Needs to be done before opt -mux_bool happens. - if (help_mode) - run("dff2dffs [-match-init]", "(-match-init for xc6s only)"); - else if (family == "xc6s") - run("dff2dffs -match-init"); - else - run("dff2dffs"); - if (widemux > 0) + if (widemux > 0) { run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover // performs less efficiently - else + } else { run("opt -fast -full"); + } run("memory_map"); } if (check_label("fine")) { - run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*"); - if (help_mode) - run("muxcover <internal options> ('-widemux' only)"); - else if (widemux > 0) { + if (help_mode) { + run("simplemap t:$mux", "('-widemux' only)"); + run("muxcover <internal options>", "('-widemux' only)"); + } else if (widemux > 0) { + run("simplemap t:$mux"); constexpr int cost_mux2 = 100; std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); switch (widemux) { @@ -570,8 +552,6 @@ struct SynthXilinxPass : public ScriptPass techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux); if (!nocarry) { techmap_args += " -map +/xilinx/arith_map.v"; - if (vpr) - techmap_args += " -D _EXPLICIT_CARRY"; } run("techmap " + techmap_args); run("opt -fast"); @@ -603,7 +583,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_luts")) { - run("opt_expr -mux_undef"); + run("opt_expr -mux_undef -noclkinv"); if (flatten_before_abc) run("flatten"); if (help_mode) diff --git a/techlibs/xilinx/xc7_dsp_map.v b/techlibs/xilinx/xc7_dsp_map.v index a4256eb92..58df977ec 100644 --- a/techlibs/xilinx/xc7_dsp_map.v +++ b/techlibs/xilinx/xc7_dsp_map.v @@ -33,6 +33,7 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); .B(B), .C(48'b0), .D(25'b0), + .CARRYIN(1'b0), .P(P_48), .INMODE(5'b00000), |