diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 372232024..9a98157e9 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1906,7 +1906,7 @@ private: } else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting && operandIfIf(nodep)) { - UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"< IF({a} && {b})"<ifsp()->castNodeIf(); AstNode* condp = nodep->condp()->unlinkFrBack(); AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext(); @@ -1922,6 +1922,49 @@ private: } } + virtual void visit(AstDisplay* nodep) { + // DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2)) + nodep->iterateChildren(*this); + if (stmtDisplayDisplay(nodep)) return; + } + bool stmtDisplayDisplay(AstDisplay* nodep) { + // DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2)) + if (!m_modp) return false; // Don't optimize under single statement + if (!nodep->backp()) return false; + AstDisplay* prevp = nodep->backp()->castDisplay(); + if (!prevp) return false; + if (!((prevp->displayType() == nodep->displayType()) + || (prevp->displayType() == AstDisplayType::DT_WRITE + && nodep->displayType() == AstDisplayType::DT_DISPLAY) + || (prevp->displayType() == AstDisplayType::DT_DISPLAY + && nodep->displayType() == AstDisplayType::DT_WRITE))) + return false; + if ((prevp->filep() && !nodep->filep()) + || (!prevp->filep() && nodep->filep()) + || !prevp->filep()->sameTree(nodep->filep())) return false; + if (!prevp->fmtp() || prevp->fmtp()->nextp() + || !nodep->fmtp() || nodep->fmtp()->nextp()) return false; + AstSFormatF* pformatp = prevp->fmtp(); + if (!pformatp || pformatp->exprsp() || pformatp->scopeNamep()) return false; + AstSFormatF* nformatp = nodep->fmtp(); + if (!nformatp || nformatp->exprsp() || nformatp->scopeNamep()) return false; + // + UINFO(9,"DISPLAY(SF({a})) DISPLAY(SF({b})) -> DISPLAY(SF({a}+{b}))"<displayType() == AstDisplayType::DT_DISPLAY) { + prevp->displayType(AstDisplayType::DT_WRITE); + pformatp->text(pformatp->text()+"\n"); + } + // We can't replace prev() as the edit tracking iterators will get confused. + // So instead we edit the prev note itself. + if (prevp->addNewline()) pformatp->text(pformatp->text()+"\n"); + pformatp->text(pformatp->text()+nformatp->text()); + if (!prevp->addNewline() && nodep->addNewline()) { + pformatp->text(pformatp->text()+"\n"); + } + nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); + return true; + } virtual void visit(AstSFormatF* nodep) { // Substitute constants into displays. The main point of this is to // simplify assertion methodologies which call functions with display's. @@ -1960,7 +2003,7 @@ private: UINFO(9," DispConst: "< "<unlinkFrBack()->deleteTree(); + argp->unlinkFrBack()->deleteTree(); VL_DANGLING(argp); } argp=nextp; } diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 2a5751368..87f17ac53 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -166,7 +166,7 @@ private: } } // Not really any way the user could do this, and we'd need to come up with some return value - //newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DT_DISPLAY, + //newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DT_WARNING, // string("%%Error: ")+name+"() called with bad scope", NULL)); //newfuncp->addStmtsp(new AstStop (newfuncp->fileline())); if (debug()>=9) newfuncp->dumpTree(cout," newfunc: "); diff --git a/test_regress/t/t_display_merge.pl b/test_regress/t/t_display_merge.pl new file mode 100755 index 000000000..39fa98e3f --- /dev/null +++ b/test_regress/t/t_display_merge.pl @@ -0,0 +1,27 @@ +#!/usr/bin/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. + +compile ( + verilator_flags2=>["--stats"], + ); + +execute ( + check_finished=>1, + expect=> (quotemeta( +'Merge: +This should merge +*-* All Finished *-*') + .'.*') + ); + +file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}__stats.txt", + qr/Node count, DISPLAY \s+ 5 \s+ 1 \s+ 1 \s+ 1/); + +ok(1); +1; diff --git a/test_regress/t/t_display_merge.v b/test_regress/t/t_display_merge.v new file mode 100644 index 000000000..2ab343756 --- /dev/null +++ b/test_regress/t/t_display_merge.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2017 by Wilson Snyder. + +module t (/*AUTOARG*/); + initial begin + $display("Merge:"); + $write("This "); + $write("should "); + $display("merge"); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule