From 7b350cacd410b16fdac5a6933aea1bb009b83621 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= <koriakin@0x04.net>
Date: Tue, 8 Oct 2019 17:00:30 +0000
Subject: xilinx: Support multiplier mapping for all families.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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     |  8 +++++-
 techlibs/xilinx/dsp_map.v        | 49 -------------------------------------
 techlibs/xilinx/synth_xilinx.cc  | 53 ++++++++++++++++++++++++++++++++++------
 techlibs/xilinx/xc3s_mult_map.v  | 14 +++++++++++
 techlibs/xilinx/xc3sda_dsp_map.v | 34 ++++++++++++++++++++++++++
 techlibs/xilinx/xc4v_dsp_map.v   | 38 ++++++++++++++++++++++++++++
 techlibs/xilinx/xc5v_dsp_map.v   | 45 ++++++++++++++++++++++++++++++++++
 techlibs/xilinx/xc6s_dsp_map.v   | 35 ++++++++++++++++++++++++++
 techlibs/xilinx/xc7_dsp_map.v    | 49 +++++++++++++++++++++++++++++++++++++
 techlibs/xilinx/xcu_dsp_map.v    | 51 ++++++++++++++++++++++++++++++++++++++
 10 files changed, 318 insertions(+), 58 deletions(-)
 delete mode 100644 techlibs/xilinx/dsp_map.v
 create mode 100644 techlibs/xilinx/xc3s_mult_map.v
 create mode 100644 techlibs/xilinx/xc3sda_dsp_map.v
 create mode 100644 techlibs/xilinx/xc4v_dsp_map.v
 create mode 100644 techlibs/xilinx/xc5v_dsp_map.v
 create mode 100644 techlibs/xilinx/xc6s_dsp_map.v
 create mode 100644 techlibs/xilinx/xc7_dsp_map.v
 create mode 100644 techlibs/xilinx/xcu_dsp_map.v

(limited to 'techlibs/xilinx')

diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 1e59f0a1b..3354605ef 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -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
index a4256eb92..000000000
--- a/techlibs/xilinx/dsp_map.v
+++ /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
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 6f8254b59..6566da832 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -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
index 000000000..67cd4ac60
--- /dev/null
+++ b/techlibs/xilinx/xc3s_mult_map.v
@@ -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
index 000000000..87348a173
--- /dev/null
+++ b/techlibs/xilinx/xc3sda_dsp_map.v
@@ -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
index 000000000..69c42f343
--- /dev/null
+++ b/techlibs/xilinx/xc4v_dsp_map.v
@@ -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
index 000000000..fc7ba46cc
--- /dev/null
+++ b/techlibs/xilinx/xc5v_dsp_map.v
@@ -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
index 000000000..e8705723b
--- /dev/null
+++ b/techlibs/xilinx/xc6s_dsp_map.v
@@ -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
index 000000000..a4256eb92
--- /dev/null
+++ b/techlibs/xilinx/xc7_dsp_map.v
@@ -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
index 000000000..fa95a5776
--- /dev/null
+++ b/techlibs/xilinx/xcu_dsp_map.v
@@ -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
+
-- 
cgit v1.2.3