aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r--techlibs/xilinx/Makefile.inc1
-rw-r--r--techlibs/xilinx/cells_sim.v147
-rw-r--r--techlibs/xilinx/cells_xtra.v82
-rw-r--r--techlibs/xilinx/dsp_map.v40
-rw-r--r--techlibs/xilinx/synth_xilinx.cc24
5 files changed, 209 insertions, 85 deletions
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 2c6e7432e..b0251d621 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -38,6 +38,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/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/abc_xc7.box))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut))
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 05e46b4e7..33b2a8f62 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -378,3 +378,150 @@ module SRLC32E (
always @(posedge CLK) if (CE) r <= { r[30:0], D };
endgenerate
endmodule
+
+module DSP48E1 (
+ output [29:0] ACOUT,
+ output [17:0] BCOUT,
+ output CARRYCASCOUT,
+ output [3:0] CARRYOUT,
+ output MULTSIGNOUT,
+ output OVERFLOW,
+ output reg signed [47:0] P,
+ output PATTERNBDETECT,
+ output PATTERNDETECT,
+ output [47:0] PCOUT,
+ output UNDERFLOW,
+ input signed [29:0] A,
+ input [29:0] ACIN,
+ input [3:0] ALUMODE,
+ input signed [17:0] B,
+ input [17:0] BCIN,
+ input [47:0] C,
+ input CARRYCASCIN,
+ input CARRYIN,
+ input [2:0] CARRYINSEL,
+ input CEA1,
+ input CEA2,
+ input CEAD,
+ input CEALUMODE,
+ input CEB1,
+ input CEB2,
+ input CEC,
+ input CECARRYIN,
+ input CECTRL,
+ input CED,
+ input CEINMODE,
+ input CEM,
+ input CEP,
+ input CLK,
+ input [24:0] D,
+ input [4:0] INMODE,
+ input MULTSIGNIN,
+ input [6:0] OPMODE,
+ input [47:0] PCIN,
+ input RSTA,
+ input RSTALLCARRYIN,
+ input RSTALUMODE,
+ input RSTB,
+ input RSTC,
+ input RSTCTRL,
+ input RSTD,
+ input RSTINMODE,
+ input RSTM,
+ input RSTP
+);
+ parameter integer ACASCREG = 1;
+ parameter integer ADREG = 1;
+ parameter integer ALUMODEREG = 1;
+ parameter integer AREG = 1;
+ parameter AUTORESET_PATDET = "NO_RESET";
+ parameter A_INPUT = "DIRECT";
+ parameter integer BCASCREG = 1;
+ parameter integer BREG = 1;
+ parameter B_INPUT = "DIRECT";
+ parameter integer CARRYINREG = 1;
+ parameter integer CARRYINSELREG = 1;
+ parameter integer CREG = 1;
+ parameter integer DREG = 1;
+ parameter integer INMODEREG = 1;
+ parameter integer MREG = 1;
+ parameter integer OPMODEREG = 1;
+ parameter integer PREG = 1;
+ parameter SEL_MASK = "MASK";
+ parameter SEL_PATTERN = "PATTERN";
+ parameter USE_DPORT = "FALSE";
+ parameter USE_MULT = "MULTIPLY";
+ parameter USE_PATTERN_DETECT = "NO_PATDET";
+ parameter USE_SIMD = "ONE48";
+ parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
+ parameter [47:0] PATTERN = 48'h000000000000;
+ parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
+ parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+ parameter [4:0] IS_INMODE_INVERTED = 5'b0;
+ parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
+
+ initial begin
+`ifdef __ICARUS__
+ if (ACASCREG != 0) $fatal(1, "Unsupported ACASCREG value");
+ if (ADREG != 0) $fatal(1, "Unsupported ADREG value");
+ if (ALUMODEREG != 0) $fatal(1, "Unsupported ALUMODEREG value");
+ if (AREG == 2) $fatal(1, "Unsupported AREG value");
+ if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value");
+ if (A_INPUT != "DIRECT") $fatal(1, "Unsupported A_INPUT value");
+ if (BCASCREG != 0) $fatal(1, "Unsupported BCASCREG value");
+ if (BREG == 2) $fatal(1, "Unsupported BREG value");
+ if (B_INPUT != "DIRECT") $fatal(1, "Unsupported B_INPUT value");
+ if (CARRYINREG != 0) $fatal(1, "Unsupported CARRYINREG value");
+ if (CARRYINSELREG != 0) $fatal(1, "Unsupported CARRYINSELREG value");
+ if (CREG != 0) $fatal(1, "Unsupported CREG value");
+ if (DREG != 0) $fatal(1, "Unsupported DREG value");
+ if (INMODEREG != 0) $fatal(1, "Unsupported INMODEREG value");
+ if (MREG != 0) $fatal(1, "Unsupported MREG value");
+ if (OPMODEREG != 0) $fatal(1, "Unsupported OPMODEREG value");
+ //if (PREG != 0) $fatal(1, "Unsupported PREG value");
+ if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value");
+ if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value");
+ if (USE_DPORT != "FALSE") $fatal(1, "Unsupported USE_DPORT value");
+ if (USE_MULT != "MULTIPLY") $fatal(1, "Unsupported USE_MULT value");
+ if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value");
+ if (USE_SIMD != "ONE48") $fatal(1, "Unsupported USE_SIMD value");
+ if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
+ if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value");
+ if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value");
+ if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value");
+ if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value");
+`endif
+ end
+
+ reg signed [29:0] Ar;
+ reg signed [17:0] Br;
+ reg signed [47:0] Pr;
+ generate
+ if (AREG == 1) begin always @(posedge CLK) if (CEA2) Ar <= A; end
+ else always @* Ar <= A;
+ if (BREG == 1) begin always @(posedge CLK) if (CEB2) Br <= B; end
+ else always @* Br <= B;
+ endgenerate
+
+ always @* begin
+ Pr <= {48{1'bx}};
+`ifdef __ICARUS__
+ if (INMODE != 4'b0000) $fatal(1, "Unsupported INMODE value");
+ if (ALUMODE != 4'b0000) $fatal(1, "Unsupported ALUMODE value");
+ if (OPMODE != 7'b000101) $fatal(1, "Unsupported OPMODE value");
+ if (CARRYINSEL != 3'b000) $fatal(1, "Unsupported CARRYINSEL value");
+ if (ACIN != 30'b0) $fatal(1, "Unsupported ACIN value");
+ if (BCIN != 18'b0) $fatal(1, "Unsupported BCIN value");
+ if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value");
+ if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value");
+`endif
+ Pr[42:0] <= $signed(Ar[24:0]) * Br;
+ end
+
+ generate
+ if (PREG == 1) begin always @(posedge CLK) if (CEP) P <= Pr; end
+ else always @* P <= Pr;
+ endgenerate
+
+endmodule
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 15fa1b63a..d79349225 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -111,88 +111,6 @@ module DNA_PORT (...);
input CLK, DIN, READ, SHIFT;
endmodule
-module DSP48E1 (...);
- parameter integer ACASCREG = 1;
- parameter integer ADREG = 1;
- parameter integer ALUMODEREG = 1;
- parameter integer AREG = 1;
- parameter AUTORESET_PATDET = "NO_RESET";
- parameter A_INPUT = "DIRECT";
- parameter integer BCASCREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer CARRYINREG = 1;
- parameter integer CARRYINSELREG = 1;
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer INMODEREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter SEL_MASK = "MASK";
- parameter SEL_PATTERN = "PATTERN";
- parameter USE_DPORT = "FALSE";
- parameter USE_MULT = "MULTIPLY";
- parameter USE_PATTERN_DETECT = "NO_PATDET";
- parameter USE_SIMD = "ONE48";
- parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
- parameter [47:0] PATTERN = 48'h000000000000;
- parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
- parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- parameter [4:0] IS_INMODE_INVERTED = 5'b0;
- parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
- output [29:0] ACOUT;
- output [17:0] BCOUT;
- output CARRYCASCOUT;
- output [3:0] CARRYOUT;
- output MULTSIGNOUT;
- output OVERFLOW;
- output [47:0] P;
- output PATTERNBDETECT;
- output PATTERNDETECT;
- output [47:0] PCOUT;
- output UNDERFLOW;
- input [29:0] A;
- input [29:0] ACIN;
- input [3:0] ALUMODE;
- input [17:0] B;
- input [17:0] BCIN;
- input [47:0] C;
- input CARRYCASCIN;
- input CARRYIN;
- input [2:0] CARRYINSEL;
- input CEA1;
- input CEA2;
- input CEAD;
- input CEALUMODE;
- input CEB1;
- input CEB2;
- input CEC;
- input CECARRYIN;
- input CECTRL;
- input CED;
- input CEINMODE;
- input CEM;
- input CEP;
- input CLK;
- input [24:0] D;
- input [4:0] INMODE;
- input MULTSIGNIN;
- input [6:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTALLCARRYIN;
- input RSTALUMODE;
- input RSTB;
- input RSTC;
- input RSTCTRL;
- input RSTD;
- input RSTINMODE;
- input RSTM;
- input RSTP;
-endmodule
-
module EFUSE_USR (...);
parameter [31:0] SIM_EFUSE_VALUE = 32'h00000000;
output [31:0] EFUSEUSR;
diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v
new file mode 100644
index 000000000..32f570935
--- /dev/null
+++ b/techlibs/xilinx/dsp_map.v
@@ -0,0 +1,40 @@
+module \$__MUL25X18 (input signed [24:0] A, input signed [17:0] B, output signed [42:0] Y);
+ 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)
+ ) _TECHMAP_REPLACE_ (
+ //Data path
+ .A({{5{A[24]}}, A}),
+ .B(B),
+ .C(48'b0),
+ .D(24'b0),
+ .P(P_48),
+
+ .INMODE(4'b0000),
+ .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 b672a0d4f..e5a27015a 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -78,6 +78,9 @@ struct SynthXilinxPass : public ScriptPass
log(" -nowidelut\n");
log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
log("\n");
+ log(" -nodsp\n");
+ log(" do not use DSP48E1s to implement multipliers and associated logic\n");
+ log("\n");
log(" -widemux <int>\n");
log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
log(" above this number of inputs (minimum value 2, recommended value >= 5).\n");
@@ -104,7 +107,7 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
- bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9;
+ bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, nodsp, abc9;
int widemux;
void clear_flags() YS_OVERRIDE
@@ -122,6 +125,7 @@ struct SynthXilinxPass : public ScriptPass
nosrl = false;
nocarry = false;
nowidelut = false;
+ nodsp = false;
abc9 = false;
widemux = 0;
}
@@ -202,6 +206,10 @@ struct SynthXilinxPass : public ScriptPass
abc9 = true;
continue;
}
+ if (args[argidx] == "-nodsp") {
+ nodsp = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -249,8 +257,8 @@ struct SynthXilinxPass : public ScriptPass
if (check_label("coarse")) {
run("proc");
- if (help_mode || flatten)
- run("flatten", "(if -flatten)");
+ if (flatten || help_mode)
+ run("flatten", "(with '-flatten')");
run("opt_expr");
run("opt_clean");
run("check");
@@ -275,6 +283,12 @@ struct SynthXilinxPass : public ScriptPass
}
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
+
+ if (!nodsp || help_mode) {
+ // NB: Xilinx multipliers are signed only
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
+ }
+
run("alumacc");
run("share");
run("opt");
@@ -317,6 +331,10 @@ struct SynthXilinxPass : public ScriptPass
run("memory_map");
run("dffsr2dff");
run("dff2dffe");
+ if (help_mode || !nodsp) {
+ run("techmap -map +/xilinx/dsp_map.v", "(skip if '-nodsp')");
+ run("xilinx_dsp", " (skip if '-nodsp')");
+ }
if (help_mode) {
run("simplemap t:$mux", " ('-widemux' only)");
run("muxcover <internal options>, ('-widemux' only)");