Skip to content

Commit

Permalink
Exclude non-simple wide expressions
Browse files Browse the repository at this point in the history
Signed-off-by: Bartłomiej Chmiel <[email protected]>
  • Loading branch information
b-chmiel committed Dec 9, 2024
1 parent 8ceb0a4 commit 67bf4e4
Show file tree
Hide file tree
Showing 16 changed files with 305 additions and 94 deletions.
24 changes: 15 additions & 9 deletions src/V3Gate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,14 @@ class GateInline final {
size_t m_statExcluded = 0; // Statistic tracking

// METHODS
static bool excludedWide(GateVarVertex* const vVtxp) {
static bool isCheapWide(const GateLogicVertex* const lVtxp, const AstNodeExpr* const rhsp) {
if (const AstSel* const selp = VN_CAST(rhsp, Sel)) {
if (selp->lsbConst() % VL_EDATASIZE == 0) return true;
}
return lVtxp->slow() || VN_IS(rhsp, NodeVarRef) || VN_IS(rhsp, Const)
|| VN_IS(rhsp, ArraySel);
}
static bool excludedWide(GateVarVertex* const vVtxp, const AstNodeExpr* const rhsp) {
// Handle wides with logic drivers.
if (!vVtxp->varScp()->isWide() || vVtxp->inEmpty()
|| vVtxp->varScp()->widthWords() <= v3Global.opt.expandLimit())
Expand All @@ -693,8 +700,7 @@ class GateInline final {
const GateLogicVertex* const lVtxp
= vVtxp->inEdges().frontp()->fromp()->as<GateLogicVertex>();

if (lVtxp->slow() || VN_IS(lVtxp->nodep(), AssignAlias))
return false; // Do not optimize consts, aliases and slow parts.
if (isCheapWide(lVtxp, rhsp)) return false;

// Exclude from inlining variables READ multiple times that are initialized by wide
// assigns.
Expand Down Expand Up @@ -790,12 +796,6 @@ class GateInline final {

// Can't inline if non-reducible, etc
if (!vVtxp->reducible()) continue;
if (excludedWide(vVtxp)) {
++m_statExcluded;
UINFO(9, "Gate inline exclude '" << vVtxp->name() << "'" << endl);
vVtxp->clearReducible("Excluded wide"); // Check once.
continue;
}

// Grab the driving logic
GateLogicVertex* const lVtxp
Expand All @@ -813,6 +813,12 @@ class GateInline final {
if (!okVisitor.isSimple()) continue;
// If the varScope is already removed from logicp, no need to try substitution.
if (!okVisitor.varAssigned(vVtxp->varScp())) continue;
if (excludedWide(vVtxp, okVisitor.substitutionp())) {
++m_statExcluded;
UINFO(9, "Gate inline exclude '" << vVtxp->name() << "'" << endl);
vVtxp->clearReducible("Excluded wide"); // Check once.
continue;
}

// Does it read multiple source variables?
if (okVisitor.readVscps().size() > 1) {
Expand Down
82 changes: 0 additions & 82 deletions test_regress/t/t_duplicate_wide_expr.v

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

test.scenarios('vlt')

test.compile(verilator_flags2=['--stats', '--expand-limit 5'])
test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 3)
test.file_grep(test.stats, r'Optimizations, expand wides\s+(\d+)', 162)
test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 2)
test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 4)

test.passes()
27 changes: 27 additions & 0 deletions test_regress/t/t_gate_inline_wide_exclude_multiple.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro.
// SPDX-License-Identifier: CC0-1.0

localparam N = 256; // Wider than expand limit.

module t(
input wire [N-1:0] i,
output logic [N-1:0] o_multiple1,
output logic [N-1:0] o_multiple2,
output wire [N-1:0] o
);

// Exclude from inline wide expressions referenced multiple times.
wire [N-1:0] wide_multiple_assigns = N >> i;
wire [N-1:0] wide = N << i;

for (genvar n = 0; n < N - 1; ++n) begin
assign o[n] = i[N-1-n] | wide[N-1-n];
end

assign o_multiple1 = wide_multiple_assigns | i + 1;
assign o_multiple2 = wide_multiple_assigns | i + 2;
endmodule

19 changes: 19 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_arraysel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

import vltest_bootstrap

test.scenarios('vlt')

test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0)
test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 1)

test.passes()
20 changes: 20 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_arraysel.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro.
// SPDX-License-Identifier: CC0-1.0

module t;
logic [255:0] arrd [0:0] = '{ 1 };
logic [255:0] y0;

// Do not exclude from inlining wide arraysels.
always_comb y0 = arrd[0];

always_comb begin
if (y0 != 1 && y0 != 0) begin
$stop;
end
end
endmodule

19 changes: 19 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

import vltest_bootstrap

test.scenarios('vlt')

test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0)
test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 2)

test.passes()
20 changes: 20 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_const.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro.
// SPDX-License-Identifier: CC0-1.0

module t;
logic [255:0] arrd = 256'b0;
logic [255:0] y0;

// Do not exclude from inlining wide variables with const assignments.
always_comb y0 = 256'(arrd[0]);

always_comb begin
if (y0 != 1 && y0 != 0) begin
$stop;
end
end
endmodule

18 changes: 18 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_other_scope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

import vltest_bootstrap

test.scenarios('vlt')

test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0)

test.passes()
26 changes: 26 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_other_scope.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro.
// SPDX-License-Identifier: CC0-1.0

localparam N = 256; // Wider than expand limit.

module t(
input wire [N-1:0] i,
output wire [N-1:0] o
);

// Do not exclude from inlining wides referenced in different scope.
wire [N-1:0] wide = N ~^ i;

sub sub(i, wide, o);
endmodule

module sub(input wire [N-1:0] i, input wire [N-1:0] wide, output logic [N-1:0] o);
initial begin
for (integer n = 0; n < N ; ++n) begin
o[n] = i[N-1-n] | wide[N-1-n];
end
end
endmodule
19 changes: 19 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_sel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

import vltest_bootstrap

test.scenarios('vlt')

test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 1)
test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 9)

test.passes()
44 changes: 44 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_sel.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro.
// SPDX-License-Identifier: CC0-1.0

module t (
output reg [1020:0] res1,
output reg [1020:0] res2,
output reg [1022:0] res3,
output reg [1022:0] res4
);
always_inline always_inline(res1, res2);
dont_inline dont_inline(res3, res4);
endmodule

module always_inline(
output reg [1020:0] res1,
output reg [1020:0] res2
);

wire [1023:0] a;
wire [478:0] b;

assign b = a[510:32];
assign res1 = {542'b0, b};
assign res2 = {542'b1, b};
endmodule

// SEL does not have proper offset so we do not have guarantee that it will be
// emitted as '[' operator, thus we do not exclude it from inlining.
module dont_inline(
output reg [1022:0] res1,
output reg [1022:0] res2
);

wire [1023:0] a;
wire [480:0] b;

// LSB % 32 != 0
assign b = a[510:30];
assign res1 = {542'b0, b};
assign res2 = {542'b1, b};
endmodule
18 changes: 18 additions & 0 deletions test_regress/t/t_gate_inline_wide_noexclude_small_wide.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

import vltest_bootstrap

test.scenarios('vlt')

test.lint(verilator_flags2=['--stats', '--expand-limit 5'])

test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0)

test.passes()
Loading

0 comments on commit 67bf4e4

Please sign in to comment.