/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *                2019  Eddie Hung    <eddie@fpgeh.com>
 *
 *  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.
 *
 */

// The following techmapping rules are intended to be run (with -max_iter 1)
//   before invoking the `abc9` pass in order to transform the design into
//   a format that it understands.
//
// For example, (complex) flip-flops are expected to be described as an
//   combinatorial box (containing all control logic such as clock enable
//   or synchronous resets) followed by a basic D-Q flop.
// Yosys will automatically analyse the simulation model (described in
//   cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in
//   order to extract the combinatorial control logic left behind.
//   Specifically, a simulation model similar to the one below:
//
//                ++===================================++
//                ||                        Sim model  ||
//                ||      /\/\/\/\                     ||
//            D -->>-----<        >     +------+       ||
//            R -->>-----<  Comb. >     |$_DFF_|       ||
//           CE -->>-----<  logic >-----| [NP]_|---+---->>-- Q
//                ||  +--<        >     +------+   |   ||
//                ||  |   \/\/\/\/                 |   ||
//                ||  |                            |   ||
//                ||  +----------------------------+   ||
//                ||                                   ||
//                ++===================================++
//
//   is transformed into:
//
//                ++==================++
//                ||         Comb box ||
//                ||                  ||
//                ||      /\/\/\/\    ||
//           D  -->>-----<        >   ||            +------+
//           R  -->>-----<  Comb. >   ||            |$__ABC|
//          CE  -->>-----<  logic >--->>-- $nextQ --| _FF_ |--+-->> Q
// $abc9_currQ +-->>-----<        >   ||            +------+  |
//             |  ||      \/\/\/\/    ||                      |
//             |  ||                  ||                      |
//             |  ++==================++                      |
//             |                                              |
//             +----------------------------------------------+
//
// The purpose of the following FD* rules are to wrap the flop with:
// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
//     the connectivity of its basic D-Q flop
// (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock
//     domain (used when partitioning the module so that `abc9' only
//     performs sequential synthesis (with reachability analysis) correctly on
//     one domain at a time) and used to infert the delay target
// (c) a special _TECHMAP_REPLACE_.$abc9_control wire that captures the control
//     domain (which, combined with this cell type, encodes to `abc9' which
//     flops may be merged together)
// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial
//     state
// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback
//     into the (combinatorial) FD* cell to facilitate clock-enable behaviour
//
// In order to perform sequential synthesis, `abc9' also requires that
// the initial value of all flops be zero.

module FDRE (output Q, input C, CE, D, R);
  parameter [0:0] INIT = 1'b0;
  parameter [0:0] IS_C_INVERTED = 1'b0;
  parameter [0:0] IS_D_INVERTED = 1'b0;
  parameter [0:0] IS_R_INVERTED = 1'b0;
  wire QQ, $nextQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDSE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_S_INVERTED(IS_R_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R)
    );
  end
  else begin
    assign Q = QQ;
    FDRE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_R_INVERTED(IS_R_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
    );
  end
  endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module FDRE_1 (output Q, input C, CE, D, R);
  parameter [0:0] INIT = 1'b0;
  wire QQ, $nextQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDSE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .S(R)
    );
  end
  else begin
    assign Q = QQ;
    FDRE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
    );
  end
  endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule

module FDCE (output Q, input C, CE, D, CLR);
  parameter [0:0] INIT = 1'b0;
  parameter [0:0] IS_C_INVERTED = 1'b0;
  parameter [0:0] IS_D_INVERTED = 1'b0;
  parameter [0:0] IS_CLR_INVERTED = 1'b0;
  wire QQ, $nextQ, $abc9_currQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDPE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_PRE_INVERTED(IS_CLR_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR)
                                            // ^^^ Note that async
                                            //     control is not directly
                                            //     supported by abc9 but its
                                            //     behaviour is captured by
                                            //     $__ABC9_ASYNC below
    );
  end
  else begin
    assign Q = QQ;
    FDCE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_CLR_INVERTED(IS_CLR_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
                                           // ^^^ Note that async
                                           //     control is not directly
                                           //     supported by abc9 but its
                                           //     behaviour is captured by
                                           //     $__ABC9_ASYNC below
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
  // Since this is an async flop, async behaviour is also dealt with
  //   using the $_ABC9_ASYNC box by abc9_map.v
  \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDCE_1 (output Q, input C, CE, D, CLR);
  parameter [0:0] INIT = 1'b0;
  wire QQ, $nextQ, $abc9_currQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDPE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .PRE(CLR)
                                            // ^^^ Note that async
                                            //     control is not directly
                                            //     supported by abc9 but its
                                            //     behaviour is captured by
                                            //     $__ABC9_ASYNC below
    );
  end
  else begin
    assign Q = QQ;
    FDCE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
                                           // ^^^ Note that async
                                           //     control is not directly
                                           //     supported by abc9 but its
                                           //     behaviour is captured by
                                           //     $__ABC9_ASYNC below
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
  \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule

module FDPE (output Q, input C, CE, D, PRE);
  parameter [0:0] INIT = 1'b1;
  parameter [0:0] IS_C_INVERTED = 1'b0;
  parameter [0:0] IS_D_INVERTED = 1'b0;
  parameter [0:0] IS_PRE_INVERTED = 1'b0;
  wire QQ, $nextQ, $abc9_currQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDCE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_CLR_INVERTED(IS_PRE_INVERTED),
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE)
                                            // ^^^ Note that async
                                            //     control is not directly
                                            //     supported by abc9 but its
                                            //     behaviour is captured by
                                            //     $__ABC9_ASYNC below
    );
  end
  else begin
    assign Q = QQ;
    FDPE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_PRE_INVERTED(IS_PRE_INVERTED),
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
                                           // ^^^ Note that async
                                           //     control is not directly
                                           //     supported by abc9 but its
                                           //     behaviour is captured by
                                           //     $__ABC9_ASYNC below
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
  \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule
module FDPE_1 (output Q, input C, CE, D, PRE);
  parameter [0:0] INIT = 1'b1;
  wire QQ, $nextQ, $abc9_currQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDCE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .CLR(PRE)
                                            // ^^^ Note that async
                                            //     control is not directly
                                            //     supported by abc9 but its
                                            //     behaviour is captured by
                                            //     $__ABC9_ASYNC below
    );
  end
  else begin
    assign Q = QQ;
    FDPE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
                                           // ^^^ Note that async
                                           //     control is not directly
                                           //     supported by abc9 but its
                                           //     behaviour is captured by
                                           //     $__ABC9_ASYNC below
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
  \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
endmodule

module FDSE (output Q, input C, CE, D, S);
  parameter [0:0] INIT = 1'b1;
  parameter [0:0] IS_C_INVERTED = 1'b0;
  parameter [0:0] IS_D_INVERTED = 1'b0;
  parameter [0:0] IS_S_INVERTED = 1'b0;
  wire QQ, $nextQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDRE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_R_INVERTED(IS_S_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S)
    );
  end
  else begin
    assign Q = QQ;
    FDSE #(
      .INIT(1'b0),
      .IS_C_INVERTED(IS_C_INVERTED),
      .IS_D_INVERTED(IS_D_INVERTED),
      .IS_S_INVERTED(IS_S_INVERTED)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule
module FDSE_1 (output Q, input C, CE, D, S);
  parameter [0:0] INIT = 1'b1;
  wire QQ, $nextQ;
  generate if (INIT == 1'b1) begin
    assign Q = ~QQ;
    FDRE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(~D), .Q($nextQ), .C(C), .CE(CE), .R(S)
    );
  end
  else begin
    assign Q = QQ;
    FDSE_1 #(
      .INIT(1'b0)
    ) _TECHMAP_REPLACE_ (
      .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
    );
  end endgenerate
  \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(QQ));

  // Special signals
  wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
  wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */};
  wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
  wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
endmodule

module RAM32X1D (
  output DPO, SPO,
  (* techmap_autopurge *) input  D,
  (* techmap_autopurge *) input  WCLK,
  (* techmap_autopurge *) input  WE,
  (* techmap_autopurge *) input  A0, A1, A2, A3, A4,
  (* techmap_autopurge *) input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
);
  parameter INIT = 32'h0;
  parameter IS_WCLK_INVERTED = 1'b0;
  wire \$DPO , \$SPO ;
  RAM32X1D #(
    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
  ) _TECHMAP_REPLACE_ (
    .DPO(\$DPO ), .SPO(\$SPO ),
    .D(D), .WCLK(WCLK), .WE(WE),
    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
    .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
  );
  \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
  \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
endmodule

module RAM64X1D (
  output DPO, SPO,
  (* techmap_autopurge *) input  D,
  (* techmap_autopurge *) input  WCLK,
  (* techmap_autopurge *) input  WE,
  (* techmap_autopurge *) input  A0, A1, A2, A3, A4, A5,
  (* techmap_autopurge *) input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
);
  parameter INIT = 64'h0;
  parameter IS_WCLK_INVERTED = 1'b0;
  wire \$DPO , \$SPO ;
  RAM64X1D #(
    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
  ) _TECHMAP_REPLACE_ (
    .DPO(\$DPO ), .SPO(\$SPO ),
    .D(D), .WCLK(WCLK), .WE(WE),
    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
    .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
  );
  \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
  \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
endmodule

module RAM128X1D (
  output       DPO, SPO,
  (* techmap_autopurge *) input        D,
  (* techmap_autopurge *) input        WCLK,
  (* techmap_autopurge *) input        WE,
  (* techmap_autopurge *) input  [6:0] A, DPRA
);
  parameter INIT = 128'h0;
  parameter IS_WCLK_INVERTED = 1'b0;
  wire \$DPO , \$SPO ;
  RAM128X1D #(
    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
  ) _TECHMAP_REPLACE_ (
    .DPO(\$DPO ), .SPO(\$SPO ),
    .D(D), .WCLK(WCLK), .WE(WE),
    .A(A),
    .DPRA(DPRA)
  );
  \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
  \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
endmodule

module SRL16E (
  output Q,
  (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
);
  parameter [15:0] INIT = 16'h0000;
  parameter [0:0] IS_CLK_INVERTED = 1'b0;
  wire \$Q ;
  SRL16E #(
    .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
  ) _TECHMAP_REPLACE_ (
    .Q(\$Q ),
    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
  );
  \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
endmodule

module SRLC32E (
  output Q,
  output Q31,
  (* techmap_autopurge *) input [4:0] A,
  (* techmap_autopurge *) input CE, CLK, D
);
  parameter [31:0] INIT = 32'h00000000;
  parameter [0:0] IS_CLK_INVERTED = 1'b0;
  wire \$Q ;
  SRLC32E #(
    .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
  ) _TECHMAP_REPLACE_ (
    .Q(\$Q ), .Q31(Q31),
    .A(A), .CE(CE), .CLK(CLK), .D(D)
  );
  \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
endmodule

module DSP48E1 (
    (* techmap_autopurge *) output [29:0] ACOUT,
    (* techmap_autopurge *) output [17:0] BCOUT,
    (* techmap_autopurge *) output reg CARRYCASCOUT,
    (* techmap_autopurge *) output reg [3:0] CARRYOUT,
    (* techmap_autopurge *) output reg MULTSIGNOUT,
    (* techmap_autopurge *) output OVERFLOW,
    (* techmap_autopurge *) output reg signed [47:0] P,
    (* techmap_autopurge *) output PATTERNBDETECT,
    (* techmap_autopurge *) output PATTERNDETECT,
    (* techmap_autopurge *) output [47:0] PCOUT,
    (* techmap_autopurge *) output UNDERFLOW,
    (* techmap_autopurge *) input signed [29:0] A,
    (* techmap_autopurge *) input [29:0] ACIN,
    (* techmap_autopurge *) input [3:0] ALUMODE,
    (* techmap_autopurge *) input signed [17:0] B,
    (* techmap_autopurge *) input [17:0] BCIN,
    (* techmap_autopurge *) input [47:0] C,
    (* techmap_autopurge *) input CARRYCASCIN,
    (* techmap_autopurge *) input CARRYIN,
    (* techmap_autopurge *) input [2:0] CARRYINSEL,
    (* techmap_autopurge *) input CEA1,
    (* techmap_autopurge *) input CEA2,
    (* techmap_autopurge *) input CEAD,
    (* techmap_autopurge *) input CEALUMODE,
    (* techmap_autopurge *) input CEB1,
    (* techmap_autopurge *) input CEB2,
    (* techmap_autopurge *) input CEC,
    (* techmap_autopurge *) input CECARRYIN,
    (* techmap_autopurge *) input CECTRL,
    (* techmap_autopurge *) input CED,
    (* techmap_autopurge *) input CEINMODE,
    (* techmap_autopurge *) input CEM,
    (* techmap_autopurge *) input CEP,
    (* techmap_autopurge *) input CLK,
    (* techmap_autopurge *) input [24:0] D,
    (* techmap_autopurge *) input [4:0] INMODE,
    (* techmap_autopurge *) input MULTSIGNIN,
    (* techmap_autopurge *) input [6:0] OPMODE,
    (* techmap_autopurge *) input [47:0] PCIN,
    (* techmap_autopurge *) input RSTA,
    (* techmap_autopurge *) input RSTALLCARRYIN,
    (* techmap_autopurge *) input RSTALUMODE,
    (* techmap_autopurge *) input RSTB,
    (* techmap_autopurge *) input RSTC,
    (* techmap_autopurge *) input RSTCTRL,
    (* techmap_autopurge *) input RSTD,
    (* techmap_autopurge *) input RSTINMODE,
    (* techmap_autopurge *) input RSTM,
    (* techmap_autopurge *) 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;

    parameter _TECHMAP_CELLTYPE_ = "";
    localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");

`define DSP48E1_INST(__CELL__) """
__CELL__ #(
            .ACASCREG(ACASCREG),
            .ADREG(ADREG),
            .ALUMODEREG(ALUMODEREG),
            .AREG(AREG),
            .AUTORESET_PATDET(AUTORESET_PATDET),
            .A_INPUT(A_INPUT),
            .BCASCREG(BCASCREG),
            .BREG(BREG),
            .B_INPUT(B_INPUT),
            .CARRYINREG(CARRYINREG),
            .CARRYINSELREG(CARRYINSELREG),
            .CREG(CREG),
            .DREG(DREG),
            .INMODEREG(INMODEREG),
            .MREG(MREG),
            .OPMODEREG(OPMODEREG),
            .PREG(PREG),
            .SEL_MASK(SEL_MASK),
            .SEL_PATTERN(SEL_PATTERN),
            .USE_DPORT(USE_DPORT),
            .USE_MULT(USE_MULT),
            .USE_PATTERN_DETECT(USE_PATTERN_DETECT),
            .USE_SIMD(USE_SIMD),
            .MASK(MASK),
            .PATTERN(PATTERN),
            .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
            .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
            .IS_CLK_INVERTED(IS_CLK_INVERTED),
            .IS_INMODE_INVERTED(IS_INMODE_INVERTED),
            .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
        ) _TECHMAP_REPLACE_ (
            .ACOUT(ACOUT),
            .BCOUT(BCOUT),
            .CARRYCASCOUT(CARRYCASCOUT),
            .CARRYOUT(CARRYOUT),
            .MULTSIGNOUT(MULTSIGNOUT),
            .OVERFLOW(OVERFLOW),
            .P(oP),
            .PATTERNBDETECT(PATTERNBDETECT),
            .PATTERNDETECT(PATTERNDETECT),
            .PCOUT(oPCOUT),
            .UNDERFLOW(UNDERFLOW),
            .A(iA),
            .ACIN(ACIN),
            .ALUMODE(ALUMODE),
            .B(iB),
            .BCIN(BCIN),
            .C(iC),
            .CARRYCASCIN(CARRYCASCIN),
            .CARRYIN(CARRYIN),
            .CARRYINSEL(CARRYINSEL),
            .CEA1(CEA1),
            .CEA2(CEA2),
            .CEAD(CEAD),
            .CEALUMODE(CEALUMODE),
            .CEB1(CEB1),
            .CEB2(CEB2),
            .CEC(CEC),
            .CECARRYIN(CECARRYIN),
            .CECTRL(CECTRL),
            .CED(CED),
            .CEINMODE(CEINMODE),
            .CEM(CEM),
            .CEP(CEP),
            .CLK(CLK),
            .D(iD),
            .INMODE(INMODE),
            .MULTSIGNIN(MULTSIGNIN),
            .OPMODE(OPMODE),
            .PCIN(PCIN),
            .RSTA(RSTA),
            .RSTALLCARRYIN(RSTALLCARRYIN),
            .RSTALUMODE(RSTALUMODE),
            .RSTB(RSTB),
            .RSTC(RSTC),
            .RSTCTRL(RSTCTRL),
            .RSTD(RSTD),
            .RSTINMODE(RSTINMODE),
            .RSTM(RSTM),
            .RSTP(RSTP)
        );
"""

    wire [29:0] iA;
    wire [17:0] iB;
    wire [47:0] iC;
    wire [24:0] iD;

    wire pA, pB, pC, pD, pAD, pM, pP;
    wire [47:0] oP, mP;
    wire [47:0] oPCOUT, mPCOUT;

    generate
    if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin
        // Disconnect the A-input if MREG is enabled, since
        //   combinatorial path is broken
        if (AREG == 0 && MREG == 0 && PREG == 0)
            assign iA = A, pA = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
        if (BREG == 0 && MREG == 0 && PREG == 0)
            assign iB = B, pB = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
        if (CREG == 0 && PREG == 0)
            assign iC = C, pC = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
        if (DREG == 0)
            assign iD = D;
        else if (techmap_guard)
        $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
        assign pD = 1'bx;
        if (ADREG == 1 && techmap_guard)
            $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
        assign pAD = 1'bx;
    if (PREG == 0) begin
        if (MREG == 1)
        \$__ABC9_REG rM (.Q(pM));
        else
        assign pM = 1'bx;
        assign pP = 1'bx;
    end else begin
            assign pM = 1'bx;
            \$__ABC9_REG rP (.Q(pP));
        end

        if (MREG == 0 && PREG == 0)
            assign mP = oP, mPCOUT = oPCOUT;
        else
            assign mP = 1'bx, mPCOUT = 1'bx;
        \$__ABC9_DSP48E1_MULT_P_MUX muxP (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
        );
        \$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
        );

        `DSP48E1_INST(\$__ABC9_DSP48E1_MULT )
    end
    else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
        // Disconnect the A-input if MREG is enabled, since
        //   combinatorial path is broken
        if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
            assign iA = A, pA = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
        if (BREG == 0 && MREG == 0 && PREG == 0)
            assign iB = B, pB = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
        if (CREG == 0 && PREG == 0)
            assign iC = C, pC = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
        if (DREG == 0 && ADREG == 0)
            assign iD = D, pD = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
        if (PREG == 0) begin
            if (MREG == 1) begin
                assign pAD = 1'bx;
        \$__ABC9_REG rM (.Q(pM));
            end else begin
                if (ADREG == 1)
                    \$__ABC9_REG rAD (.Q(pAD));
                else
                    assign pAD = 1'bx;
        assign pM = 1'bx;
        end
        assign pP = 1'bx;
    end else begin
            assign pAD = 1'bx, pM = 1'bx;
            \$__ABC9_REG rP (.Q(pP));
        end

        if (MREG == 0 && PREG == 0)
            assign mP = oP, mPCOUT = oPCOUT;
        else
            assign mP = 1'bx, mPCOUT = 1'bx;
        \$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
        );
        \$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
        );

        `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT )
    end
    else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
        // Disconnect the A-input if MREG is enabled, since
        //   combinatorial path is broken
        if (AREG == 0 && PREG == 0)
            assign iA = A, pA = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
        if (BREG == 0 && PREG == 0)
            assign iB = B, pB = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
        if (CREG == 0 && PREG == 0)
            assign iC = C, pC = 1'bx;
        else
            \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
        if (DREG == 1 && techmap_guard)
            $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
        assign pD = 1'bx;
        if (ADREG == 1 && techmap_guard)
            $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
        assign pAD = 1'bx;
        if (MREG == 1 && techmap_guard)
            $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
        assign pM = 1'bx;
        if (PREG == 1)
            \$__ABC9_REG rP (.Q(pP));
        else
            assign pP = 1'bx;

        if (MREG == 0 && PREG == 0)
            assign mP = oP, mPCOUT = oPCOUT;
        else
            assign mP = 1'bx, mPCOUT = 1'bx;
        \$__ABC9_DSP48E1_P_MUX muxP (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
        );
        \$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT (
            .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
        );

        `DSP48E1_INST(\$__ABC9_DSP48E1 )
    end
    else
        $error("Invalid DSP48E1 configuration");
    endgenerate
    `undef DSP48E1_INST
endmodule