read_verilog << EOT

module dffe_00( input clk, en,
			input d1, output reg q1,
		);
	always @( negedge clk ) begin
		if ( ~en )
			q1 <= d1;
	end
endmodule

module dffe_01( input clk, en,
			input d1, output reg q1,
		);
	always @( negedge clk ) begin
		if ( en )
			q1 <= d1;
	end
endmodule

module dffe_10( input clk, en,
			input d1, output reg q1,
		);
	always @( posedge clk ) begin
		if ( ~en )
			q1 <= d1;
	end
endmodule

module dffe_11( input clk, en,
			input d1, output reg q1,
		);
	always @( posedge clk ) begin
		if ( en )
			q1 <= d1;
	end
endmodule

module dffe_wide_11( input clk, en,
			input [3:0] d1, output reg [3:0] q1,
		);
	always @( posedge clk ) begin
		if ( en )
			q1 <= d1;
	end
endmodule

EOT

proc
opt

design -save before

#------------------------------------------------------------------------------

# Test -pos

clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen

# falling edge clock flops don't get matched on -pos
select -module dffe_00 -assert-count 0 t:\\pdk_icg
select -module dffe_01 -assert-count 0 t:\\pdk_icg
# rising edge clock flops do get matched on -pos
select -module dffe_10 -assert-count 1 t:\\pdk_icg
select -module dffe_11 -assert-count 1 t:\\pdk_icg
# if necessary, EN is inverted, since the given ICG
# is assumed to have an active-high EN
select -module dffe_10 -assert-count 1 t:\$_NOT_
select -module dffe_11 -assert-count 0 t:\$_NOT_

# Extra credit: multi-bit FFs work fine as well
select -module dffe_wide_11 -assert-count 1 t:\\pdk_icg

#------------------------------------------------------------------------------

# Test -neg

design -load before
clockgate -min_net_size 1 -neg pdk_icg ce:clkin:clkout -tie_lo scanen

# falling edge clock flops do get matched on -neg
select -module dffe_00 -assert-count 1 t:\\pdk_icg
select -module dffe_01 -assert-count 1 t:\\pdk_icg
# rising edge clock flops don't get matched on -neg
select -module dffe_10 -assert-count 0 t:\\pdk_icg
select -module dffe_11 -assert-count 0 t:\\pdk_icg
# if necessary, EN is inverted, since the given ICG
# is assumed to have an active-high EN
select -module dffe_00 -assert-count 1 t:\$_NOT_
select -module dffe_01 -assert-count 0 t:\$_NOT_

#------------------------------------------------------------------------------

# Same as first case, but on fine-grained cells

design -load before

techmap

clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen

# falling edge clock flops don't get matched on -pos
select -module dffe_00 -assert-count 0 t:\\pdk_icg
select -module dffe_01 -assert-count 0 t:\\pdk_icg
# falling edge clock flops do get matched on -pos
select -module dffe_10 -assert-count 1 t:\\pdk_icg
select -module dffe_11 -assert-count 1 t:\\pdk_icg
# if necessary, EN is inverted, since the given ICG
# is assumed to have an active-high EN
select -module dffe_10 -assert-count 1 t:\$_NOT_
select -module dffe_11 -assert-count 0 t:\$_NOT_

# Extra credit: multi-bit FFs work fine as well
select -module dffe_wide_11 -assert-count 1 t:\\pdk_icg

#------------------------------------------------------------------------------

design -load before
clockgate -min_net_size 2 -neg pdk_icg ce:clkin:clkout -tie_lo scanen

# No FF set sharing a (clock, clock enable) pair is large enough
select -module dffe_00 -assert-count 0 t:\\pdk_icg
select -module dffe_01 -assert-count 0 t:\\pdk_icg
select -module dffe_10 -assert-count 0 t:\\pdk_icg
select -module dffe_11 -assert-count 0 t:\\pdk_icg

#------------------------------------------------------------------------------

design -reset
read_rtlil << EOT

module \bad1
  wire input 1 \clk
  wire input 3 \d1
  wire input 2 \en
  wire output 4 \q1
  cell $dffe $auto$ff.cc:266:slice$27
    parameter \CLK_POLARITY 1
    parameter \EN_POLARITY 1
    parameter \WIDTH 1
    connect \CLK \clk
    connect \D \d1
    connect \EN 1'1
    connect \Q \q1
  end
end

module \bad2
  wire input 1 \clk
  wire input 3 \d1
  wire input 2 \en
  wire output 4 \q1
  cell $dffe $auto$ff.cc:266:slice$27
    parameter \CLK_POLARITY 1
    parameter \EN_POLARITY 1
    parameter \WIDTH 1
    connect \CLK 1'1
    connect \D \d1
    connect \EN \en
    connect \Q \q1
  end
end

EOT

# Check we don't choke on constants
clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen
select -module bad1 -assert-count 0 t:\\pdk_icg
select -module bad2 -assert-count 0 t:\\pdk_icg

#------------------------------------------------------------------------------

# Regression test: EN is a bit from a multi-bit wire
design -reset
read_verilog << EOT
module dffe_wide_11( input clk, input [1:0] en,
			input [3:0] d1, output reg [3:0] q1,
		);
	always @( posedge clk ) begin
		if ( en[0] )
			q1 <= d1;
	end
endmodule

EOT

proc
opt

clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen
select -assert-count 1 t:\\pdk_icg

#------------------------------------------------------------------------------

design -load before
clockgate -liberty clockgate.lib

# rising edge ICGs
select -module dffe_00 -assert-count 0 t:\\pos_small
select -module dffe_01 -assert-count 0 t:\\pos_small

select -module dffe_10 -assert-count 1 t:\\pos_small
select -module dffe_11 -assert-count 1 t:\\pos_small

# falling edge ICGs
select -module dffe_00 -assert-count 1 t:\\neg_small
select -module dffe_01 -assert-count 1 t:\\neg_small

select -module dffe_10 -assert-count 0 t:\\neg_small
select -module dffe_11 -assert-count 0 t:\\neg_small

# and nothing else
select -module dffe_00 -assert-count 0 t:\\pos_big
select -module dffe_01 -assert-count 0 t:\\pos_big
select -module dffe_10 -assert-count 0 t:\\pos_big
select -module dffe_11 -assert-count 0 t:\\pos_big
select -module dffe_00 -assert-count 0 t:\\pos_small_tielo
select -module dffe_01 -assert-count 0 t:\\pos_small_tielo
select -module dffe_10 -assert-count 0 t:\\pos_small_tielo
select -module dffe_11 -assert-count 0 t:\\pos_small_tielo
select -module dffe_00 -assert-count 0 t:\\neg_big
select -module dffe_01 -assert-count 0 t:\\neg_big
select -module dffe_10 -assert-count 0 t:\\neg_big
select -module dffe_11 -assert-count 0 t:\\neg_big
select -module dffe_00 -assert-count 0 t:\\neg_small_tielo
select -module dffe_01 -assert-count 0 t:\\neg_small_tielo
select -module dffe_10 -assert-count 0 t:\\neg_small_tielo
select -module dffe_11 -assert-count 0 t:\\neg_small_tielo

# if necessary, EN is inverted, since the given ICG
# is assumed to have an active-high EN
select -module dffe_10 -assert-count 1 t:\$_NOT_
select -module dffe_11 -assert-count 0 t:\$_NOT_

#------------------------------------------------------------------------------

# test multiple liberty files to behave the same way
design -load before
clockgate -liberty clockgate_pos.lib -liberty clockgate_neg.lib

# rising edge ICGs
select -module dffe_00 -assert-count 0 t:\\pos_small
select -module dffe_01 -assert-count 0 t:\\pos_small

select -module dffe_10 -assert-count 1 t:\\pos_small
select -module dffe_11 -assert-count 1 t:\\pos_small

# falling edge ICGs
select -module dffe_00 -assert-count 1 t:\\neg_small
select -module dffe_01 -assert-count 1 t:\\neg_small

select -module dffe_10 -assert-count 0 t:\\neg_small
select -module dffe_11 -assert-count 0 t:\\neg_small

# and nothing else
select -module dffe_00 -assert-count 0 t:\\pos_big
select -module dffe_01 -assert-count 0 t:\\pos_big
select -module dffe_10 -assert-count 0 t:\\pos_big
select -module dffe_11 -assert-count 0 t:\\pos_big
select -module dffe_00 -assert-count 0 t:\\pos_small_tielo
select -module dffe_01 -assert-count 0 t:\\pos_small_tielo
select -module dffe_10 -assert-count 0 t:\\pos_small_tielo
select -module dffe_11 -assert-count 0 t:\\pos_small_tielo
select -module dffe_00 -assert-count 0 t:\\neg_big
select -module dffe_01 -assert-count 0 t:\\neg_big
select -module dffe_10 -assert-count 0 t:\\neg_big
select -module dffe_11 -assert-count 0 t:\\neg_big
select -module dffe_00 -assert-count 0 t:\\neg_small_tielo
select -module dffe_01 -assert-count 0 t:\\neg_small_tielo
select -module dffe_10 -assert-count 0 t:\\neg_small_tielo
select -module dffe_11 -assert-count 0 t:\\neg_small_tielo

# if necessary, EN is inverted, since the given ICG
# is assumed to have an active-high EN
select -module dffe_10 -assert-count 1 t:\$_NOT_
select -module dffe_11 -assert-count 0 t:\$_NOT_

#------------------------------------------------------------------------------

design -load before
clockgate -liberty clockgate.lib -dont_use pos_small -dont_use neg_small

# rising edge ICGs
select -module dffe_10 -assert-count 1 t:\\pos_big
select -module dffe_11 -assert-count 1 t:\\pos_big

# falling edge ICGs
select -module dffe_00 -assert-count 1 t:\\neg_big
select -module dffe_01 -assert-count 1 t:\\neg_big