read_verilog <<EOF
module bufgate(A, Y);
	input wire A;
	output wire Y = A;
endmodule

module reducegate(A, B, C, X, Y);
	input wire A;
	input wire B;
	input wire C;
	output wire X = &{A, B, C};
	output wire Y = |{A, B, C};
endmodule

module fagate(A, B, C, X, Y);
	input wire A;
	input wire B;
	input wire C;
	wire t1 = A ^ B;
	wire t2 = A & B;
	wire t3 = C & t1;
	output wire X = t1 ^ C;
	output wire Y = t2 | t3;
endmodule
EOF
design -stash gatelib

read_verilog <<EOF
module ripple_carry(A, B, Y);
	parameter WIDTH = 4;

	input wire [WIDTH-1:0] A;
	input wire [WIDTH-1:0] B;
	output wire [WIDTH-1:0] Y;

	wire [WIDTH:0] carry;
	assign carry[0] = 0;

	generate
		genvar i;

		for (i = 0; i < WIDTH; i = i + 1) begin
			FA fa(
				.A(A[i]),
				.B(B[i]), .Y(Y[i]),
				.CI(carry[i]), .CO(carry[i + 1]),
			);
		end
	endgenerate
endmodule

(* gate *)
module FA(A, B, CI, CO, Y);
	input wire A, B, CI;
	output wire CO, Y;
	assign {CO, Y} = A + B + CI;
endmodule
EOF

prep
cellmatch -lib gatelib FA A:gate

design -save gold
techmap -map %$cellmatch
design -save gate

select -assert-none ripple_carry/t:FA

design -reset
design -copy-from gold -as gold ripple_carry
design -copy-from gate -as gate ripple_carry
opt_clean
equiv_make gold gate equiv
hierarchy -top equiv
flatten
opt_clean
equiv_induct equiv
equiv_status -assert

design -reset
design -load gatelib
cellmatch -derive_luts
select -assert-any bufgate/w:Y a:lut=2'b10 %i
select -assert-any reducegate/w:X a:lut=8'b10000000 %i
select -assert-any reducegate/w:Y a:lut=8'b11111110 %i
select -assert-any fagate/w:X a:lut=8'b10010110 %i
select -assert-any fagate/w:Y a:lut=8'b11101000 %i
