yosys/tests/silimate/report_fanout.ys

253 lines
5.4 KiB
Plaintext

# Test 1: Input port with high fanout is reported
# Input 'a' fans out to 5 output ports, limit is 3 => should warn for 'a'
# Input 'b' fans out to 2 output ports (<= 3) => no warn for 'b'
log -header "Input port fanout exceeds limit"
log -push
design -reset
read_verilog <<EOF
module top (
input wire a,
input wire b,
output wire w1,
output wire w2,
output wire w3,
output wire w4,
output wire w5,
output wire x1,
output wire x2
);
assign w1 = a;
assign w2 = a;
assign w3 = a;
assign w4 = a;
assign w5 = a;
assign x1 = b;
assign x2 = b;
endmodule
EOF
proc -noopt
opt_clean -purge
# 'a' has fanout 5 (> 3), 'b' has fanout 2 (<= 3)
# Expect exactly one warning for input port 'a'
logger -expect warning "\(top, a\) = 5" 1
report_fanout -limit 3
design -reset
log -pop
# Test 2: Cell output port with high fanout is reported
# AND gate output fans out to 5 output ports, limit is 2 => should warn
log -header "Cell output port fanout exceeds limit"
log -push
design -reset
read_verilog <<EOF
module top (
input wire a,
input wire b,
output wire w1,
output wire w2,
output wire w3,
output wire w4,
output wire w5
);
wire and_out = a & b;
assign w1 = and_out;
assign w2 = and_out;
assign w3 = and_out;
assign w4 = and_out;
assign w5 = and_out;
endmodule
EOF
proc -noopt
opt_clean -purge
# The $and cell's Y port fans out to 5 (> 2)
# Input ports a and b each fan out to 1 cell input (<= 2), no warn for them
logger -expect warning "\(top, .*, Y\) = 5" 1
report_fanout -limit 2
design -reset
log -pop
# Test 3: No warnings when all fanouts are within the limit
log -header "No fanout exceeds limit"
log -push
design -reset
read_verilog <<EOF
module top (
input wire a,
input wire b,
output wire w1,
output wire w2
);
wire and_out = a & b;
assign w1 = and_out;
assign w2 = and_out;
endmodule
EOF
proc -noopt
opt_clean -purge
# All fanouts <= 10, so no warnings expected
logger -expect-no-warnings
report_fanout -limit 10
design -reset
log -pop
# Test 4: Multiple cell output ports reported in the same module
# Two cells each have fanout of 3, limit is 1 => two warnings
log -header "Multiple cells with high fanout"
log -push
design -reset
read_verilog <<EOF
module top (
input wire a,
input wire b,
input wire c,
output wire w1,
output wire w2,
output wire w3,
output wire x1,
output wire x2,
output wire x3
);
wire and_out = a & b;
wire or_out = a | c;
assign w1 = and_out;
assign w2 = and_out;
assign w3 = and_out;
assign x1 = or_out;
assign x2 = or_out;
assign x3 = or_out;
endmodule
EOF
proc -noopt
opt_clean -purge
# Both cells' Y ports fan out to 3 (> 1). Input 'a' fans out to 2 cell inputs (> 1).
# Expect 3 warnings total.
logger -expect warning "\(top, .*, Y\) = 3" 2
logger -expect warning "\(top, a\) = 2" 1
report_fanout -limit 1
design -reset
log -pop
# Test 5: Mixed - input port AND cell output both exceed limit
log -header "Input port and cell output both exceed limit"
log -push
design -reset
read_verilog <<EOF
module top (
input wire a,
input wire b,
output wire w1,
output wire w2,
output wire w3,
output wire y1,
output wire y2,
output wire y3
);
wire not_out = !a;
assign w1 = a;
assign w2 = a;
assign w3 = a;
assign y1 = not_out;
assign y2 = not_out;
assign y3 = not_out;
endmodule
EOF
proc -noopt
opt_clean -purge
# 'a' fans out to 3 output ports + 1 cell input = 4 total (> 2)
# $logic_not Y fans out to 3 (> 2)
logger -expect warning "\(top, a\) = 4" 1
logger -expect warning "\(top, .*, Y\) = 3" 1
report_fanout -limit 2
design -reset
log -pop
# Test 6: Clock and reset ports are excluded by default
log -header "Clock and reset exclusion"
log -push
design -reset
read_verilog <<EOF
module top (
input wire clk,
input wire rst,
input wire [3:0] d,
output reg [3:0] q
);
// Four separate always blocks to create four independent $adff cells
always @(posedge clk or posedge rst) begin
if (rst) q[0] <= 1'b0; else q[0] <= d[0];
end
always @(posedge clk or posedge rst) begin
if (rst) q[1] <= 1'b0; else q[1] <= d[1];
end
always @(posedge clk or posedge rst) begin
if (rst) q[2] <= 1'b0; else q[2] <= d[2];
end
always @(posedge clk or posedge rst) begin
if (rst) q[3] <= 1'b0; else q[3] <= d[3];
end
endmodule
EOF
proc -noopt
opt_clean -purge
# 'clk' and 'rst' each fan out to 4 FF cells but are excluded by default
# 'd' is 4 bits wide, each bit fans out to 1 FF (aggregated = 4), not excluded
logger -expect warning "\(top, d\) = 4" 1
report_fanout -limit 3
design -reset
log -pop
# Test 7: -include_clk_rst makes clock/reset nets reportable
log -header "Clock and reset included with -include_clk_rst"
log -push
design -reset
read_verilog <<EOF
module top (
input wire clk,
input wire rst,
input wire [3:0] d,
output reg [3:0] q
);
always @(posedge clk or posedge rst) begin
if (rst) q[0] <= 1'b0; else q[0] <= d[0];
end
always @(posedge clk or posedge rst) begin
if (rst) q[1] <= 1'b0; else q[1] <= d[1];
end
always @(posedge clk or posedge rst) begin
if (rst) q[2] <= 1'b0; else q[2] <= d[2];
end
always @(posedge clk or posedge rst) begin
if (rst) q[3] <= 1'b0; else q[3] <= d[3];
end
endmodule
EOF
proc -noopt
opt_clean -purge
# With -include_clk_rst, clk and rst (fanout 4 each) should be reported
logger -expect warning "\(top, d\) = 4" 1
logger -expect warning "\(top, clk\) = 4" 1
logger -expect warning "\(top, rst\) = 4" 1
report_fanout -limit 3 -include_clk_rst
design -reset
log -pop