xilinx: Support multiplier mapping for all families.
authorMarcin Kościelnicki <koriakin@0x04.net>
Tue, 8 Oct 2019 17:00:30 +0000 (17:00 +0000)
committerMarcin Kościelnicki <koriakin@0x04.net>
Tue, 22 Oct 2019 16:06:57 +0000 (18:06 +0200)
This supports several older families that are not yet supported for
actual logic synthesis — the intention is to add them soon.

techlibs/xilinx/Makefile.inc
techlibs/xilinx/dsp_map.v [deleted file]
techlibs/xilinx/synth_xilinx.cc
techlibs/xilinx/xc3s_mult_map.v [new file with mode: 0644]
techlibs/xilinx/xc3sda_dsp_map.v [new file with mode: 0644]
techlibs/xilinx/xc4v_dsp_map.v [new file with mode: 0644]
techlibs/xilinx/xc5v_dsp_map.v [new file with mode: 0644]
techlibs/xilinx/xc6s_dsp_map.v [new file with mode: 0644]
techlibs/xilinx/xc7_dsp_map.v [new file with mode: 0644]
techlibs/xilinx/xcu_dsp_map.v [new file with mode: 0644]

index 1e59f0a1be15374272b97ec909956b6b42b0f085..3354605efc7a5d4e38d0f0e32aca7e3c0a1f82b2 100644 (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))
diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v
deleted file mode 100644 (file)
index a4256eb..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-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;
-       DSP48E1 #(
-               // 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"),
-               .USE_DPORT("FALSE")
-       ) _TECHMAP_REPLACE_ (
-               //Data path
-               .A({{5{A[24]}}, A}),
-               .B(B),
-               .C(48'b0),
-               .D(25'b0),
-               .P(P_48),
-
-               .INMODE(5'b00000),
-               .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
index 6f8254b59d7f23a5ab8fa175b14cdedaeb171c70..6566da832d330c2be9fac8b1647bde8c16ca85fc 100644 (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");
diff --git a/techlibs/xilinx/xc3s_mult_map.v b/techlibs/xilinx/xc3s_mult_map.v
new file mode 100644 (file)
index 0000000..67cd4ac
--- /dev/null
@@ -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
+
diff --git a/techlibs/xilinx/xc3sda_dsp_map.v b/techlibs/xilinx/xc3sda_dsp_map.v
new file mode 100644 (file)
index 0000000..87348a1
--- /dev/null
@@ -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
+
diff --git a/techlibs/xilinx/xc4v_dsp_map.v b/techlibs/xilinx/xc4v_dsp_map.v
new file mode 100644 (file)
index 0000000..69c42f3
--- /dev/null
@@ -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
diff --git a/techlibs/xilinx/xc5v_dsp_map.v b/techlibs/xilinx/xc5v_dsp_map.v
new file mode 100644 (file)
index 0000000..fc7ba46
--- /dev/null
@@ -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
+
diff --git a/techlibs/xilinx/xc6s_dsp_map.v b/techlibs/xilinx/xc6s_dsp_map.v
new file mode 100644 (file)
index 0000000..e870572
--- /dev/null
@@ -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
+
+
diff --git a/techlibs/xilinx/xc7_dsp_map.v b/techlibs/xilinx/xc7_dsp_map.v
new file mode 100644 (file)
index 0000000..a4256eb
--- /dev/null
@@ -0,0 +1,49 @@
+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;
+       DSP48E1 #(
+               // 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"),
+               .USE_DPORT("FALSE")
+       ) _TECHMAP_REPLACE_ (
+               //Data path
+               .A({{5{A[24]}}, A}),
+               .B(B),
+               .C(48'b0),
+               .D(25'b0),
+               .P(P_48),
+
+               .INMODE(5'b00000),
+               .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
diff --git a/techlibs/xilinx/xcu_dsp_map.v b/techlibs/xilinx/xcu_dsp_map.v
new file mode 100644 (file)
index 0000000..fa95a57
--- /dev/null
@@ -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
+