xilinx: Support multiplier mapping for all families.

This supports several older families that are not yet supported for
actual logic synthesis — the intention is to add them soon.
This commit is contained in:
Marcin Kościelnicki 2019-10-08 17:00:30 +00:00
parent a3a7bb9bf7
commit 7b350cacd4
9 changed files with 269 additions and 9 deletions

View File

@ -42,7 +42,13 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_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/dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3s_mult_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3sda_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc4v_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v))

View File

@ -343,14 +343,51 @@ struct SynthXilinxPass : public ScriptPass
if (!nodsp || help_mode) {
run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first
// NB: Xilinx multipliers are signed only
run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
if (help_mode)
run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}");
else if (family == "xc2v" || family == "xc3s" || family == "xc3se" || family == "xc3sa")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc3sda")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc3sda_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc6s")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc6s_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc4v")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc4v_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
else if (family == "xc5v")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc5v_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
else if (family == "xc6v" || family == "xc7")
run("techmap -map +/mul2dsp.v -map +/xilinx/xc7_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
else if (family == "xcu" || family == "xcup")
run("techmap -map +/mul2dsp.v -map +/xilinx/xcu_dsp_map.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=18 "
"-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
// limited to 18x18 in order to take
// advantage of the (PCOUT << 17) -> PCIN
// dedicated cascade chain capability
"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL27X18");
run("select a:mul2dsp");
run("setattr -unset mul2dsp");
run("opt_expr -fine");

View File

@ -0,0 +1,14 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
MULT18X18 _TECHMAP_REPLACE_ (
.A(A),
.B(B),
.P(Y)
);
endmodule

View File

@ -0,0 +1,34 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48A #(
// Disable all registers
.A0REG(0),
.A1REG(0),
.B0REG(0),
.B1REG(0),
.CARRYINREG(0),
.CARRYINSEL("OPMODE5"),
.CREG(0),
.DREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0)
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,38 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48 #(
// Disable all registers
.AREG(0),
.BREG(0),
.B_INPUT("DIRECT"),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.SUBTRACTREG(0),
.LEGACY_MODE("MULT18X18")
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.P(P_48),
.SUBTRACT(1'b0),
.OPMODE(7'b000101),
.CARRYINSEL(2'b00),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,45 @@
module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48E #(
// Disable all registers
.ACASCREG(0),
.A_INPUT("DIRECT"),
.ALUMODEREG(0),
.AREG(0),
.BCASCREG(0),
.B_INPUT("DIRECT"),
.BREG(0),
.MULTCARRYINREG(0),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.USE_MULT("MULT"),
.USE_SIMD("ONE48")
) _TECHMAP_REPLACE_ (
//Data path
.A({{5{A[24]}}, A}),
.B(B),
.C(48'b0),
.P(P_48),
.ALUMODE(4'b0000),
.OPMODE(7'b000101),
.CARRYINSEL(3'b000),
.ACIN(30'b0),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,35 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48A1 #(
// Disable all registers
.A0REG(0),
.A1REG(0),
.B0REG(0),
.B1REG(0),
.CARRYINREG(0),
.CARRYINSEL("OPMODE5"),
.CREG(0),
.DREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0)
) _TECHMAP_REPLACE_ (
//Data path
.A(A),
.B(B),
.C(48'b0),
.D(18'b0),
.P(P_48),
.OPMODE(8'b0000010)
);
assign Y = P_48;
endmodule

View File

@ -0,0 +1,51 @@
module \$__MUL27X18 (input [26:0] A, input [17:0] B, output [44:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [47:0] P_48;
DSP48E2 #(
// Disable all registers
.ACASCREG(0),
.ADREG(0),
.A_INPUT("DIRECT"),
.ALUMODEREG(0),
.AREG(0),
.BCASCREG(0),
.B_INPUT("DIRECT"),
.BREG(0),
.CARRYINREG(0),
.CARRYINSELREG(0),
.CREG(0),
.DREG(0),
.INMODEREG(0),
.MREG(0),
.OPMODEREG(0),
.PREG(0),
.USE_MULT("MULTIPLY"),
.USE_SIMD("ONE48"),
.AMULTSEL("A"),
.BMULTSEL("B")
) _TECHMAP_REPLACE_ (
//Data path
.A({{3{A[26]}}, A}),
.B(B),
.C(48'b0),
.D(27'b0),
.P(P_48),
.INMODE(5'b00000),
.ALUMODE(4'b0000),
.OPMODE(9'b00000101),
.CARRYINSEL(3'b000),
.ACIN(30'b0),
.BCIN(18'b0),
.PCIN(48'b0),
.CARRYIN(1'b0)
);
assign Y = P_48;
endmodule