Support ++/-- on dotted member variables.

This commit is contained in:
Wilson Snyder 2023-04-07 20:57:17 -04:00
parent 827cbf22c9
commit d67d75282c
8 changed files with 191 additions and 14 deletions

View File

@ -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]

View File

@ -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); }

21
test_regress/t/t_class_inc.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -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);
| ^~

View File

@ -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");

View File

@ -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;

View File

@ -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