diff options
-rw-r--r-- | kernel/rtlil.cc | 5 | ||||
-rw-r--r-- | kernel/rtlil.h | 2 | ||||
-rw-r--r-- | passes/pmgen/.gitignore | 3 | ||||
-rw-r--r-- | passes/pmgen/Makefile.inc | 9 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp.cc | 136 | ||||
-rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 94 | ||||
-rw-r--r-- | techlibs/common/mul2dsp.v | 4 | ||||
-rw-r--r-- | techlibs/ecp5/dsp_map.v | 4 | ||||
-rw-r--r-- | techlibs/xilinx/Makefile.inc | 1 | ||||
-rw-r--r-- | techlibs/xilinx/cells_map.v | 41 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 26 | ||||
-rw-r--r-- | techlibs/xilinx/dsp_map.v | 40 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 4 |
13 files changed, 312 insertions, 57 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a09f4a0d1..6f5082138 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3353,7 +3353,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const { unpack(); cover("kernel.rtlil.sigspec.extract_pos"); - return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length); + return std::vector<RTLIL::SigBit>(bits_.begin() + offset, length >= 0 ? bits_.begin() + offset + length : bits_.end() + length + 1); } void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) @@ -3426,7 +3426,7 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) check(); } -void RTLIL::SigSpec::extend_u0(int width, bool is_signed) +RTLIL::SigSpec& RTLIL::SigSpec::extend_u0(int width, bool is_signed) { cover("kernel.rtlil.sigspec.extend_u0"); @@ -3443,6 +3443,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) append(padding); } + return *this; } RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 82cbfaf28..8d88cc97c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -776,7 +776,7 @@ public: void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); - void extend_u0(int width, bool is_signed = false); + RTLIL::SigSpec& extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index 0ad36ea2c..10e245e00 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1,2 +1 @@ -/ice40_dsp_pm.h -/peepopt_pm.h +/%_pm.h diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 7911132db..e33866670 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,14 +1,19 @@ OBJS += passes/pmgen/ice40_dsp.o +OBJS += passes/pmgen/xilinx_dsp.o OBJS += passes/pmgen/peepopt.o # -------------------------------------- +passes/pmgen/%.o: passes/pmgen/%_pm.h passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h +passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h +EXTRA_OBJS += passes/pmgen/xilinx_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h +.SECONDARY: passes/pmgen/xilinx_dsp_pm.h -passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg - $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_dsp $(filter-out $<,$^) +passes/pmgen/%_pm.h: passes/pmgen/pmgen.py passes/pmgen/%.pmg + $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $* $(filter-out $<,$^) # -------------------------------------- diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc new file mode 100644 index 000000000..a09f96a7f --- /dev/null +++ b/passes/pmgen/xilinx_dsp.cc @@ -0,0 +1,136 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/xilinx_dsp_pm.h" + +void pack_xilinx_dsp(xilinx_dsp_pm &pm) +{ + auto &st = pm.st_xilinx_dsp; + +#if 1 + log("\n"); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("dsp: %s\n", log_id(st.dsp, "--")); + log("ffP: %s\n", log_id(st.ffP, "--")); + log("muxP: %s\n", log_id(st.muxP, "--")); + log("P_WIDTH: %d\n", st.P_WIDTH); +#endif + + log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); + + Cell *cell = st.dsp; + log_assert(cell); + + if (st.clock != SigBit()) + { + cell->setPort("\\CLK", st.clock); + + if (st.ffA) { + SigSpec D = st.ffA->getPort("\\D"); + cell->setPort("\\A", D.extend_u0(30)); + cell->setParam("\\AREG", State::S1); + if (st.ffA->type == "$dff") + cell->setPort("\\CEA2", State::S1); + else if (st.ffA->type == "$dffe") + cell->setPort("\\CEA2", st.ffA->getPort("\\EN")); + else log_abort(); + } + if (st.ffB) { + SigSpec D = st.ffB->getPort("\\D"); + cell->setPort("\\B", D.extend_u0(18)); + cell->setParam("\\BREG", State::S1); + if (st.ffB->type == "$dff") + cell->setPort("\\CEB2", State::S1); + else if (st.ffB->type == "$dffe") + cell->setPort("\\CEB2", st.ffB->getPort("\\EN")); + else log_abort(); + } + if (st.ffP) { + SigSpec P = cell->getPort("\\P"); + SigSpec Q = st.ffP->getPort("\\Q"); + Q.append(P.extract(GetSize(Q), -1)); + cell->setPort("\\P", Q); + cell->setParam("\\PREG", State::S1); + if (st.ffP->type == "$dff") + cell->setPort("\\CEP", State::S1); + else if (st.ffP->type == "$dffe") + cell->setPort("\\CEP", st.ffP->getPort("\\EN")); + else log_abort(); + } + + log(" clock: %s (%s)", log_signal(st.clock), "posedge"); + + if (st.ffA) + log(" ffA:%s", log_id(st.ffA)); + + if (st.ffB) + log(" ffB:%s", log_id(st.ffB)); + + if (st.ffP) + log(" ffY:%s", log_id(st.ffP)); + + log("\n"); + } + + pm.autoremove(st.ffA); + pm.autoremove(st.ffB); + pm.autoremove(st.ffP); + pm.autoremove(st.muxP); + pm.blacklist(cell); +} + +struct Ice40DspPass : public Pass { + Ice40DspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" xilinx_dsp [options] [selection]\n"); + log("\n"); + log("Pack registers into Xilinx DSPs\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing XILINX_DSP pass (pack DSPs).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp); + } +} Ice40DspPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg new file mode 100644 index 000000000..ceed64b30 --- /dev/null +++ b/passes/pmgen/xilinx_dsp.pmg @@ -0,0 +1,94 @@ +pattern xilinx_dsp + +state <SigBit> clock +state <int> P_WIDTH + +match dsp + select dsp->type.in(\DSP48E1) +endmatch + +match ffA + select ffA->type.in($dff, $dffe) + // select nusers(port(ffA, \Q)) == 2 + index <SigSpec> port(ffA, \Q).extend_u0(30) === port(dsp, \A) + // DSP48E1 does not support clock inversion + index <Const> param(ffA, \CLK_POLARITY).as_bool() === true + optional +endmatch + +code clock + if (ffA) + clock = port(ffA, \CLK).as_bit(); +endcode + +match ffB + select ffB->type.in($dff, $dffe) + // select nusers(port(ffB, \Q)) == 2 + index <SigSpec> port(ffB, \Q).extend_u0(18) === port(dsp, \B) + index <Const> param(ffB, \CLK_POLARITY).as_bool() === true + optional +endmatch + +code clock + if (ffB) { + SigBit c = port(ffB, \CLK).as_bit(); + + if (clock != SigBit() && c != clock) + reject; + + clock = c; + } +endcode + +code P_WIDTH + SigSpec P = port(dsp, \P); + int i; + for (i = GetSize(P); i > 0; i--) + if (nusers(P[i-1]) > 1) + break; + P_WIDTH = i; +endcode + +match ffP + select ffP->type.in($dff, $dffe) + select nusers(port(ffP, \D)) == 2 + filter param(ffP, \WIDTH).as_int() == P_WIDTH + filter port(ffP, \D) == port(dsp, \P).extract(0, P_WIDTH) + index <Const> param(ffP, \CLK_POLARITY) === State::S1 + optional +endmatch + +// $mux cell left behind by dff2dffe +// would prefer not to run 'opt_expr -mux_undef' +// since that would lose information helpful for +// efficient wide-mux inference +match muxP + if !ffP + select muxP->type.in($mux) + select port(muxP, \A).is_fully_undef() + filter param(muxP, \WIDTH).as_int() == P_WIDTH + filter port(muxP, \B) == port(dsp, \P).extract(0, P_WIDTH) + select nusers(port(muxP, \B)) == 2 + optional +endmatch + +match ffY + if muxP + select ffY->type.in($dff, $dffe) + select nusers(port(ffY, \D)) == 2 + index <SigSpec> port(ffY, \D) === port(muxP, \Y) +endmatch + +code ffP clock + if (ffY) + ffP = ffY; + + if (ffP) { + SigBit c = port(ffP, \CLK).as_bit(); + + if (clock != SigBit() && c != clock) + reject; + + clock = c; + } +endcode diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 262e29986..6f2281c0a 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -33,7 +33,7 @@ module \$mul (A, B, Y); output [Y_WIDTH-1:0] Y;
generate
- if (B_WIDTH < A_WIDTH)
+ if (A_WIDTH >= B_WIDTH)
\$__mul_gen #(
.A_SIGNED(A_SIGNED),
.B_SIGNED(B_SIGNED),
@@ -213,7 +213,7 @@ module \$__mul_gen (A, B, Y); `DSP_NAME _TECHMAP_REPLACE_ (
.A({ {{`DSP_A_MAXWIDTH-A_WIDTH}{Asign}}, A }),
.B({ {{`DSP_B_MAXWIDTH-B_WIDTH}{Bsign}}, B }),
- .OUT({dummy, out})
+ .Y({dummy, out})
);
if (Y_WIDTH < A_WIDTH+B_WIDTH)
assign Y = out[Y_WIDTH-1:0];
diff --git a/techlibs/ecp5/dsp_map.v b/techlibs/ecp5/dsp_map.v index 5f7755afb..24e28869e 100644 --- a/techlibs/ecp5/dsp_map.v +++ b/techlibs/ecp5/dsp_map.v @@ -1,10 +1,10 @@ -module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] OUT); +module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); MULT18X18D _TECHMAP_REPLACE_ ( .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]), .B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]), .C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0), .SIGNEDA(1'b0), .SIGNEDB(1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0), - .P0(OUT[0]), .P1(OUT[1]), .P2(OUT[2]), .P3(OUT[3]), .P4(OUT[4]), .P5(OUT[5]), .P6(OUT[6]), .P7(OUT[7]), .P8(OUT[8]), .P9(OUT[9]), .P10(OUT[10]), .P11(OUT[11]), .P12(OUT[12]), .P13(OUT[13]), .P14(OUT[14]), .P15(OUT[15]), .P16(OUT[16]), .P17(OUT[17]), .P18(OUT[18]), .P19(OUT[19]), .P20(OUT[20]), .P21(OUT[21]), .P22(OUT[22]), .P23(OUT[23]), .P24(OUT[24]), .P25(OUT[25]), .P26(OUT[26]), .P27(OUT[27]), .P28(OUT[28]), .P29(OUT[29]), .P30(OUT[30]), .P31(OUT[31]), .P32(OUT[32]), .P33(OUT[33]), .P34(OUT[34]), .P35(OUT[35]) + .P0(Y[0]), .P1(Y[1]), .P2(Y[2]), .P3(Y[3]), .P4(Y[4]), .P5(Y[5]), .P6(Y[6]), .P7(Y[7]), .P8(Y[8]), .P9(Y[9]), .P10(Y[10]), .P11(Y[11]), .P12(Y[12]), .P13(Y[13]), .P14(Y[14]), .P15(Y[15]), .P16(Y[16]), .P17(Y[17]), .P18(Y[18]), .P19(Y[19]), .P20(Y[20]), .P21(Y[21]), .P22(Y[22]), .P23(Y[23]), .P24(Y[24]), .P25(Y[25]), .P26(Y[26]), .P27(Y[27]), .P28(Y[28]), .P29(Y[29]), .P30(Y[30]), .P31(Y[31]), .P32(Y[32]), .P33(Y[33]), .P34(Y[34]), .P35(Y[35]) ); endmodule 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_map.v b/techlibs/xilinx/cells_map.v index 8302e0b3a..2eb9fa2c1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -365,44 +365,3 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); endmodule `endif - -module \$__MUL25X18 (input [23:0] A, input [16:0] B, output [40:0] OUT); - 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({6'b0, A}), - .B({1'b0, 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 OUT = P_48; -endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index ea5a3b788..1262fc8c1 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -466,11 +466,11 @@ module DSP48E1 ( 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 != 0) $fatal(1, "Unsupported AREG 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 != 0) $fatal(1, "Unsupported BREG 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"); @@ -479,7 +479,7 @@ module DSP48E1 ( 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 (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"); @@ -494,8 +494,18 @@ module DSP48E1 ( `endif end + reg [29:0] Ar; + reg [17:0] Br; + reg [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 - P <= {48{1'bx}}; + Pr <= {48{1'bx}}; `ifdef __ICARUS__ if (INMODE != 4'b0000) $fatal(1, "Unsupported INMODE value"); if (ALUMODE != 4'b0000) $fatal(1, "Unsupported ALUMODE value"); @@ -506,6 +516,12 @@ module DSP48E1 ( if (PCIN != 48'b0) $fatal(1, "Unsupported PCIN value"); if (CARRYIN != 1'b0) $fatal(1, "Unsupported CARRYIN value"); `endif - P[42:0] <= $signed(A[24:0]) * $signed(B); + Pr[42:0] <= $signed(Ar[24:0]) * $signed(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/dsp_map.v b/techlibs/xilinx/dsp_map.v new file mode 100644 index 000000000..2063c45e2 --- /dev/null +++ b/techlibs/xilinx/dsp_map.v @@ -0,0 +1,40 @@ +module \$__MUL25X18 (input [23:0] A, input [16:0] B, output [40: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({6'b0, A}), + .B({1'b0, 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 5bfbd1583..815bf0848 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -333,6 +333,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)"); |