/*
 *  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.
 *
 */

// ============================================================================
// LCU

(* techmap_celltype = "$lcu" *)
module _80_xilinx_lcu (P, G, CI, CO);
	parameter WIDTH = 2;

	input [WIDTH-1:0] P, G;
	input CI;

	output [WIDTH-1:0] CO;

	wire _TECHMAP_FAIL_ = WIDTH <= 2;

	genvar i;

`ifdef _CLB_CARRY

	localparam CARRY4_COUNT = (WIDTH + 3) / 4;
	localparam MAX_WIDTH    = CARRY4_COUNT * 4;
	localparam PAD_WIDTH    = MAX_WIDTH - WIDTH;

	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, P & ~G};
	wire [MAX_WIDTH-1:0] C  = CO;

	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice

		// Partially occupied CARRY4
		if ((i+1)*4 > WIDTH) begin

			// First one
			if (i == 0) begin
				CARRY4 carry4_1st_part
				(
				.CYINIT(CI),
				.CI    (1'd0),
				.DI    (G [(Y_WIDTH - 1):i*4]),
				.S     (S [(Y_WIDTH - 1):i*4]),
				.CO    (CO[(Y_WIDTH - 1):i*4]),
				);
			// Another one
			end else begin
				CARRY4 carry4_part
				(
				.CYINIT(1'd0),
				.CI    (C [i*4 - 1]),
				.DI    (G [(Y_WIDTH - 1):i*4]),
				.S     (S [(Y_WIDTH - 1):i*4]),
				.CO    (CO[(Y_WIDTH - 1):i*4]),
				);
			end

		// Fully occupied CARRY4
		end else begin

			// First one
			if (i == 0) begin
				CARRY4 carry4_1st_full
				(
				.CYINIT(CI),
				.CI    (1'd0),
				.DI    (G [((i+1)*4 - 1):i*4]),
				.S     (S [((i+1)*4 - 1):i*4]),
				.CO    (CO[((i+1)*4 - 1):i*4]),
				);
			// Another one
			end else begin
				CARRY4 carry4_full
				(
				.CYINIT(1'd0),
				.CI    (C [i*4 - 1]),
				.DI    (G [((i+1)*4 - 1):i*4]),
				.S     (S [((i+1)*4 - 1):i*4]),
				.CO    (CO[((i+1)*4 - 1):i*4]),
				);
			end

		end

	end endgenerate

`elsif _EXPLICIT_CARRY

	wire [WIDTH-1:0] C = {CO, CI};
	wire [WIDTH-1:0] S = P & ~G;

	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
		MUXCY muxcy (
			.CI(C[i]),
			.DI(G[i]),
			.S(S[i]),
			.O(CO[i])
		);
	end endgenerate

`else

	wire [WIDTH-1:0] C = {CO, CI};
	wire [WIDTH-1:0] S = P & ~G;

	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
		MUXCY muxcy (
			.CI(C[i]),
			.DI(G[i]),
			.S(S[i]),
			.O(CO[i])
		);
	end endgenerate
`endif

endmodule


// ============================================================================
// ALU

(* techmap_celltype = "$alu" *)
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
	parameter A_SIGNED = 0;
	parameter B_SIGNED = 0;
	parameter A_WIDTH = 1;
	parameter B_WIDTH = 1;
	parameter Y_WIDTH = 1;
	parameter _TECHMAP_CONSTVAL_CI_ = 0;
	parameter _TECHMAP_CONSTMSK_CI_ = 0;

	input [A_WIDTH-1:0] A;
	input [B_WIDTH-1:0] B;
	output [Y_WIDTH-1:0] X, Y;

	input CI, BI;
	output [Y_WIDTH-1:0] CO;

	wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;

	wire [Y_WIDTH-1:0] A_buf, B_buf;
	\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
	\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));

	wire [Y_WIDTH-1:0] AA = A_buf;
	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;

	genvar i;

`ifdef _CLB_CARRY

	localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4;
	localparam MAX_WIDTH    = CARRY4_COUNT * 4;
	localparam PAD_WIDTH    = MAX_WIDTH - Y_WIDTH;

	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, AA ^ BB};
	wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB};

	wire [MAX_WIDTH-1:0] C  = CO;

	genvar i;
	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice

		// Partially occupied CARRY4
		if ((i+1)*4 > Y_WIDTH) begin

			// First one
			if (i == 0) begin
				CARRY4 carry4_1st_part
				(
				.CYINIT(CI),
				.CI    (1'd0),
				.DI    (DI[(Y_WIDTH - 1):i*4]),
				.S     (S [(Y_WIDTH - 1):i*4]),
				.O     (Y [(Y_WIDTH - 1):i*4]),
				.CO    (CO[(Y_WIDTH - 1):i*4])
				);
			// Another one
			end else begin
				CARRY4 carry4_part
				(
				.CYINIT(1'd0),
				.CI    (C [i*4 - 1]),
				.DI    (DI[(Y_WIDTH - 1):i*4]),
				.S     (S [(Y_WIDTH - 1):i*4]),
				.O     (Y [(Y_WIDTH - 1):i*4]),
				.CO    (CO[(Y_WIDTH - 1):i*4])
				);
			end

		// Fully occupied CARRY4
		end else begin

			// First one
			if (i == 0) begin
				CARRY4 carry4_1st_full
				(
				.CYINIT(CI),
				.CI    (1'd0),
				.DI    (DI[((i+1)*4 - 1):i*4]),
				.S     (S [((i+1)*4 - 1):i*4]),
				.O     (Y [((i+1)*4 - 1):i*4]),
				.CO    (CO[((i+1)*4 - 1):i*4])
				);
			// Another one
			end else begin
				CARRY4 carry4_full
				(
				.CYINIT(1'd0),
				.CI    (C [i*4 - 1]),
				.DI    (DI[((i+1)*4 - 1):i*4]),
				.S     (S [((i+1)*4 - 1):i*4]),
				.O     (Y [((i+1)*4 - 1):i*4]),
				.CO    (CO[((i+1)*4 - 1):i*4])
				);
			end

		end

	end endgenerate

`elsif _EXPLICIT_CARRY

	wire [Y_WIDTH-1:0] S = AA ^ BB;
	wire [Y_WIDTH-1:0] DI = AA & BB;

	wire CINIT;
	// Carry chain.
	//
	// VPR requires that the carry chain never hit the fabric.	The CO input
	// to this techmap is the carry outputs for synthesis, e.g. might hit the
	// fabric.
	//
	// So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
	// e.g. off fabric dedicated chain.  CO is the carry outputs that are
	// available to the fabric.
	wire [Y_WIDTH-1:0] CO_CHAIN;
	wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};

	// If carry chain is being initialized to a constant, techmap the constant
	// source.	Otherwise techmap the fabric source.
	generate for (i = 0; i < 1; i = i + 1) begin:slice
		CARRY0 #(.CYINIT_FABRIC(1)) carry(
			.CI_INIT(CI),
			.DI(DI[0]),
			.S(S[0]),
			.CO_CHAIN(CO_CHAIN[0]),
			.CO_FABRIC(CO[0]),
			.O(Y[0])
		);
	end endgenerate

	generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
		if(i % 4 == 0) begin
			CARRY0 carry (
				.CI(C[i]),
				.DI(DI[i]),
				.S(S[i]),
				.CO_CHAIN(CO_CHAIN[i]),
				.CO_FABRIC(CO[i]),
				.O(Y[i])
			);
		end
		else
		begin
			CARRY carry (
				.CI(C[i]),
				.DI(DI[i]),
				.S(S[i]),
				.CO_CHAIN(CO_CHAIN[i]),
				.CO_FABRIC(CO[i]),
				.O(Y[i])
			);
		end
	end endgenerate

	generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
		if(i % 4 == 0) begin
			CARRY0 top_of_carry (
				.CI(C[i]),
				.DI(DI[i]),
				.S(S[i]),
				.CO_CHAIN(CO_CHAIN[i]),
				.O(Y[i])
			);
		end
		else
		begin
			CARRY top_of_carry (
				.CI(C[i]),
				.DI(DI[i]),
				.S(S[i]),
				.CO_CHAIN(CO_CHAIN[i]),
				.O(Y[i])
			);
		end
		// Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
		// a non-congested path to output the top of the carry chain.
		// Registering the output of the CARRY block would solve this, but not
		// all designs do that.
		if((i+1) % 4 == 0) begin
			CARRY0 carry_output (
				.CI(CO_CHAIN[i]),
				.DI(0),
				.S(0),
				.O(CO[i])
			);
		end
		else
		begin
			CARRY carry_output (
				.CI(CO_CHAIN[i]),
				.DI(0),
				.S(0),
				.O(CO[i])
			);
		end
	end endgenerate

`else

	wire [Y_WIDTH-1:0] S = AA ^ BB;
	wire [Y_WIDTH-1:0] DI = AA & BB;

	wire [Y_WIDTH-1:0] C = {CO, CI};

	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
		MUXCY muxcy (
			.CI(C[i]),
			.DI(DI[i]),
			.S(S[i]),
			.O(CO[i])
		);
		XORCY xorcy (
			.CI(C[i]),
			.LI(S[i]),
			.O(Y[i])
		);
	end endgenerate

`endif

	assign X = S;
endmodule

