diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 522c0c3a6..6bd46d81e 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -594,7 +594,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { const V3Number& compNum = constp->num(); auto setPolarities = [this, &compNum](const LeafInfo& ref, const V3Number* maskp) { - const bool maskFlip = isOrTree(); + const bool maskFlip = isAndTree() ^ ref.polarity(); int constantWidth = compNum.width(); if (maskp) constantWidth = std::max(constantWidth, maskp->width()); const int maxBitIdx = std::max(ref.lsb() + constantWidth, ref.msb() + 1); diff --git a/test_regress/t/t_const_opt.pl b/test_regress/t/t_const_opt.pl index c46c13c54..c01b55613 100755 --- a/test_regress/t/t_const_opt.pl +++ b/test_regress/t/t_const_opt.pl @@ -20,7 +20,7 @@ execute( ); if ($Self->{vlt}) { - file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 37); + file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 39); } ok(1); 1; diff --git a/test_regress/t/t_const_opt.v b/test_regress/t/t_const_opt.v index 3151eb44d..33be8914e 100644 --- a/test_regress/t/t_const_opt.v +++ b/test_regress/t/t_const_opt.v @@ -62,7 +62,7 @@ module t(/*AUTOARG*/ $write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum); if (crc !== 64'hc77bb9b3784ea091) $stop; // What checksum will we end up with (above print should match) -`define EXPECTED_SUM 64'hd1610f7181cbc1b4 +`define EXPECTED_SUM 64'h5a76f060ff8aba3e if (sum !== `EXPECTED_SUM) $stop; $write("*-* All Finished *-*\n"); @@ -95,10 +95,11 @@ module Test(/*AUTOARG*/ logic bug4059_out; logic bug4832_out; logic bug4837_out; + logic bug4857_out; output logic o; - logic [16:0] tmp; + logic [17:0] tmp; assign o = ^tmp; always_ff @(posedge clk) begin @@ -131,6 +132,7 @@ module Test(/*AUTOARG*/ tmp[14]<= bug4059_out; tmp[15]<= bug4832_out; tmp[16]<= bug4837_out; + tmp[17]<= bug4857_out; end bug3182 i_bug3182(.in(d[4:0]), .out(bug3182_out)); @@ -144,6 +146,7 @@ module Test(/*AUTOARG*/ bug4059 i_bug4059(.clk(clk), .in(d), .out(bug4059_out)); bug4832 i_bug4832(.clk(clk), .in(d), .out(bug4832_out)); bug4837 i_bug4837(.clk(clk), .in(d), .out(bug4837_out)); + bug4857 i_bug4857(.clk(clk), .in(d), .out(bug4857_out)); endmodule @@ -450,3 +453,39 @@ module bug4837(input wire clk, input wire [31:0] in, output out); assign out = out_data[33] ^ out_data[32] ^ out_data[0]; endmodule + +// See issue #4857 +// (1'b0 != (!a)) | b was wrongly optimized to +// (a | b) & 1'b1 +// polarity was not considered when traversing NEQ under AND/OR tree +module bug4857(input wire clk, input wire [31:0] in, output out); + logic [95:0] d; + always_ff @(posedge clk) + d <= {d[63:0], in}; + + wire celloutsig_12z; + wire celloutsig_15z; + wire celloutsig_17z; + wire celloutsig_4z; + wire celloutsig_67z; + wire celloutsig_9z; + logic [95:0] in_data; + logic result; + + // verilator lint_off UNDRIVEN + wire [95:0] out_data; + // verilator lint_on UNDRIVEN + + assign celloutsig_4z = ~(in_data[72] & in_data[43]); // 1 + assign celloutsig_67z = | { in_data[64], celloutsig_12z }; // 0 + assign celloutsig_15z = in_data[43] & ~(celloutsig_4z); // 0 + assign celloutsig_9z = celloutsig_17z & ~(in_data[43]); // 00000000 + assign celloutsig_17z = celloutsig_15z & ~(in_data[43]);// 0 + assign celloutsig_12z = celloutsig_4z != celloutsig_9z; // 1 + assign out_data[32] = celloutsig_67z; // 1 + + assign in_data = d; + always_ff @ (posedge clk) + result <= out_data[32]; + assign out = result; +endmodule diff --git a/test_regress/t/t_const_opt_dfg.pl b/test_regress/t/t_const_opt_dfg.pl new file mode 100755 index 000000000..ef7ce89ed --- /dev/null +++ b/test_regress/t/t_const_opt_dfg.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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 + +scenarios(simulator => 1); +top_filename("t/t_const_opt.v"); + +compile( + verilator_flags2 => ["-Wno-UNOPTTHREADS", + "--stats", "$Self->{t_dir}/t_const_opt.cpp"], + ); + +execute( + check_finished => 1, + ); + +if ($Self->{vlt}) { + file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 34); +} +ok(1); +1;