From d67d75282c8550e7f5ac24a344517523f2d9e594 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 7 Apr 2023 20:57:17 -0400 Subject: [PATCH] Support ++/-- on dotted member variables. --- Changes | 1 + src/V3LinkInc.cpp | 23 ++++---- test_regress/t/t_class_inc.pl | 21 +++++++ test_regress/t/t_class_inc.v | 37 +++++++++++++ test_regress/t/t_increment_bad.out | 3 - test_regress/t/t_math_real.v | 10 ++++ test_regress/t/t_math_wide_inc.pl | 21 +++++++ test_regress/t/t_math_wide_inc.v | 89 ++++++++++++++++++++++++++++++ 8 files changed, 191 insertions(+), 14 deletions(-) create mode 100755 test_regress/t/t_class_inc.pl create mode 100644 test_regress/t/t_class_inc.v create mode 100755 test_regress/t/t_math_wide_inc.pl create mode 100644 test_regress/t/t_math_wide_inc.v diff --git a/Changes b/Changes index 7ad1c2e30..52905d12a 100644 --- a/Changes +++ b/Changes @@ -22,6 +22,7 @@ Verilator 5.009 devel * Support method calls without parenthesis (#4034). [Ryszard Rozak, Antmicro Ltd] * Support complicated IEEE 'for' assignments. * Support $fopen as an expression. +* Support ++/-- on dotted member variables. * Change range order warning from LITENDIAN to ASCRANGE (#4010). [Iztok Jeras] * Change ZERODLY to a warning. * Fix random internal crashes (#666). [Dag Lem] diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index ac89c57ee..e420d1276 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -240,11 +240,12 @@ private: return; } - const AstNodeVarRef* varrefp = nullptr; - if (m_unsupportedHere || !(varrefp = VN_CAST(nodep->rhsp(), VarRef))) { + if (m_unsupportedHere) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Incrementation in this context."); return; } + AstNodeExpr* const readp = nodep->rhsp(); + AstNodeExpr* const writep = nodep->thsp(); AstConst* const constp = VN_AS(nodep->lhsp(), Const); UASSERT_OBJ(nodep, constp, "Expecting CONST"); @@ -254,8 +255,9 @@ private: // Prepare a temporary variable FileLine* const fl = backp->fileline(); const string name = string{"__Vincrement"} + cvtToStr(++m_modIncrementsNum); - AstVar* const varp = new AstVar{fl, VVarType::BLOCKTEMP, name, VFlagChildDType{}, - varrefp->varp()->subDTypep()->cloneTree(true)}; + AstVar* const varp = new AstVar{ + fl, VVarType::BLOCKTEMP, name, VFlagChildDType{}, + new AstRefDType{fl, AstRefDType::FlagTypeOfExpr{}, readp->cloneTree(true)}}; if (m_ftaskp) varp->funcLocal(true); // Declare the variable @@ -264,30 +266,29 @@ private: // Define what operation will we be doing AstNodeExpr* operp; if (VN_IS(nodep, PostSub) || VN_IS(nodep, PreSub)) { - operp = new AstSub{fl, new AstVarRef{fl, varrefp->varp(), VAccess::READ}, newconstp}; + operp = new AstSub{fl, readp->cloneTree(true), newconstp}; } else { - operp = new AstAdd{fl, new AstVarRef{fl, varrefp->varp(), VAccess::READ}, newconstp}; + operp = new AstAdd{fl, readp->cloneTree(true), newconstp}; } if (VN_IS(nodep, PreAdd) || VN_IS(nodep, PreSub)) { // PreAdd/PreSub operations // Immediately after declaration - increment it by one - varp->addNextHere(new AstAssign{fl, new AstVarRef{fl, varrefp->varp(), VAccess::WRITE}, + varp->addNextHere(new AstAssign{fl, writep->cloneTree(true), new AstVarRef{fl, varp, VAccess::READ}}); // Immediately after incrementing - assign it to the original variable varp->addNextHere(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, operp}); } else { // PostAdd/PostSub operations // assign the original variable to the temporary one - varp->addNextHere( - new AstAssign{fl, new AstVarRef{fl, varrefp->varp(), VAccess::WRITE}, operp}); + varp->addNextHere(new AstAssign{fl, writep->cloneTree(true), operp}); // Increment the original variable by one varp->addNextHere(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, - new AstVarRef{fl, varrefp->varp(), VAccess::READ}}); + readp->cloneTree(true)}); } // Replace the node with the temporary - nodep->replaceWith(new AstVarRef{varrefp->fileline(), varp, VAccess::READ}); + nodep->replaceWith(new AstVarRef{readp->fileline(), varp, VAccess::READ}); VL_DO_DANGLING(nodep->deleteTree(), nodep); } void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } diff --git a/test_regress/t/t_class_inc.pl b/test_regress/t/t_class_inc.pl new file mode 100755 index 000000000..859050d63 --- /dev/null +++ b/test_regress/t/t_class_inc.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2023 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, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_inc.v b/test_regress/t/t_class_inc.v new file mode 100644 index 000000000..446df0c3f --- /dev/null +++ b/test_regress/t/t_class_inc.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base #(type T = integer); + T m_count; + + function void test1(); + if (this.m_count != 0) $stop; + if (this.m_count++ != 0) $stop; + if (this.m_count != 1) $stop; + if (m_count++ != 1) $stop; + if (this.m_count != 2) $stop; + endfunction +endclass + +class Cls #(type T = integer) extends Base #(T); +endclass + +module t; + Cls #(int) c; + + initial begin + c = new; + c.test1(); + + c.m_count = 0; + if (c.m_count != 0) $stop; + if (c.m_count++ != 0) $stop; + if (c.m_count != 1) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_increment_bad.out b/test_regress/t/t_increment_bad.out index 026148082..08749d938 100644 --- a/test_regress/t/t_increment_bad.out +++ b/test_regress/t/t_increment_bad.out @@ -17,9 +17,6 @@ %Error-UNSUPPORTED: t/t_increment_bad.v:27:29: Unsupported: Incrementation in this context. 27 | pos = (a > 0) ? a++ : --b; | ^~ -%Error-UNSUPPORTED: t/t_increment_bad.v:29:24: Unsupported: Incrementation in this context. - 29 | pos = array[0][0]++; - | ^~ %Error-UNSUPPORTED: t/t_increment_bad.v:32:37: Unsupported: Incrementation in this context. 32 | assert property (@(posedge clk) a++ >= 0); | ^~ diff --git a/test_regress/t/t_math_real.v b/test_regress/t/t_math_real.v index 8798f1cdb..661837d61 100644 --- a/test_regress/t/t_math_real.v +++ b/test_regress/t/t_math_real.v @@ -138,6 +138,16 @@ module t (/*AUTOARG*/ r = real'(96'shf0000000_00000000_00000000); if (r != -4951760157141521099596496896.0) $stop; + r = 1.5; + if (r++ != 1.5) $stop; + if (r != 2.5) $stop; + if (r-- != 2.5) $stop; + if (r != 1.5) $stop; + if (++r != 2.5) $stop; + if (r != 2.5) $stop; + if (--r != 1.5) $stop; + if (r != 1.5) $stop; + r = 1.23456; s = $sformatf("%g", r); `checks(s, "1.23456"); diff --git a/test_regress/t/t_math_wide_inc.pl b/test_regress/t/t_math_wide_inc.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_math_wide_inc.pl @@ -0,0 +1,21 @@ +#!/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, + ); + +ok(1); +1; diff --git a/test_regress/t/t_math_wide_inc.v b/test_regress/t/t_math_wide_inc.v new file mode 100644 index 000000000..1d62ca03f --- /dev/null +++ b/test_regress/t/t_math_wide_inc.v @@ -0,0 +1,89 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2023 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 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer i; + reg [6:0] w7; + reg [14:0] w15; + reg [30:0] w31; + reg [62:0] w63; + reg [94:0] w95; + + integer cyc = 0; + + // Test loop + always @ (posedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d\n", $time, cyc); +`endif + cyc <= cyc + 1; + if (cyc==0) begin + // Setup + w7 = {7{1'b1}}; + w15 = {15{1'b1}}; + w31 = {31{1'b1}}; + w63 = {63{1'b1}}; + w95 = {95{1'b1}}; + end + else if (cyc == 1) begin + if (w7++ != {7{1'b1}}) $stop; + if (w7 != {7{1'b0}}) $stop; + if (w7-- != {7{1'b0}}) $stop; + if (w7 != {7{1'b1}}) $stop; + if (++w7 != {7{1'b0}}) $stop; + if (w7 != {7{1'b0}}) $stop; + if (--w7 != {7{1'b1}}) $stop; + if (w7 != {7{1'b1}}) $stop; + + if (w15++ != {15{1'b1}}) $stop; + if (w15 != {15{1'b0}}) $stop; + if (w15-- != {15{1'b0}}) $stop; + if (w15 != {15{1'b1}}) $stop; + if (++w15 != {15{1'b0}}) $stop; + if (w15 != {15{1'b0}}) $stop; + if (--w15 != {15{1'b1}}) $stop; + if (w15 != {15{1'b1}}) $stop; + + if (w31++ != {31{1'b1}}) $stop; + if (w31 != {31{1'b0}}) $stop; + if (w31-- != {31{1'b0}}) $stop; + if (w31 != {31{1'b1}}) $stop; + if (++w31 != {31{1'b0}}) $stop; + if (w31 != {31{1'b0}}) $stop; + if (--w31 != {31{1'b1}}) $stop; + if (w31 != {31{1'b1}}) $stop; + + if (w63++ != {63{1'b1}}) $stop; + if (w63 != {63{1'b0}}) $stop; + if (w63-- != {63{1'b0}}) $stop; + if (w63 != {63{1'b1}}) $stop; + if (++w63 != {63{1'b0}}) $stop; + if (w63 != {63{1'b0}}) $stop; + if (--w63 != {63{1'b1}}) $stop; + if (w63 != {63{1'b1}}) $stop; + + if (w95++ != {95{1'b1}}) $stop; + if (w95 != {95{1'b0}}) $stop; + if (w95-- != {95{1'b0}}) $stop; + if (w95 != {95{1'b1}}) $stop; + if (++w95 != {95{1'b0}}) $stop; + if (w95 != {95{1'b0}}) $stop; + if (--w95 != {95{1'b1}}) $stop; + if (w95 != {95{1'b1}}) $stop; + end + else if (cyc==99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule