From 7be343fd7c885359ac29e50e9732509caf64637d Mon Sep 17 00:00:00 2001 From: Rafal Kapuscik Date: Thu, 8 Oct 2020 07:54:01 -0400 Subject: [PATCH] Support 'this' (#2585). --- Changes | 2 ++ docs/CONTRIBUTORS | 1 + include/verilated_threads.h | 2 +- src/V3AstNodes.h | 4 ++- src/V3LinkDot.cpp | 25 +++++++++-------- src/V3SymTable.h | 1 + test_regress/t/t_class_extends_this.out | 18 ------------- test_regress/t/t_class_uses_this.pl | 21 +++++++++++++++ test_regress/t/t_class_uses_this.v | 34 ++++++++++++++++++++++++ test_regress/t/t_class_uses_this_bad.out | 4 +++ test_regress/t/t_class_uses_this_bad.pl | 23 ++++++++++++++++ test_regress/t/t_class_uses_this_bad.v | 19 +++++++++++++ 12 files changed, 123 insertions(+), 31 deletions(-) create mode 100755 test_regress/t/t_class_uses_this.pl create mode 100644 test_regress/t/t_class_uses_this.v create mode 100644 test_regress/t/t_class_uses_this_bad.out create mode 100755 test_regress/t/t_class_uses_this_bad.pl create mode 100644 test_regress/t/t_class_uses_this_bad.v diff --git a/Changes b/Changes index 27898f4ab..7396621c7 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Support # as a comment in -f files (#2497). [phantom-killua] +**** Support 'this' (#2585). [Rafal Kapuscik] + **** Fix -G dropping public indication (#2561). [Andrew Goessling] **** Fix $urandom_range passed variable (#2563). [nanduraj1] diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 868a3ff45..18c6447e8 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -53,6 +53,7 @@ Philipp Wagner Pieter Kapsenberg Piotr Binkowski Qingyao Sun +Rafal Kapuscik Richard Myers Rupert Swarbrick Sean Cross diff --git a/include/verilated_threads.h b/include/verilated_threads.h index baa8dcb5b..1ff8de64e 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -28,7 +28,7 @@ // VL_THREADED. // Alternatively it is always safe but may harm performance to always // define VL_THREADED for all compiles. -# error "verilated_threads.h/cpp expected VL_THREADED (from verilator --threads)" +#error "verilated_threads.h/cpp expected VL_THREADED (from verilator --threads)" #endif #include diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 845c2927b..cf681fad5 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2359,7 +2359,9 @@ public: if (varScopep()) { return (varScopep() == samep->varScopep()); } else { - return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name()); + return (hiername() == samep->hiername() + && (hiername() != "" || samep->hiername() != "") + && varp()->name() == samep->varp()->name()); } } virtual int instrCount() const override { diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index db98918d0..0bf9e5af6 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1961,8 +1961,18 @@ private: m_ds.m_dotp = nodep; // Always, not just at start m_ds.m_dotPos = DP_SCOPE; - // m_ds.m_dotText communicates the cell prefix between stages - if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) { + if (VN_IS(nodep->lhsp(), ParseRef) && nodep->lhsp()->name() == "this") { + VSymEnt* classSymp = m_ds.m_dotSymp; + do { + classSymp = classSymp->fallbackp(); + } while (classSymp && !VN_IS(classSymp->nodep(), Class)); + m_ds.m_dotSymp = classSymp; + if (!classSymp) { + nodep->v3error("'this' used outside class"); + m_ds.m_dotErr = true; + } + } else if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) { + // m_ds.m_dotText communicates the cell prefix between stages // if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in // dotted reference"); m_ds.m_dotErr=true; } m_ds.m_dotPos = DP_PACKAGE; @@ -2019,21 +2029,14 @@ private: // Generally resolved during Primay, but might be at param time under AstUnlinkedRef UASSERT_OBJ(m_statep->forPrimary() || m_statep->forPrearray(), nodep, "ParseRefs should no longer exist"); - if (nodep->name() == "this") { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: this"); - } else if (nodep->name() == "super") { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: super"); - } + if (nodep->name() == "super") { nodep->v3warn(E_UNSUPPORTED, "Unsupported: super"); } DotStates lastStates = m_ds; bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed if (start) { m_ds.init(m_curSymp); // Note m_ds.m_dot remains nullptr; this is a reference not under a dot } - if (nodep->name() == "this") { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: this"); - m_ds.m_dotErr = true; - } else if (nodep->name() == "super") { + if (nodep->name() == "super") { nodep->v3warn(E_UNSUPPORTED, "Unsupported: super"); m_ds.m_dotErr = true; } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index d72925dbe..6fbdca71f 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -108,6 +108,7 @@ public: void operator delete(void* objp, size_t size) {} #endif void fallbackp(VSymEnt* entp) { m_fallbackp = entp; } + VSymEnt* fallbackp() const { return m_fallbackp; } void parentp(VSymEnt* entp) { m_parentp = entp; } VSymEnt* parentp() const { return m_parentp; } void packagep(AstNodeModule* entp) { m_packagep = entp; } diff --git a/test_regress/t/t_class_extends_this.out b/test_regress/t/t_class_extends_this.out index 364b929f1..87bd383a9 100644 --- a/test_regress/t/t_class_extends_this.out +++ b/test_regress/t/t_class_extends_this.out @@ -1,15 +1,3 @@ -%Error-UNSUPPORTED: t/t_class_extends_this.v:13:11: Unsupported: this - 13 | if (this.value != 1) $stop; - | ^~~~ -%Error: t/t_class_extends_this.v:13:11: Can't find definition of scope/variable: 'this' - 13 | if (this.value != 1) $stop; - | ^~~~ -%Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this - 21 | if (this.value != 2) $stop; - | ^~~~ -%Error: t/t_class_extends_this.v:21:11: Can't find definition of scope/variable: 'this' - 21 | if (this.value != 2) $stop; - | ^~~~ %Error-UNSUPPORTED: t/t_class_extends_this.v:22:11: Unsupported: super 22 | if (super.value != 1) $stop; | ^~~~~ @@ -28,12 +16,6 @@ %Error: t/t_class_extends_this.v:24:7: Can't find definition of scope/variable: 'super' 24 | super.value = 10; | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends_this.v:25:7: Unsupported: this - 25 | this.value = 20; - | ^~~~ -%Error: t/t_class_extends_this.v:25:7: Can't find definition of scope/variable: 'this' - 25 | this.value = 20; - | ^~~~ %Error-UNSUPPORTED: t/t_class_extends_this.v:26:11: Unsupported: super 26 | if (super.value != 10) $stop; | ^~~~~ diff --git a/test_regress/t/t_class_uses_this.pl b/test_regress/t/t_class_uses_this.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_class_uses_this.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 2020 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_uses_this.v b/test_regress/t/t_class_uses_this.v new file mode 100644 index 000000000..d1a30b01a --- /dev/null +++ b/test_regress/t/t_class_uses_this.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 Rafal Kapuscik +// SPDX-License-Identifier: CC0-1.0 +// +class foo; + bit [3:0] addr; + function void set (bit [3:0] addr); + begin : body + this.addr = addr; + end : body + endfunction +endclass + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + foo bar; + foo baz; + initial begin + bar = new(); + baz = new(); + bar.set(4); +`ifdef TEST_VERBOSE + $display(bar.addr); + $display(baz.addr); +`endif + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_uses_this_bad.out b/test_regress/t/t_class_uses_this_bad.out new file mode 100644 index 000000000..05075f46a --- /dev/null +++ b/test_regress/t/t_class_uses_this_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_class_uses_this_bad.v:15:12: 'this' used outside class + 15 | this.addr = 2; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_class_uses_this_bad.pl b/test_regress/t/t_class_uses_this_bad.pl new file mode 100755 index 000000000..953874c82 --- /dev/null +++ b/test_regress/t/t_class_uses_this_bad.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 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( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +#execute( +# check_finished => 1, +# ); + +ok(1); +1; diff --git a/test_regress/t/t_class_uses_this_bad.v b/test_regress/t/t_class_uses_this_bad.v new file mode 100644 index 000000000..1db9fade6 --- /dev/null +++ b/test_regress/t/t_class_uses_this_bad.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 Rafal Kapuscik +// SPDX-License-Identifier: CC0-1.0 +// + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + bit [3:0] addr; + initial begin + this.addr = 2; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule