diff options
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r-- | techlibs/xilinx/Makefile.inc | 1 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 147 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.v | 82 | ||||
-rw-r--r-- | techlibs/xilinx/dsp_map.v | 40 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 24 |
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)"); |