diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 0a1fcdb91..49dc1a377 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -812,12 +812,13 @@ private: // commonly appears after V3Expand and the simplification in matchMaskedOr. Similarly, // drop redundant masking of left shift result. E.g.: 0xff000000 & ((uint32_t)a << 24). - if (nodep->width() != nodep->rhsp()->width()) return false; // Paranoia - const auto checkMask = [=](const V3Number& mask) -> bool { const AstConst* const constp = VN_CAST(nodep->lhsp(), Const); if (constp->num().isCaseEq(mask)) { - nodep->replaceWith(nodep->rhsp()->unlinkFrBack()); + AstNode* const rhsp = nodep->rhsp(); + rhsp->unlinkFrBack(); + nodep->replaceWith(rhsp); + rhsp->dtypeFrom(nodep); VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; } @@ -3101,7 +3102,7 @@ private: // Common two-level operations that can be simplified TREEOP ("AstAnd {$lhsp.castConst,matchAndCond(nodep)}", "DONE"); TREEOP ("AstAnd {$lhsp.castConst, $rhsp.castOr, matchMaskedOr(nodep)}", "DONE"); - TREEOP ("AstAnd {$lhsp.castConst, matchMaskedShift(nodep)}", "DONE"); + TREEOPC("AstAnd {$lhsp.castConst, matchMaskedShift(nodep)}", "DONE"); TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstOr {matchOrAndNot(nodep)}", "DONE"); diff --git a/test_regress/t/t_write_format_bug.out b/test_regress/t/t_write_format_bug.out new file mode 100644 index 000000000..ab787ff12 --- /dev/null +++ b/test_regress/t/t_write_format_bug.out @@ -0,0 +1,9 @@ +00005678 +00001234 +00005679 +00001234 +0000567a +00001234 +0000567b +00001234 +*-* All Finished *-* diff --git a/test_regress/t/t_write_format_bug.pl b/test_regress/t/t_write_format_bug.pl new file mode 100755 index 000000000..1576259ea --- /dev/null +++ b/test_regress/t/t_write_format_bug.pl @@ -0,0 +1,22 @@ +#!/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); + +compile( + ); + +execute( + check_finished => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_write_format_bug.v b/test_regress/t/t_write_format_bug.v new file mode 100644 index 000000000..11a6895f1 --- /dev/null +++ b/test_regress/t/t_write_format_bug.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2021 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module test( + /*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cnt = 32'h12345678; + int cyc = 0; + + always @(posedge clk) begin + if (cyc > 3) begin + $write("*-* All Finished *-*\n"); + $finish; + end else begin + cyc <= cyc + 1; + cnt <= cnt + 1; + $write("%08x\n", {16'h0, cnt[15: 0]}); + $write("%08x\n", {16'h0, cnt[31:16]}); + end + end + +endmodule